JSR 303 Bean Validation Using Spring 3

March 10th, 2010

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: ..

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.

 

Balaji Solutions Log, Spring , ,

weblogic.xml deployment descriptor

December 31st, 2009

If you are using 10.3.0 version of Weblogic here is a sample weblogic.xml file with correct schema information:





	YOUR_APPLICATION_CONTEXT_NAME


And here is a sample weblogic.xml file for version 10.3.2 version:





     	YOUR_APPLICATION_CONTEXT_NAME


If you use the wrong version file, you might end up with exceptions like this:

com.bea.xml.XmlException: failed to load java type corresponding to e=weblogic-web-app@http://xmlns.oracle.com/weblogic/weblogic-web-app
at com.bea.staxb.runtime.internal.UnmarshalResult.getPojoBindingType(UnmarshalResult.java:361)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:316)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:326)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineRootType(UnmarshalResult.java:307)
at com.bea.staxb.runtime.internal.UnmarshalResult.unmarshalDocument(UnmarshalResult.java:158)
Truncated. see log file for complete stacktrace

Balaji Solutions Log

Redirecting from Wordpress.com

October 14th, 2009

The blog post WordPress.com to Wordpress.org is an excellent reference if you are planning on redirecting your existing Wordpress.com blog to a blog on a domain you own. However, it does not talk about redirecting a Wordpress.com blog to a blog on a sub-domain. In this post, I want to share the steps I followed to redirect my http://onerandomthought.wordpress.com blog to http://blog.inflinx.com hosted on Go Daddy. I am assuming that you have already moved all your posts from your Wordpress.com blog to your new blog and verified that Permalinks on both blogs match.

 

Step 1: Log into http://wordpress.com and go to the Domains in the Dashboard. Under “Add a Domain” enter your subdomain.domain.com and hit “Add domain to blog”:
 Add a Domain

 

Wordpress would come back complaining that there is a possible problem with the domain, It recommends that we add a CNAME entry pointing to Wordpress.com blog in registrar before proceeding:
Problem Adding Domain

 

Step 2: Log into your godaddy.com account and launch Domain Manager. Select the domain name in the list of domains:
Go Daddy Select Domain

 

On the resulting page, click on the “Total DNS Control”:
Total DNS Selection

 

Inside the “Total DNS Control”, before I could add a CNAME entry for “blog”, I had to delete the existing “blog” record under A (HOST). The delete option is listed under “Actions”. Make sure you save the IP address that blog is pointing to:
 Delete Sub Domain

 

The next step is to create a new CNAME entry. Click on the Add New CNAME Record and fill the resulting form. Then, hit Ok and it would create a new CNAME record:
Add CNAME Record

 

Step 3: Repeat Step 1 and now wordpress.com should allow you to register the domain:
Wordpress - Add a sub domain

 

Follow the next steps and purchase the credits to register the domain:
Purchase Domain Mapping

 

Once the purchase, is complete, All the traffic for blog.inflinx.com should now be redirected to onerandomthought.wordpress.com.
After Domain Mapping Purchase
You might need to clear the DNS Cache to verify the redirect. On Max OSX, this is done through the command: dscacheutil -flushcache

 

Step 4: Now that we have this going, we just need to reverse the redirection behavior. In the Wordpress.com, select the radio button next to your sub domain and hit “Update Primary Domain”. Then, go back to the “Total DNS Control” and undo what was done in Step 2. This involves first deleting the CNAME entry and adding the blog entry under A(Host). Make sure you are using the same IP address you saved in step 2.

 

Once Step 4 is completed, all the Wordpress.com blog traffic should now be sent over to the blog on your sub domain.

Balaji Solutions Log, Wordpress

Adding JQuery Slider Part II

October 9th, 2009

In my last post I showed how to easily add slider functionality using JQuery. In this post I will showcase some of the options that slider provides with a Temperature Converter. This is how it will work: the slider represents temperature measured in Celsius units and ranges between 0 and 100. As the user drags the slider, we will display the temperature equivalent in Fahrenheit.

Lets start by registering a basic slider:

   <script type="text/javascript">
	$(function()
	{
		$("#slider").slider();
	});
   </script>

Since the slider converts temperatures in the range 0 celsius and 100 celsius, modify the slider definition to include the range:

	$("#slider").slider({
		min: 0,
		max: 100,
		step: 1

	});

The next step is to add two span tags to display the chosen temperature and the temperature in Fahrenheit:

	Temperature in Celsius: <span id="celsius">0</span>
	
	Temperature in Fahrenheit: <span id="fahrenheit"></span>

Finally all we need to do would be to captrue the slide event so that we can update the span tags:

	$("#slider").slider({
		min: 0,
		max: 100,
		step: 1,
		slide: handleSlide
	});

The handleSlide is a javascript function that looks like this:

	function handleSlide(event, ui)
	{
		// Update the celsius span
		$("#celsius").html(ui.value);

		// Compute the fahrenheit equivalent
		var fTemp = (1.8 * ui.value) + 32;

		// Just display the last two digits of the temp
		$("#fahrenheit").html(fTemp.toFixed(2));
	}

Here is a working demo

Balaji JQuery, Solutions Log

Theming Websites using Spring MVC

October 8th, 2009

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

Balaji Spring ,

Adding JQuery UI Slider

October 1st, 2009

Here are five easy steps to add slider functionality to your web applications:

Step 1: Go to JQuery UI site and create a custom download. To keep things simple, select “No Theme”.under theme section and deselect all but UI Core and Slider checkboxes. Hit Download and unzip the downloaded file.

Step 2: Copy the jquery-1.3.2.min.js and “jquery-ui-1.7.2.custom.min.js” files into your project. These files should be under the js folder. Include the js files in your html/jsp page.

	
	
      

Step 3: Add the following styles to the page:


I am using the slider bar and slider handle images from YUI

Step 4: Add a DIV for the slider in the HTML.

Step 5: Initialize the slider in the document ready function:

	
      

That’s it. You can find a demo of this example here.

Balaji Getting Started, JQuery, Solutions Log , ,

Basic JQuery Tips

September 22nd, 2009

This is more for my reference and hopefully helps others working with JQuery.

  1. Getting and Setting the innerHTML of an element

    		var content = $("#id").html();
    		$("#id").html("Some HTML");
       
  2. Getting and Setting the text (with out any HTML) of an element

    		var txt = $("#id").text();
    		$("#id").text("Some Text");
    	
  3. Removing content from an element

    		$("#id").empty();
    	
  4. Getting and Setting style properties

    		var displayValue = $("#id").css("display");
    
    		$("#id").css("display", "block");
    	
  5. Hiding and Displaying elements

    		// Toggles an element's visibility
    		$("#id").toggle();
    
    		$("#id").hide();
    
    		// Sets the display style property to block and not inline
    		$("#id").show();
    	
  6. Registering to events such as keyup

    		$("#id").keyup(function(){
    			alert($(this).val());
    		});
    	
  7. Dealing with CSS classes

    		// Adds the specified class to the element
    		$("#id").addClass("showme");
    
    		// Multiple classes should be separated by spaces
    		$("#id").addClass("showme1 showme2");
    
    		// Removes the specified class
    		$("#id").removeClass("hideme");
    
    		// Multiple classes should be separated by spaces
    		$("#id").removeClass("hideme1 hideme2");
    
    		// Removes all the classes
    		$("#id").removeClass();
    	
  8. Getting and Setting values of form elements

    		// For input boxes
    		$("#inputbox").val(); // Returns the text box value
    		$("#inputbox").val("set some value");
    
    		// For select boxes
    		$("#selectbox").val(); // Returns the selected value
    		// To get the text of the selected option
    		$("#selectbox :selected").text();
    
    		// Programatically selects a value or multiple values
    		$("#singleselect").val("123");
    		$("#multipleselect").val(["12", "234"]);
    
    		// For checkboxes and radio buttons
    		$("#chkId").val();  // Returns value whether the check box is checked or not
    		// Returns true when the check box is checked
    		$("#chkId").attr("checked"); 		
    
    		// Programatically checks the check box
    		$("#chkId").attr("checked", "checked");
    	

Balaji JQuery, Uncategorized