Write Operations in DWR

Write operations are not allowed with the default session setting for the OpenViewInSession filter which is commonly defined in web.xml as a hibernate filter. If you want to enable write operations when using DWR (Direct Web Remoting), one of the ways is to declare a filter for DWR urls. Put the following configuration in your web.xml, also please note the url pattern in filter-mapping element.


<filter>
<filter-name>dwrWriteHibernateFilter</filter-name>
<filter-class>
some.package.name.OpenWriteSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>dwrWriteHibernateFilter</filter-name>
<url-pattern>*.dwr</url-pattern>
</filter-mapping>

The filter class as follows:

// more imports
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate3.support.OpenSessionInViewFilter;

public class OpenWriteSessionInViewFilter extends OpenSessionInViewFilter {

protected Session getSession(SessionFactory sessionFactory)
throws DataAccessResourceFailureException {
Session session = super.getSession(sessionFactory);
session.setFlushMode(FlushMode.COMMIT);
return session;
}

protected void closeSession(Session session, SessionFactory factory) {
session.flush();
super.closeSession(session, factory);
}
}

Integrating Spring MVC with Hibernate Annotation-Based Validation

In this article, I would like to demonstrate how to integrate Spring MVC, Spring bean validation framework and hibernate validator using annotations. The Hibernate Validator project is implementation of JSR 303 – Bean Validation standard, which defines a metadata model and API for JavaBean validation. For the the purpose of this example, I used Spring Framework v3.0.5 and Hibernate Validator v4.1.0.

What I like about Spring + Hibernate validation, is that this combination eliminates the need to use validator classes in controllers for bean validation. In other words, less code, less classes, everything looks much cleaner.

I am not going to talk about how to build web application from scratch using Spring MVC. I assume that you already have something working in place. I am just going to show the important bits needed, in order to plug hibernate validation in to your code:

1. Define two following beans in your application context XML in your WEB-INF directory:

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

The basic configuration above will trigger JSR-303 to initialize using its default bootstrap mechanism. A JSR-303 provider, such as Hibernate Validator, is expected to be present in the classpath and will be detected automatically.

<bean id="messageSource"
     class="org.springframework.context.support.ResourceBundleMessageSource">
	<property name="basename" value="/WEB-INF/message-resources.bundle" />
</bean>

The bean above knows how to access resource bundles using specified basenames.

2. Create resource bundle (in this example it is “message-resources.bundle”) under WEB-INF. The resource bundle is where you should define your validation messages that the end user sees if his form submission fails validation. Please note that the bundle does not have to be at the root of WEB-INF, it can be placed also in a sub-directory of WEB-INF. The format for validation messages in your bundle should be as follows:

Annotation.bean-variable-name.bean-propery=validation error message.

For example:

NotBlank.someFormName.name=Name must not be blank,
Size.someFormName.name=Name must be less than or equal to {1} characters.
NotBlank.someFormName.street=Street name should not be blank. Please enter a value
NotEmpty.someFormName.selectedItem=Item selection is required

The example above describes four different validation messages for different validation rules. In case of a particular validation rule disobeyed, its respective validation message will be found based on the validation annotation, bean name and bean property name.

3. In your controller, in the method that validates bean from the POST request, annotate your bean with annotation @Valid. For example:

@RequestMapping(value = "/update.html", method = RequestMethod.POST)
 public String update (    @ModelAttribute("someFormName")
 @Valid SomeForm someFormName,
 BindingResult result,
 Model model)
 {

 if(result.hasErrors()) {
 // Return view name
 }

 // Do stuff

 // Return view name
 }

The @Valid annotation is part of the standard JSR 303 – Bean Validation API, and is not a Spring-specific construct. The Hibernate Validator instance invoked when a @Valid method argument is encountered.

Very important: your bean variable name in your controller method (in this case its “someFormName“) must match the bean variable name in your validation message resource bundle.

4. Annotate your bean member variables with annotations that tell Hibernate Validator what should be validated and what are the validation rules:

public final class SomeForm {

 @NotBlank
 @Size(min=0,max=20)
 private String name;

 @NotBlank
 private String street;

 @NotEmpty
 private String selectedItem;

 // Getters

 // Setters
}

As you can see from the above bean, the three fields that should be validated are annotated with @NotBlank, @NotEmpty and @Size. The validation rules are simple: the name property must not be blank nor longer than 20 characters, street property must not be blank, while selectedItem must not be empty.

By the way, you can have more complicated validation rules in place using annotations. It is possible to use expressions which decide whether validation rules should fire. Consider the following, which validate an email field:

@Email(applyIf="email is not blank")
@NotBlank
private String email;

You don’t want to display invalid email format error message when the filed is blank. Therefore that above expression in @Email annotation will have the rule fired only when the property is not blank. Expression can be especially very convenient when validating password fields:

@NotBlank
private String password;

@NotBlank(applyIf = "password is not blank")
@Expression(value = "confirmedPassword= password", applyIf = "password is not blank")
private String confirmedPassword;

Validation rules for confirmedPassword property will fire only when password field will not be blank.

That’s it :) If any rule(s) are disobeyed, the BindingResult result object will be populated with appropriate error messages, loaded from your message bundle. The error messages then can be displayed in your JSP using Spring tag:

<spring:hasBindErrors name="someFormName">
	<c:forEach items="${errors.allErrors}" var="error">
		<spring:message message="${error}"/>
	</c:forEach>
</spring:hasBindErrors>

And that is it! Feel free to post a comment if you run into problems and I iwll try to help you the best I can :)

How To Define a Spring Bean With Generics Parameter

At the time when this article was written, the Spring framework does not allow to define beans in application context xml file using parameterized classes. The reason for that is that generics parameters are compiler information, and not run-time. Compiler information is something that Spring does not care about. For example, the following (or something similar) will NOT work:

<bean id="someClass" class="asia.javabeans.SomeClass<asia.javabeans.Blah>"  />

Sometimes, this restriction can create a problem if you have a parameterized class that has to be loaded by Spring. As a workaround, create an empty child class that extends your parameterized class, and then use that class’s canonical name as your bean definition. Consider the following parameterized parent and the extending child classes:

public class SomeParent<Blah> {

}

public class Child extends SomeParent<Blah> {
   // Just an empty class
}

and your Spring definition can now look like this:

<bean id="childClass" class="asia.javabeans.Child" />

The down side here is that you get stuck with an empty class, but at least you can have your bean definition in your application context xml file.