Archive

Posts Tagged ‘Spring MVC’

Spring MVC – Sitemesh 3 Integration

October 9th, 2012 4 comments

Sitemesh is a web page layout/decoration framework that makes it easy to create applications with consistent layout/look and feel. I have used Sitemesh 2 for years and absolutely love it. Sitemesh 3 is a complete rewrite of the framework and has huge performance benefits. A full list of the new features is listed here. In this blog I will share the steps needed for integrating Sitemesh 3 in a Spring MVC application.

1. We start by creating a Maven based web application using my Spring archetype. Here is the generated pom.xml file with dependencies:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.inflinx.blog</groupId>
	<artifactId>sitemesh3</artifactId>
	<name>sitemesh3</name>
	<packaging>war</packaging>
	<version>1.0.0</version>
	
	<properties>
		<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			 <exclusions>
		         <exclusion>
		            <groupId>commons-logging</groupId>
		            <artifactId>commons-logging</artifactId>
		         </exclusion>
      		</exclusions>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		
		<dependency>
		     <groupId>cglib</groupId>
		     <artifactId>cglib</artifactId>
		     <version>2.2.2</version>
		     <scope>compile</scope>
		</dependency>
		
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
		
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.0.0.GA</version>
			<scope>compile</scope>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>4.2.0.Final</version>
			<scope>compile</scope>
			<exclusions>
				<exclusion>
					<artifactId>slf4j-api</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
			</exclusions>
		</dependency>
	            
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<dependency>
      		<groupId>org.slf4j</groupId>
	      	<artifactId>jcl-over-slf4j</artifactId>
	      	<version>1.5.8</version>
  	 	</dependency>
   		<dependency>
      		<groupId>org.slf4j</groupId>
      		<artifactId>slf4j-api</artifactId>
      		<version>1.5.8</version>
   		</dependency>
	   <dependency>
	      <groupId>org.slf4j</groupId>
	      <artifactId>slf4j-log4j12</artifactId>
	      <version>1.5.8</version>
	   </dependency>
	
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
			  
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>            
		
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.0</version>
	    	<scope>provided</scope>
		</dependency>				
 
	</dependencies>
    <build>
        <plugins>
        	<plugin>
			    <groupId>org.mortbay.jetty</groupId>
			    <artifactId>maven-jetty-plugin</artifactId>
			</plugin>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


2. To the web application we add the following Sitemesh 3 maven dependency:

	
		<dependency>
			<groupId>org.sitemesh</groupId>
			<artifactId>sitemesh</artifactId>
			<version>3.0-alpha-2</version>	
		</dependency>
	
	

3. We then create a Sitemesh decorator containing common layout/look and feel that all the pages should have. Create a main.jsp file under WEB-INF/decorator folder with the following contents:


<html>
  <head>
    <title><sitemesh:write property='title'/></title>
    <sitemesh:write property='head'/>
  </head>
  
  <body>
    <div style="color: red">
    	<sitemesh:write property='body'/>
    </div>
  </body>
  
</html> 

4. The next step is to let Sitemesh know about this decorator. This is done via sitemesh.xml file located under WEB-INF folder.

	<?xml version="1.0" encoding="UTF-8"?>
	<sitemesh>
 		<mapping path="/*" decorator="/WEB-INF/decorator/main.jsp"/>
	</sitemesh>

In the above configuration file, the mapping element tells Sitemesh to apply main.jsp decorator to all the pages. Other configuration options provided by Sitemesh 3 are listed here.

5. The final step in the integration is to add Sitemesh filter to web.xml.

  	<filter>
    	<filter-name>sitemesh</filter-name>
    	<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
  	</filter>

 	<filter-mapping>
    	<filter-name>sitemesh</filter-name>
    	<url-pattern>/*</url-pattern>
  	</filter-mapping>

When you run the application you should see the red font color applied due to main.jsp decorator:

Sitemesh App

Categories: SiteMesh, Spring Tags: ,

Spring Async And Future – Report Generation Example

September 9th, 2012 5 comments

Spring 3.0 introduced the @Async annotation for executing tasks asynchronously. The asynchronous capabilities are highly useful in situations where we need to execute a long running task before allowing user input. For example, every time we open a Gmail message with attachment, Gmail performs a anti-virus scan before showing the download link to the user.

In this blog post, I will kick off a long running report asynchronously. Then I will use JQuery to periodically check if the report has been created. When the report is finally available, a link to the report is shown to the user.

We start by creating a ReportService as shown below. The generateReport method returns java.util.concurrent.Future interface. This interface allows the caller to retrieve the execution result at later time.

package com.inflinx.blog.springfuture.service;

import java.util.concurrent.Future;

import com.inflinx.blog.springfuture.domain.Report;

public interface ReportService {
	
	public Future generateReport();
	
}

The report service implementation is shown below. We simulate the “long running process” by calling the sleep method on the current thread. The method returns AsyncResult instance with the newly created Report as pass through value.


package com.inflinx.blog.springfuture.service;

import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import com.inflinx.blog.springfuture.domain.Report;

@Service("reportsService")
public class ReportServiceImpl implements ReportService {

	@Async
	public Future generateReport() {
		
		try {
			Thread.sleep(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		Report report = new Report();
		report.setName("New Report");
		report.setDescription("New Report Description");
		
		return new AsyncResult(report);
	}
	
}

We complete the service layer implementation by adding the following Spring configuration file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:annotation-config />
    
    <context:component-scan base-package="com.inflinx.blog.springfuture.service" />
       
    <task:annotation-driven />
       
</beans>       		

Now that we have completed our service layer, let’s create an MVC Controller that uses the ReportService to create a new report. The new report is then saved in the user’s session.

package com.inflinx.blog.springfuture.web.controller;

import java.util.concurrent.Future;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.inflinx.blog.springfuture.domain.Report;
import com.inflinx.blog.springfuture.service.ReportService;

@Controller
public class HomeController 
{
	@Autowired
	@Qualifier("reportsService")
	private ReportService reportService;
	
	@RequestMapping(value="/home.html", method=RequestMethod.GET)
	public String showHome(HttpSession session) 
	{
		Future report = reportService.generateReport();
		
		session.setAttribute("report", report);
		
		return "home";
	}	
}

To this controller, we then add a method that returns the status of the report generation. The method implementation simply retrieves the Future object and invokes the isDone method to check the status of the running task.

	@RequestMapping("/reportstatus.json")
	@ResponseBody
	public String reportStatus(HttpSession session) {
		Future report = (Future)session.getAttribute("report");
		
		if(report.isDone()) {
			System.out.println("Report Generation Done");
			return "COMPLETE";
		}
		else {
			System.out.println("Still Working on Report");
			return "WORKING";
		}
	}

We then add a method to the controller that shows the generated report as shown below:


@RequestMapping(value="/report.html", method=RequestMethod.GET)
	public String showReport(HttpSession session, Model model) throws InterruptedException, ExecutionException 
	{
		Future report = (Future)session.getAttribute("report");
		
		Report r = report.get();
		model.addAttribute("report", r);
		
		return "report";
	}

The report.jsp view returned by the above method is shown below:


<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Generated Report
</h1>

 Name: ${report.name} <br />
 Description: ${report.description}

</body>
</html>

We finally tie everything in the home.jsp view that gets returned by the showHome method. In the home.jsp, we use JQuery’s setInterval method to call the reportstatus.json URL every two seconds. Once we get the “COMPLETE” response, we show the download link.


<html>
<head>
	<title>Home</title>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

<script type="text/javascript">
	
	$(document).ready(function() {
		
		// Check The Status Every 2 Seconds
		var timer = setInterval(function() {
			
			$.ajax({
				  url: 'reportstatus.json',
				  success: function(data) {
					
					if(data === 'COMPLETE') {
						$('#reportLink').html("<a target='_target' href='report.html'>Download Report</a>");	
						clearInterval(timer);
					}
				  }
			});
			
		}, 2000);
	});
		
</script>

</head>
<body>
<h1>
  Report Generator
</h1>

<div id="reportLink">Please Wait While Your Report Is Being Generated</div>

</body>
</html>

Here is a screenshot of the application’s home.jsp page:

Here is a screenshot after the report has been generated:

The screenshot of the newly generated report:

Categories: Spring Tags: , ,

Integrating CAPTCHA Into Spring MVC Web Applications

May 25th, 2012 1 comment

Integrating CAPTCHA in an application involves two simple steps:

  1. Display CAPTCHA Widget
  2. Validate CAPTCHA Reponse

In this blog post, I will be using Google’s reCAPTCHA. Before we can start using reCAPTCHA, we need to sign up for API keys.

Obtaining reCAPTCHA keys

1. Go to the reCAPTCHA Key Signup Page and login using your Google Account.

Enter the your domain name and hit “Create Key”. The generated keys by default are restricted to the specified domain. However, all keys will work on the localhost domain, making it easy to test during development.

Captcha Creation



Make a note of the generated public and private keys. We need both keys in order to generate CAPTCHA and verify response.

Display CAPTCHA Widget

reCAPTCHA provides a Java Library wrapper that makes CAPTCHA generation/verification easier. Maven users can get the jar file with the following dependency:

   <dependency>
		<groupId>net.tanesha.recaptcha4j</groupId>
		<artifactId>recaptcha4j</artifactId>
		<version>0.0.7</version>
	</dependency>

With the dependency added, generating the CAPTCHA Widget simply involves placing the below scriptlet in a JSP page:

	<%
		ReCaptcha captcha = ReCaptchaFactory.newReCaptcha("PUBLIC_KEY", "PRIVATE_KEY", false);
		out.print(captcha.createRecaptchaHtml(null, null));
    %>	

In the above code, we first create an instance of ReCaptcha by passing in the generated public and private key. The third parameter instructs if a noscript tag should to be placed around the generated HTML.

Since, I don’t like using Scriptlets in my JSP pages, I will create a reusable JSP tag that wraps the above code. We start out by creating a CaptchaTag class as shown below:


package com.inflinx.blog.web.tag;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import org.apache.commons.lang.StringUtils;

import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaFactory;

public class CaptchaTag extends SimpleTagSupport
{
	private String publickey;
	private String privatekey;
	private String themeName;
	
	@Override
	public void doTag() throws JspException, IOException 
	{
		ReCaptcha captcha = ReCaptchaFactory.newReCaptcha(publickey, privatekey, false);
		Properties properties = new Properties();
		
		if(StringUtils.isNotEmpty(themeName))
		{
			properties.put("theme", themeName);
		}
		
		String captchaHtml = captcha.createRecaptchaHtml(null, properties);
		getJspContext().getOut().write(captchaHtml);
	}

	public String getThemeName() {
		return themeName;
	}

	public void setThemeName(String themeName) {
		this.themeName = themeName;
	}

	public String getPublickey() {
		return publickey;
	}

	public void setPublickey(String publickey) {
		this.publickey = publickey;
	}

	public String getPrivatekey() {
		return privatekey;
	}

	public void setPrivatekey(String privatekey) {
		this.privatekey = privatekey;
	}
}

The above tag takes has three attributes: public key, private key and theme name. The theme option can be used to control the reCAPTCHA widget’s look and feel. Possible values include: “red”, “white”, “blackglass” or “clean”. The default is the red.

To complete the implementation of the tag, lets create a captcha.tld file under WEB-INF/tlds folder with the following contents:

<taglib xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1">
     
    <tlibversion>1.0</tlibversion>
    <jspversion>2.1</jspversion>
    <shortname>CaptcahTags</shortname>
    <uri>http://blog.inflinx.com</uri>
    <info>Captcha Tags</info>
 
    <tag>
        <name>captcha</name>
        <tagclass>com.inflinx.blog.web.tag.CaptchaTag</tagclass>
        <bodycontent>empty</bodycontent>
        <info>Generates Captcha Widget</info>
        <attribute>
             <name>publickey</name>
             <required>true</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
		<attribute>
             <name>privatekey</name>
             <required>true</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
		<attribute>
             <name>themeName</name>
             <required>false</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
    </tag>
 
</taglib>

With all this in place, update the JSP page with the following code to display the CAPTCHA Widget:


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib prefix="captcha" uri="/WEB-INF/tlds/captcha.tld" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<html>
<head>
	<title>Home</title>
</head>
<body>

<form method="post">

	<captcha:captcha themeName="clean" publickey="YOUR_PUBLIC_KEY" privatekey="YOUR_PRIVATE_KEY"/>
	
</form>


</body>
</html>

Upon running the code, you should see a CAPTCHA similar to the image below:

Captcha In Action

Validate CAPTCHA Reponse

In order to valdiate the CAPTCHA response, we need to modify the POST method of the receiving controller as shown below:

@RequestMapping(method = RequestMethod.POST)
	public String processSubmit(HttpServletRequest request, Model model)
	{
		ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
        reCaptcha.setPrivateKey("YOUR_PRIVATE_KEY");
        
		String remoteAddr = request.getRemoteAddr();
        String challengeField = request.getParameter("recaptcha_challenge_field");
        String responseField = request.getParameter("recaptcha_response_field");
        ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(remoteAddr, challengeField, responseField);

        if(!reCaptchaResponse.isValid())
        {
        	model.addAttribute("invalidCaptcha", "Captcha Is Invalid");
        	return "home";
        }
        
        return "success";
	}

In the above code, we start by creating a ReCaptchaImpl instance and pass in the Private key. The reCaptcha widget generates two fields “recaptcha_challenge_field”, “recaptcha_response_field” that are needed to verify the response. We pass in those two fields along with the IP Address of the client to get a response.

For invalid responses, we set a model attribute to indicate the error. Now, in a Spring MVC application where you are using a command object for the form, you can add an error instance instead:

		if(!reCaptchaResponse.isValid())
        {
        	errors.reject("captcha.invalid");
        }

Spring MVC 3.1.1 Archetype

May 18th, 2012 No comments

I have created a new Maven archetype for creating Spring MVC 3.1.1 based web applications.

To install the archetype, download the file and simply run the following command:

mvn install:install-file -DgroupId=com.inflinx.blog -DartifactId=spring-mvc-web-archetype -Dversion=1.0.0 -Dpackaging=jar -Dfile=spring-mvc-web-archetype-1.0.0.jar

The above command needs to be run from the directory where you have placed the downloaded file.


To use the installed archetype run the following command from your project folder:

mvn archetype:generate -DarchetypeGroupId=com.inflinx.blog -DarchetypeArtifactId=spring-mvc-web-archetype -DarchetypeVersion=1.0.0 -DgroupId=com.inflinx.blog -DartifactId=YOUR_PROJECT_NAME -DartifactVersion=1.0.0 -DinteractiveMode=false

If you are interested in creating your own archetypes refer to my Creating Maven Archetypes – Spring MVC Example blog post.

Categories: Maven, Spring Tags: ,

Creating Maven Archetypes – Spring MVC Example

April 16th, 2010 7 comments

Maven Archetypes are project templates that allow users easily create new projects. Maven Archetypes are great way to share best practices and enforce consistency beyond Maven’s standard directory structure. For example, an organization can provide its developers an archetype bundled with company’s approved CSS and JavaScript libraries.

Recently, I have been creating a lot of Spring MVC based projects and each time I do, I copy a lot of information (configuration files, css files, dependency information etc) from an existing project. Following the DRY principles, I decided to create several Spring MVC based archetypes that can help me bootstrap my projects quickly. In this post I will share my experiences creating and using a new Maven Archetype.

Maven provides several ways to create a new archetype as described here. Since I have an existing Spring MVC project, I will be using the archetype:create-from-project goal.

 

Creating Archetype

Step 1: Identify the Maven Project that would be used as prototype for the archetype. Make sure it has only the resources (configuration, properties and Java files) that you would like to be part of the archetype. It is recommended to remove IDE specific files (.project, .classpath etc) from the project directory. Here is the spring-mvc-prototype project that I will be using:

Prototype Project Layout

Prototype Project Layout

Step 2: Using command line, navigate to the project folder spring-mvc-prototype and run the following command:

	mvn archetype:create-from-project
	

Upon completion of the command, you should see the message “Archetype created in target/generated-sources/archetype”. The newly created archetype is now under spring-mvc-prototype/target/generated-sources/archetype

Step 3: The next step is to move the newly created archetype into a separate folder so that it can be tweaked and published. I have moved the content inside the spring-mvc-simple-archetype folder.

Archetype Directory Structure

Archetype Directory Structure

Step 4: Modify the artifactId in the archetype’s pom.xml located at the root of spring-mvc-simple-archetype folder.

Existing pom.xml:

  com.inflinx.blog
  spring-mvc-prototype-archetype
  1.0.0-SNAPSHOT
  maven-archetype
  spring-mvc-prototype-archetype

Modified pom.xml:

	com.inflinx.blog
	spring-mvc-simple-archetype
	1.0.0-SNAPSHOT
	maven-archetype
	spring-mvc-simple-archetype	

Step 5: Modify the finalName in the resource’s pom.xml file located at spring-mvc-simple-archetypesrcmainresourcesarchetype-resources.

		 
		spring-mvc-prototype

		
		${artifactId}
	

During project creation, maven will replace the ${artifactId} expression with the user supplied artifactId value.

Step 6: When creating a project from an archetype, Maven prompts the user for a package name. Maven will create the package in the source folder (srcmainjava) of the project being created and will move the contents under archetype-resourcessrcmainjava into the package.

Maven File Copy

Maven File Copy

While generating the “testproject” above, the user specified the package “com.inflinx.blog.testproject”. So the SomeJavaClass.java file got moved to the root of the package and the HomeController.java got moved under the web.controller subpackage.

Step 7: The next step is to verify that the generated archetype.xml (located under src/main/resources/META-INF/maven) has all the files listed and they are located in the right directories. For example, the HomeController is located under archetype-resources/src/main/java/web/controller/HomeController.java. So there should be an entry under sources in the archetype.xml that looks something like this:

	  
	    src/main/java/com/inflinx/blog/mvcprototype/web/controller/HomeController.java
	  

Step 8: Modify the configuration files to correctly use the ${package} variable. For example, the webContext.xml file is modified so that the controllers located under web.controller sub package are picked up:

		
	

Step 9: The final step in creating the archetype is to run the following on command line inside the folder spring-mvc-simple-archetype:

	mvn clean install
	

 

Using the archetype

Once the archetype is installed, there are several ways to create a project from it.

Generate goal: Create an empty folder and run the following command:

 		
 		mvn archetype:generate -DarchetypeCatalog=local
		

This goal would scan the local catalog for archetypes and prompts the user to select an archetype to use.

Command Line Archetype Usage

Command Line Archetype Usage

Once the user enters 1, Maven selects the spring-mvc-simple-archteype for project creation.

m2Eclipse Plugin: If you are an Eclipse user, use the New Project Wizard and search and select the spring-mvc-simple-archetype.

m2Eclipse Archetype Usage

m2Eclipse Archetype Usage

Using m2Eclipse plugin is a real time saver since it creates the associated IDE specific configuration files.

 

Adding Custom Properties

On some projects, additional information such as user name or web application context might be needed to generate the project. Here are the steps to prompt the user for information and use it:

Step 1: Add to the archetype-metadata.xml file located under spring-mvc-simple-archetypesrcmainresourcesMETA-INFmaven a required properties entry:

	
    	
  	

Step 2: Modify the file where you would like to use the information. Below, I have modified weblogic.xml to have the context root value the user has provided:

 
	
		
	        true
	    
		${contextRoot}	
	

When the user uses the archetype with the above modifications, he will be prompted for the contextRoot.

Custom Attribute Usage In Action

Custom Attribute Usage In Action

JSR 303 Bean Validation Using Spring 3

March 10th, 2010 26 comments

The JSR 303 specification provides a metadata model for JavaBean validation. The validation API provides a variety of annotations that makes validation easy at any layer. In this post I will demo Spring 3′s support for JSR 303 in the web layer. You can download the code here (eclipse project).

The first part of the post talks about creating a simple bookstore admin application using Spring MVC. The second part of the post will add JSR 303 validation. If you are an experienced Spring developer, you can safely skip to the second part. The final part will show how to customize the validation error messages.

1. Online Bookstore Admin Application

The admin application will be designed to allow administrators enter information about new books. Here are the steps that implement this requirement:

Step 1. Create a web project and add all the required jars
I will be using Eclipse’s and here is a list of the required jars that need to be in the classpath:

org.springframework.asm-3.0.1.RELEASE.jar
org.springframework.beans-3.0.1.RELEASE.jar
org.springframework.context-3.0.1.RELEASE.jar
org.springframework.context.support-3.0.1.RELEASE.jar
org.springframework.core-3.0.1.RELEASE.jar
org.springframework.expression-3.0.1.RELEASE.jar
org.springframework.test-3.0.1.RELEASE.jar
org.springframework.web-3.0.1.RELEASE.jar
org.springframework.web.servlet-3.0.1.RELEASE.jar
commons-collections-3.1.jar
hibernate-validator-4.0.2.GA.jar
jcl-over-slf4j-1.5.10.jar
joda-time-1.6.jar
jstl-1.2.jar
log4j.jar
slf4j-api-1.5.8.jar
slf4j-log4j12.jar
validation-api-1.0.0.GA.jar

Step 2. Create a web-Context.xml file under WEB-INF folder to hold web layer spring bean configuration. Here are the contents of the file:

		
		<?xml version="1.0" encoding="UTF-8"?>
		<beans xmlns="http://www.springframework.org/schema/beans"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xmlns:context="http://www.springframework.org/schema/context"
			xmlns:mvc="http://www.springframework.org/schema/mvc"
			xsi:schemaLocation="
				http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
				http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
			
			<!-- Enable annotation driven controllers, validation etc... -->
			<mvc:annotation-driven />
			
			<!-- Controllers package -->
			<context:component-scan base-package="com.inflinx.blog.bookstore.web.controller" />
		
			<!-- JSP page location -->
			<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
				<property name="suffix" value=".jsp"/>
			</bean>
			 	
		</beans>
			
	

Step 3. Add Spring MVC Dispatcher Servlet to web.xml file. In the declaration below, Spring MVC will handle all URL requests to html pages.

		
		<?xml version="1.0" encoding="UTF-8"?>
		<web-app version="2.5" 
			xmlns="http://java.sun.com/xml/ns/javaee" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
			xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

		  <servlet>
				<servlet-name>bookstore</servlet-name>
				<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
				<init-param>
					<param-name>contextConfigLocation</param-name>
					<param-value>/WEB-INF/web-Context.xml</param-value>
				</init-param>
				<load-on-startup>1</load-on-startup>
			</servlet>
		
			<servlet-mapping>
				<servlet-name>bookstore</servlet-name>
				<url-pattern>*.html</url-pattern>
			</servlet-mapping>
		
		</web-app>
		
	

Step 4. Create a Book domain object to hold information about a book:

		package com.inflinx.blog.bookstore.domain;

		public class Book
		{
			private String name;
			private String description;

			public String getName()
			{
				return name;
			}
			public void setName(String name)
			{
				this.name = name;
			}
			public String getDescription()
			{
				return description;
			}
			public void setDescription(String description)
			{
				this.description = description;
			}

			@Override
			public String toString()
			{
				return "Name: " + name + ", Description: " + description ;
			}
		}	
	

Step 5. Create a BookFormController to prepare the form and process form submission

		package com.inflinx.blog.bookstore.web.controller;
		
		import java.util.Map;
		
		import org.springframework.stereotype.Controller;
		import org.springframework.web.bind.annotation.RequestMapping;
		import org.springframework.web.bind.annotation.RequestMethod;
		
		import com.inflinx.blog.bookstore.domain.Book;
		
		@Controller
		@RequestMapping("/book.html")
		public class BookFormController
		{
			// Display the form on the get request
			@RequestMapping(method=RequestMethod.GET)
			public String showForm(Map model)
			{
				Book book  = new Book();
				model.put("book", book);
				return "form";
			}
			
		}
	
	

Step 6. Create form.jsp page with a form to capture book details:

	
		<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
		<html>
			<head></head>
			<body>
				<form:form method="post" action="book.html" commandName="book">
					<table>
						<tr>
							<td>Name:</td> <td><form:input path="name" /></td>
						</tr> 
						<tr>
							<td>Description:</td> <td><form:textarea path="description"/></td>
						</tr>
						</table>
					<input type="submit" value="Create" />
				</form:form>
			</body>
		</html>
	
	
	

The form will be submitted to the book.html page.

Step 7. Modify BookFormController to read the submitted data and process it.

		
		// Process the form. 
		@RequestMapping(method=RequestMethod.POST)
		public String processForm(Book book, Map model)
		{
			// Persistence logic to save the book will go here

			// Add the saved book to the model
			model.put("book", book);
			return "result";
		}	
	

Step 8. Create a result.jsp page to display the form submission result:

		<html>
			<body>
				${book.name} is stored in the database
			</body>
		</html>
	

Deploy the application and go to http://<yourserver:port>/bookstore/book.html. The page should present a form shown below:

Form

Form

Enter the book name “Test Book” and submit the form. You should see a screen that looks similar to image below:

Form Submission Result

Form Submission Result

 

2 Adding JSR 303 validation

Consider the following validation requirements to the book class:
a. Name and Description cannot be null or blank
b. Description cannot be more than 50 characters

Here are the steps to add the above validation requirements:

Step 1. Add @NotEmpty and @Size annotations to the name and description files of the Book class

		public class Book
		{
			@NotEmpty
			private String name;
			
			@Size(min=1, max=50)
			private String description;
			
			// Getters and setters here	
		}
	

NotEmpty annotation is not part of JSR 303 specification. It is part of Hibernate Validator framework which is the reference implementation for JSR 303.

Step 2. Modify BookFormController to have Spring validate the submitted data. This is done by adding a @Valid annotation before the book method parameter. The result of the validation can be accessed using the BindingResult method parameter.

		// Process the form. 
		@RequestMapping(method=RequestMethod.POST)
		public String processForm(@Valid Book book, BindingResult result, Map model)
		{
			if(result.hasErrors())
			{
				return "form";
			}
			// Persistence logic to save the book will go here

			// Add the saved book to the model
			model.put("book", book);
			return "result";
		} 	
 	

Step 3. Modify the form.jsp so that error messages can be displayed:

 		<form:form method="post" action="book.html" commandName="book">
					<table>
						<tr>
							<td>Name:</td> <td><form:input path="name" /></td> <td><form:errors path="name" /></td>
						</tr> 
						<tr>
							<td>Description:</td> <td><form:textarea path="description"/></td> <td><form:errors path="description" /></td>
						</tr>
						</table>
					<input type="submit" value="Create" />
		</form:form>
 	

Redeploy the application and when you submit an empty form, you should see validation failure messages next to the fields:

Validation Failed

Validation Failed

 

3 Customizing error messages

The validation failure messages in the image above are default to the framework. To make custom error messages appear follow these steps:

Step 1. Create a messages.properties file under the WEB-INF folder. Add the following messages:

   		NotEmpty.book.name=Name is a required field
		Size.book.description=Description must be between 1 and 50 characters
   	

Each message above follows this convention:

<CONSTRAINT_NAME>.<COMMAND_NAME>.<FIELD_NAME>

Step 2. Let Spring know about the newly created properties file. This is done by modifying the web-Context.xml file to include this bean declaration:

   	
			
	
    

Redeploy the application and submit an empty form. This time you should see custom error messages appear next to the fields:

Custom Validation Failed Messages

Custom Validation Failed Messages

 

Download the source code for this post here. The application is tested on Glassfish 3.0 and WebLogic 10.3.

 

Theming Websites using Spring MVC

October 8th, 2009 8 comments

Many websites today allow their users to theme or change the look and feel of their sites. Gmail for example, currently provides over 34 themes to skin the mail interface. Themes can make websites more interactive and put the user in the driver seat when it comes to experiencing the site.

Conceptually, a theme is a collection of static resources such as stylesheets and images. When a user picks a theme, the theme’s styles and images dynamically gets associated with the site. In this post, I will create a simple Spring MVC Web application and show how Spring MVC can be used to manage theme resources easily. If you have used Spring MVC quite a bit, you can safely skip to Step 5.

Step 1: The first step in the process is to create a Spring MVC web project. Following maven conventions, here is the directory structure of the project:

Spring MVC Theme Project Structure

Spring MVC Theme Project Structure

Step 2: The next step is to add the required jars. Here is the dependency list that needs to be added to the pom.xml file:

		
		<dependencies>
			<dependency>
			    <groupId>org.springframework</groupId>
			    <artifactId>spring-webmvc</artifactId>
			    <version>2.5.6.SEC01</version>
			    <scope>compile</scope>
        		</dependency>	
        
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>1.2.14</version>
				<scope>compile</scope>
			</dependency>
		</dependencies>			
	

This would add the following jars to the project:

Spring MVC Theme Jars

Spring MVC Theme Jars

Step 3: The next step is to add Spring “goodness” to the project. This is done by adding Spring MVC dispatcher servlet definition to web.xml:

		<!-- Spring MVC Servlet -->
		<servlet>
			<servlet-name>springthemes</servlet-name>
			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
			<load-on-startup>1</load-on-startup>		
		</servlet>
			
		<servlet-mapping>
			<servlet-name>springthemes</servlet-name>
			<url-pattern>*.html</url-pattern>
		</servlet-mapping>	
	

The Spring MVC Dispatcher Servlet by default looks for the <context-name>-servlet.xml file for Web Tier bean definitions. Create a file called springthemes-servlet.xml under WEB-INF folder with the following information:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	
	<!-- Scan for controllers -->
	<context:component-scan base-package="com.inflinx.blog.springthemes.web.controller" />
	
	<!-- Views are jsp pages defined directly in the root -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:suffix=".jsp"/>
    
</beans>

Step 4: To keep things simple, create a controller class called HomeController that simply redirects to the home.jsp page. Here is the HomeController class definition:

	package com.inflinx.blog.springthemes.web.controller;

	import org.springframework.stereotype.Controller;
	import org.springframework.web.bind.annotation.RequestMapping;
	import org.springframework.web.bind.annotation.RequestMethod;

	@Controller
	@RequestMapping("/home.html")
	public class HomeController
	{
		@RequestMapping(method = RequestMethod.GET)
		public String showHome()
		{
			return "home";
		}
	}

Here is the home.jsp file:

<html>
	<head>
		<title>Welcome to Spring Themes</title>	
	</head>
	
	<body>
		Hello Visitor!!
	</body>
</html>

If you deploy the application and hit http://<server:port>/springthemes/home.html, you should see a page that looks like this:

Spring MVC Theme Default Page

Spring MVC Theme Default Page

Now that we are successfull in creating a simple Spring MVC project, lets add two themes to it – dark theme and bright theme. The site automatically gets the “dark” theme during nights and the “bright” theme during day time.

Step 5: In this step, lets create the css files (one of the many static resources that a theme can have) associated with each theme. Here are the css files (I placed them under the themes folder):

dark.css

	body {
		font-size:13px; 
		text-align:center;
		color: white;
		background-color: black
	}

bright.css

	body {
		font-size:9px; 
		text-align:center;
		color: blue;
		background-color: white;
}

Step 6: The next step is to define the themes. The default way to do this in Spring MVC is to use one property file for each theme. Here are the two theme definitions:

#dark theme properties file dark.properties
css=themes/dark.css
page.title=Welcome to Dark Theme
welcome.message=Hello Visitor!! Have a Good night!!

#bright theme properties file bright.properties
css=themes/bright.css
page.title=Welcome to Bright Theme
welcome.message=Hello Visitor!! Have a Good day!!

Step 7: Now that we have defined the themes, we need to tell Spring where to find them. This is done using a ThemeSource. Add the following line to the springthemes-servlet.xml file:

   

Step 8: Spring needs to know what theme to use when a request is made. This is done using a ThemeResolver. Spring provides three theme resolvers out of the box: FixedThemeResolver, SessionThemeResolver, CookieThemeResolver that are sufficient for most use cases. However, our site needs to inherit a theme based on the time, we will create a new theme resolver called DarkAndBrightThemeResolver:

package com.inflinx.blog.springthemes.web.resolver;

import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.theme.AbstractThemeResolver;

public class DarkAndBrightThemeResolver extends AbstractThemeResolver
{
	@Override
	public String resolveThemeName(HttpServletRequest arg0)
	{	
		return isNight() ? "dark" : "bright";
	}

	// Pretty lame implementation
	private boolean isNight()
	{
		return new Random().nextBoolean();
	}
	
	@Override
	public void setThemeName(HttpServletRequest arg0, HttpServletResponse arg1, String arg2)
	{	
	}
}		

Add the newly created theme resolver definition to the springthemes-servlet.xml file:

   

Step 9: The final step is use modify the view to use the theme. This is done using tag. Make the following changes to home.jsp page:

  <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
  <html> 
  	<head>
  		<link  rel="stylesheet" href='<spring:theme code="css"/>' type="text/css" />
  		<title><spring:theme code="page.title"/></title>	
  	</head>
  	<body>
  		<spring:theme code="welcome.message" />
  	</body>
  </html>

Now, redeploy the application and as you refresh the URL, you should randomly see the site switch between the two themes. Here is the site with the two themes:

Dark Theme

Dark Theme



Bright Theme

Bright Theme

Categories: Spring Tags: ,