Saturday 13 November 2010

Rules-based Validation using Drools, JSR303 and Spring

Validation and business rules are closely linked. Indeed validation logic could be thought of as being part of the implicit business rules for an application.

It seems natural that integrating a business rules solution with a validation technology might be a natural step. In this post, I explore the possibility of integrating JSR303 and Drools to provide business rule driven validation within a Spring application. JSR303 is the standard Java method for data validation using annotations and Drools is a business rules engine that is a JBoss project and an implementation of JSR94, the standard Java rule engine API.

When to use (and when not to)

I don't think that this is a natural choice for all data validation needs. For a start, if the validation in your application is simple, the standard JSR303 annotations mixed with a few custom annotations might be enough. Integrating Drools comes at a cost in terms of architectural complexity and additional dependencies for you application. And although Drools is highly performance-optimised, a set of business rules in Drools will probably be slower than a set of custom Java statements.

However, there are significant benefits to complex applications - particularly if you are using Drools already. In that case, the complexity and dependency arguments are not valid.

The big benefit is the ability to externalise the business rules from the application and enable them to be edited without redeploying the application.

Drools overview

In a Drools application, business rules can be written in a powerful expression language called mvel (although XML can be used as well). In the Drools Expert documentation, the following basic example is given.

 
    public class Applicant {

        private String name;

        private int age;

        private boolean valid;

        // getter and setter methods here

    }
 
    package com.company.license;

    rule "Is of valid age" 
        when 
            $a : Applicant( age < 18 ) 
        then 
            $a.setValid( false ); 
        end

The rule consists of conditions (when) and consequences (then). In this rule, when the Applicant age property is less than 18, the valid property is set to false.

Often, business rules will need to access collaborators such as services or DAOs. These can be injected as "globals" in the rule definition. For example, the scenario above could be modified so that the applicant needs to be loaded from a DAO in order to check the age. The applicant identifier is a property in an ApplicationForm, submitted from a GUI or web application.

We'll also introduce a new class to hold the validation result, rather than setting the validity on the model object itself, which is somewhat artificial. This object could be returned to the presentation tier to tell the user what went wrong.

Error object to hold validation result:


    package com.acme.app.validation;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Collections;

    public class Errors {
 
        private final List<Error> errors = Collections.synchronizedList(new ArrayList<Error>());

        public Collection<Error> getErrors() {
            return Collections.unmodifiableCollection(errors);
        }
 
        public void addError(Object target, String field, String message) {
            this.errors.add(new Error(target, field, message));
        }
 
        public boolean hasErrors() {
            if (this.errors.size() > 0) {
                return true;
            }
            return false;
        }
    }

    class Error {
        private final Object target;
        private final String field;
        private final String message;
 
        public Error(Object target, String field, String message) {
            super();
            this.target = target;
            this.field = field;
            this.message = message;
        }

        public Object getTarget() {
            return target;
        }

        public String getField() {
            return field;
        }

        public String getMessage() {
            return message;
        }
    }

Modified Applicant (with identity)

 
    public class Applicant {

        private int id;

        private String name;

        private int age;

        private boolean valid;

        // getter and setter methods here

    }

ApplicationForm from the GUI/web:

 
    public class ApplicationForm {
 
        private int applicantId;
 
        private Date date;

        // getter and setter methods here

    }

Here is a slightly silly test DAO:

    
    public class ApplicantDaoImpl implements ApplicantDao {
 
        private final Map<Integer, Applicant> applicants = new HashMap<Integer, Applicant>();
 
        public ApplicantDaoImpl() {
            Applicant app1 = new Applicant(1, "Mr John Smith", 16);
            applicants.put(app1.getId(), app1);
            Applicant app2 = new Applicant(2, "Mr Joe Bloggs", 21);
            applicants.put(app2.getId(), app2);
        }
 
        @Override
        public Applicant findApplicant(Integer identifier) {
            return applicants.get(identifier);
        }

    }

Finally, a rule with a global representing the ApplicantDao and using our new Errors object could look like:

 
    package com.acme.app.rules

        import com.acme.app.form.ApplicationForm
        import com.acme.app.model.Applicant
        import com.acme.app.validation.Errors
        import com.acme.app.dao.ApplicantDao

        global ApplicantDao applicantDao

        rule "Check applicant age"
            when
                $a : ApplicationForm()
                $errors : Errors() 
                $applicant:Applicant( age < 18 ) from applicantDao.findApplicant($a.getApplicantId())
            then
                $errors.addError( $a, "applicantId", "Applicant age < 18" );
            end

In this version of the rule, the applicant is loaded from a DAO based on their identity. If the age of the applicant is less than 18, an error is inserted into the Errors object specifying the target object, field and message to return to the GUI. Obviously, this could be internationalized by putting a message code instead of the actual message.

That's an extremely brief overview of rules. Next, I'll quickly discuss the main API that Java programmers use when interacting with Drools. These will be used by the JSR303 validator when validating a bean using business rules.

At the most basic level, Drools stores business rules in a KnowledgeBase, from which can be created "sessions" which enable users to execute the rules based on facts, which are usually model objects inserted into the session.

There are two types of session: StatefulKnowldegeSession and StatelessKnowledgeSession. A StatelessKnowledgeSession is considered appropriate for use cases such as validation, because they are intended as a "one-shot" function call: pass in the facts, execute the rules, get a result. That's therefore the interface I will use for the integration with a JSR303 validation.

Here is a simple example of creating a StatelessKnowledgeSession and executing the rules based on a collection of facts, each of which is inserted in turn before the rules are fired.


    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newFileSystemResource( fileName ), ResourceType.DRL );
        assertFalse( kbuilder.hasErrors() );     
        if (kbuilder.hasErrors() ) {
            System.out.println( kbuilder.getErrors() );
        }
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
 
        StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
        ksession.execute( collection );

Spring integration

Conveniently, in Drools 5.1 some additional Spring integration was added that enables you to create KnowledgeBases and sessions declaratively in the application context, using a purpose-built namespace.

In this example, Spring is the "glue" bringing together the Drools and JSR303 parts. Here's the configuration.


    <?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:drools="http://drools.org/schema/drools-spring"       
       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://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd">
  
        <drools:kbase id="kbase">
            <drools:resources>
                <drools:resource type="DRL" source="classpath:testSpring.drl"></drools:resource>
            </drools:resources>
        </drools:kbase>
    
        <drools:ksession id="statelessKSession" type="stateless" name="statelessKSession" kbase="kbase">
        </drools:ksession>
  
    </beans>

I'm keeping things very simple - there is a lot more that the namespace can do in terms of configuring knowledge bases, agents, sessions etc.

JSR 303 Overview

JSR303 is a standard Java mechanism for validating JavaBeans using convenient annotations. Creating custom annotations is a matter of creating the annotation and an accompanying ConstraintValidator implementation, which will be automatically used by the Validator when it encounters the annotation on a bean getting validated.

The annotation itself is simple.


    package com.acme.app.validation;

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
 
    import javax.validation.Constraint;
    import javax.validation.Payload;
 
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Constraint(validatedBy=BusinessRulesConstraintValidator.class)
 
    public @interface BusinessRulesConstraint {
        String message() default "Business rules validation failed.";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }

The validator is also reasonably simple. A StatelessKnowledgeSession and a simple bean carrying a Map of the needed collaborators (to be set as globals) are injected into the constructor.

When the isValid() method is called, an Errors object and the target of the validation are inserted into the session and the validation rules are fired. If the Errors object comes back with errors, validation has failed and a ConstraintViolation is built using the data in the Errors object.


    package com.acme.app.validation;

    import java.util.Arrays;
    import java.util.Map;

    import javax.validation.ConstraintValidator;    
    import javax.validation.ConstraintValidatorContext;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.drools.runtime.StatefulKnowledgeSession;
    import org.drools.runtime.StatelessKnowledgeSession;
    import org.springframework.beans.factory.annotation.Autowired;

    /**
     * Custom JSR303 {@link ConstraintValidator} that
     * uses a Drools {@link StatelessKnowledgeSession} to
     * implement rules-based validation of objects
     * decorated with a @BusinessRulesConstraint annotation
     */
    public class BusinessRulesConstraintValidator implements ConstraintValidator<BusinessRulesConstraint, Object> {

        private final Log logger = LogFactory.getLog(BusinessRulesConstraintValidator.class);
 
        private final StatelessKnowledgeSession session;
 
        @Autowired
        public BusinessRulesConstraintValidator(StatelessKnowledgeSession session, Collaborators collaborators) {
            this.session = session;
            if (collaborators != null) {
                Map<String, Object> map = collaborators.getCollaborators();
                for (String key : map.keySet()) {
                    session.setGlobal(key, map.get(key));
                }
            }
        }

        @Override
        public void initialize(BusinessRulesConstraint constraint) {}

        @Override
        public boolean isValid(Object target, ConstraintValidatorContext context) {
  
            // Create Errors
            Errors errors = new Errors();
  
            try {
   
                // Fire rules
                session.execute(Arrays.asList(new Object[]{errors, target}));
   
                // Check for errors
                if (errors.hasErrors()) {
                    // Build constraint violations
                    context.disableDefaultConstraintViolation();
                    for (Error error : errors.getErrors()) {
    context.buildConstraintViolationWithTemplate(error.getMessage()).addNode(error.getField()).addConstraintViolation();
                    }
                    return false;
                }
            } 
            catch (Exception e) {
                logger.error(e);
                return false;
            }
  
            return true;
        }

    }

The Collaborators object is extremely simple:


package com.acme.app.validation;

import java.util.Collections;
import java.util.Map;

public class Collaborators {
 
    private final Map<String, Object> collaborators;

    public Collaborators(Map<String, Object> collaborators) {
        super();
        this.collaborators = collaborators;
    }

    public Map<String, Object> getCollaborators() {
        return Collections.unmodifiableMap(collaborators);
    }
}

It's simply a container holding a map into which collaborators such as DAO or Service facades could be injected using Spring.

The full Spring configuration gluing the whole thing together is below:


<?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:drools="http://drools.org/schema/drools-spring"       
       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://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd">
  
  <drools:kbase id="kbase">
    <drools:resources>
      <drools:resource type="DRL" source="classpath:testSpring.drl"></drools:resource>
    </drools:resources>
  </drools:kbase>
    
  <drools:ksession id="statelessKSession" type="stateless" name="statelessKSession" kbase="kbase"></drools:ksession>

  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"></bean>
  
  <bean id="collaborators" class="com.acme.app.validation.Collaborators">
      <constructor-arg><map>
              <entry key="applicantDao" value-ref="applicantDao"></entry>
          </map>
      </constructor-arg></bean>

<bean id="applicantDao" class="com.acme.app.dao.impl.ApplicantDaoImpl"></bean>
</beans>

Using the validator is very simple. First, the ApplicantForm object needs to be decorated with the @BusinessRulesConstraint annotation at class level so that the JSR303 validator will be triggered to use the BusienssRulesConstraintValidator.


package com.acme.app.form;

import java.util.Date;

import com.acme.app.validation.BusinessRulesConstraint;

@BusinessRulesConstraint
public class ApplicationForm {
 
    private Integer applicantId;
 
    private Date date;

    // getters/setters
}

Then it is a matter of invoking the validator with a bean instance like this:


package com.acme.app.validation.tests;

import java.util.Date;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.acme.app.form.ApplicationForm;

public class ValidationTestCase {
 
    private static ApplicationContext ctx;
 
    private static Validator validator;
 
    @BeforeClass
    public static void beforeClass() {
  
        // Create the Spring application context
        String[] paths = { "application-context.xml" };
        ctx = new ClassPathXmlApplicationContext(paths);
  
    }
 
    @Before
    public void before() {
        validator = (Validator)ctx.getBean("validator");
    }
 
    @Test
    public void testInvalidAge() {
        ApplicationForm applicationForm = new ApplicationForm(1, new Date());
        Set<ConstraintViolation<ApplicationForm>> violations = validator.validate(applicationForm);
        Assert.assertNotNull(violations);
        Assert.assertEquals(Integer.valueOf(2), Integer.valueOf(violations.size()));
    }
 
}

Summary

This post shows you an approach for integrating JSR303 and Drools in a Spring application, something you might want to do if you were using these technologies already in your application and it was sufficiently complex to warrant it. The steps involved are:

  • Create your domain objects and decorate them withe @BusinessRulesConstraint where business rule validation is to be used.
  • Create the .drl file with your validation logic in it.
  • Configure Spring as above with a KnowledgeBase containing your drl file as a resource, a StatelessKnowledgeSession derived from that KnowledgeBase, your collaborators for the rules and the JSR303 validator.

That's it!

Postscript: Maven configuration

For Maven users, this should be useful in getting all the dependencies for this example to work.



<dependencies>
  
    <!-- Spring bits -->
    <dependency>
        <groupid>org.springframework</groupId>
        <artifactid>spring-core</artifactId>
        <version>${org.springframework.version}</version>
    </dependency>

    <dependency>
        <groupid>org.springframework</groupId>
        <artifactid>spring-context</artifactId>
        <version>${org.springframework.version}</version>
    </dependency>    
  
    <dependency>
        <groupid>org.springframework</groupId>
        <artifactid>spring-beans</artifactId>
        <version>${org.springframework.version}</version>
    </dependency>   
    
    <!-- Drools bits -->
    <dependency>
        <groupid>org.drools</groupId>
        <artifactid>drools-core</artifactId>
        <version>5.1.1</version>
    </dependency>
  
    <dependency>
        <groupid>org.drools</groupId>
        <artifactid>drools-spring</artifactId>
        <version>5.1.1</version>
    </dependency>

    <!-- JSR303 bits -->
    <dependency>
        <groupid>org.hibernate</groupId>
        <artifactid>hibernate-validator</artifactId>
        <version>4.1.0.Final</version>
    </dependency>

    <dependency>
        <groupid>org.slf4j</groupId>
        <artifactid>slf4j-api</artifactId>
        <version>1.5.6</version>
    </dependency>
  
    <!-- concrete Log4J Implementation for SLF4J API-->
    <dependency>
        <groupid>org.slf4j</groupId>
        <artifactid>slf4j-log4j12</artifactId>
        <version>1.5.6</version>
    </dependency>
 
</dependencies>

Wednesday 20 October 2010

Validating service method parameters using JSR 303, Spring AOP/AspectJ and Spring

When building an application with Spring and JSR303 you can easily validate form submissions using the built in JSR303 validators. This helps ensure that parameters passed to service methods are valid in a web application. However, there are certain cases where you might wish to invoke your service methods directly rather than from within an MVC controller, for example if you were using DWR or a REST web service. Here is an example of a service facade that might exist in a Spring application.
public interface UserService {

 public abstract void updateUser(UserForm userForm);

}

@Service
public class UserServiceImpl {

 @Override
 @Secured({"ROLE_EMPLOYEE"})
 @Transactional(readOnly=false, isolation=Isolation.READ_COMMITTED,propagation=Propagation.SUPPORTS)
 public abstract void updateUser(UserForm userForm) {
   User user = extractUserFromUserForm(userForm);
   userDao.updateUser(user);
 }

}
Here is the UserForm parameter that is passed to the updateUser method above. It is a simple Form or Command bean using JSR 303 annotations to validate input.
@FieldMatch.List({
 @FieldMatch(first = "password", second = "confirmPassword"),
})
public class UserForm {
 @NotNull
 private String username;

 @NotNull
 @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}")
 private String password;

 @NotNull
 @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}")
 private String confirmPassword;

}
If the only client of the facade is a Spring MVC controller, the JSR303 validator can easily be wired in to validate the UserForm before it gets anywhere near the facade. However, if you are invoking the service in another way, there is a risk that the UserForm wouldn't be valid when it is passsed to the updateUser() method. How could we prevent that? The obvious answer would be to invoke the JSR303 validator in code in the facade implementation. Something like this would do the trick:
@Service
public class UserServiceImpl {

 @Autowired
 private Validator validator;

 @Override
 @Secured({"ROLE_EMPLOYEE"})
 @Transactional(readOnly=false, isolation=Isolation.READ_COMMITTED,propagation=Propagation.SUPPORTS)
 public abstract void updateUser(UserForm userForm) {

   // Validate input
   Set> violations = validator.validate(userForm);
   if (!violations.isEmpty())
     throw new ConstraintViolationException(violations);

   // Perform update
   User user = extractUserFromUserForm(userForm);
   userDao.updateUser(user);
 }

}
Reasonably simple - but if you do that for every service method, the repeated boilerplate code will add up to a fair bit of typing and clutter. Here is my proposed alternative. Use a new annotation to decorate the parameter in the service method, and use AOP to intercept method invocations and perform parameter validation. It is effectively the same solution but with less typing. Here is what the end solution would look like.
@Service
public class UserServiceImpl {

 @Autowired
 private Validator validator;

 @Override
 @Secured({"ROLE_EMPLOYEE"})
 @Transactional(readOnly=false, isolation=Isolation.READ_COMMITTED,propagation=Propagation.SUPPORTS)
 public abstract void updateUser(@Valid UserForm userForm) {

   // Perform update
   User user = extractUserFromUserForm(userForm);
   userDao.updateUser(user);
 }

}
Note the @Valid annnotation on the UserForm parameter. This isn't the standard JSR 303, but our own custom annotation that is used to mark parameters that need validation via AOP. On reflection, I probably should have called it something else to avoid confusion.
package myapp.validators.aspects;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Valid {
 Class[] groups() default {};
}

The aspect that performs the validation is here.
package myapp.validators.aspects;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

@Aspect
public class ValidateAspect {
 
 @Autowired
 private Validator validator;

 public void setVaidator(Validator validator) {
   this.validator = validator;
 }
 
  
 @Before("execution(* *(@myapp.validators.aspects.Valid (*)))")
 public void valid(JoinPoint jp) throws NoSuchMethodException {

   // ConstraintViolations to return
   Set<ConstraintViolation<?>> violations = new HashSet<ConstraintViolation<?>>();

   // Get the target method
   Method interfaceMethod = ((MethodSignature)jp.getSignature()).getMethod();
   Method implementationMethod = jp.getTarget().getClass().getMethod(interfaceMethod.getName(), interfaceMethod.getParameterTypes());
  
   // Get the annotated parameters and validate those with the @Valid annotation
   Annotation[][] annotationParameters = implementationMethod.getParameterAnnotations();
   for (int i = 0; i < annotationParameters.length; i++) {
     Annotation[] annotations = annotationParameters[i];
     for (Annotation annotation : annotations) {
       if (annotation.annotationType().equals(Valid.class)) {
         Valid valid = (Valid)annotation;
         Object arg = jp.getArgs()[i];
         violations.addAll(validator.validate(arg, valid.groups()));
       }
     }
   }
        
   // Throw an exception if ConstraintViolations are found
   if (!violations.isEmpty()) {
     throw new ConstraintViolationException(violations);
   }
  }
}

The final bit of glue in Spring to make it all work is to declare the custom annotation aspect in the application context.


 

Hope this is useful to someone. I found the following blogs and forum threads helpful in coming up with this post and related code. References http://forum.springsource.org/showthread.php?t=77390 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html http://blog.newsplore.com/2010/02/23/spring-mvc-3-0-rest-rebuttal

Tuesday 25 May 2010

Creating a custom JSR 303 constraint annotation with Spring 3

Spring 3.0 has support for JSR303 annotation-driven validation, which makes it easy to build declarative validation into Java Beans in Spring applications. Out of the box, JSR303 supports annotations such as @NotNull and @Size etc which allow you to perform basic validation checks. However, most applications will need to do more sophisticated "business-logic" validation such as checking whether an email already exists in a database. I recently needed to do just that in a Spring MVC application that needed a "Forgot Password" function to let users receive an email with their password. The Spring MVC command object was very simple:
public class SendPasswordReminderCommand implements Serializable {
 
 private static final long serialVersionUID = 42L;

 private String email;

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }

      // equals, hashcode, toString, constructors omitted
}
Annotating this class with JSR 303 annotations to check the format of the email or ensure that the email is not null is easy enough (using @NotNull, @Length from the core javax.validation.constraints standard package and @Email from the org.hibernate.validator.constraints package). Ideally, you would also be able to check the database and ensure that the email exists in the database and inform the user if not as part of the validation. To do this, having a custom annotation called @EmailExistsConstraint would be ideal - but you need to make your own!
public class SendPasswordReminderCommand implements Serializable {
 
 private static final long serialVersionUID = 42L;
 
 @NotNull
 @Length(min=1)
 @Email
 @EmailExistsConstraint
 private String email;

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }
}
Creating the custom constraint requires you to create two classes - an annotation interface and associated constraint validator. The annotation is straightforward.

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy=EmailExistsConstraintValidator.class)

public @interface EmailExistsConstraint {
 String message() default "Email doesn't exists";
 Class[] groups() default {};
 Class[] payload() default {};
}

The constraint validator is where you perform the database check. As this is a Spring and Hibernate application, the constraint validator uses a Hibernate DAO as a "collaborator" to perform the check.
public class EmailExistsConstraintValidator implements ConstraintValidator {

 private Log log = LogFactory.getLog(EmailExistsConstraintValidator.class);
 
 @Autowired
 private EmployeeFinder employeeFinder;
 
 @Override
 public void initialize(EmailExistsConstraint constraint) {
  
 }

 @Override
 public boolean isValid(Object target, ConstraintValidatorContext context) {
  
  try {
   Collection employees = employeeFinder.findEmployeeByEmail((String) target);
   if (employees.size() > 0) {
    return true;
   }
  } catch (Exception e) {
   log.error(e);
  }
  return false;
 }

 public void setEmployeeFinder(EmployeeFinder employeeFinder) {
  this.employeeFinder = employeeFinder;
 }
}

This is a fairly straightforward constraint validator implementation. If the database contains a record matching the email address, the isValid() method returns true and false if not. All that Spring needs to use JSR303 is to register the Spring validator implementation in the application context. It then automatically detects any custom constraints and will validate classes using your annotations without any further configuration.

However, there is still one problem with this. As it stands, the Validator will validate all of the annotations in one pass. This is a problem, because the database check will occur even if the email fails all of the other checks which is wasteful and potentially confusing to the user, who would see multiple validation messages. Thankfully, the JSR303 specification contains the concept of groups, which can be used to lump annotations together and process them in a specified order. The example below illustrates how groups can be used to split the basic format checks from the database check.
@GroupSequence(value={SendPasswordReminderCommand.class, FormatChecks.class,BusinessLogicChecks.class})
public class SendPasswordReminderCommand implements Serializable {
 
 private static final long serialVersionUID = 42L;
 
 @NotNull(groups=FormatChecks.class)
 @Length(min=1, groups=FormatChecks.class)
 @Email(groups=FormatChecks.class)
 @EmailExistsConstraint(groups=BusinessLogicChecks.class)
 private String email;

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }
}
Firstly, each annotation has a group parameter that specifies a class (in this example, FormatChecks.class and BusinessLogicChecks.class). These classes are marker interfaces that are simply used to identify groups. To specify the sequence in which annotation groups are processed, the @GroupSequence annotation is used. An array of classes is passed to the values parameter that starts by convention with the class being validated, followed by the group marker interfaces in the order that you wish to process them. The marker interfaces are very straightforward. One of the interfaces must extend the javax.validation.groups.Default marker interface, which as you may guess is the default group if no group is specified.
public interface FormatChecks extends Default {

}

public interface BusinessLogicChecks {

}
You can define as many groups as you want. As you can see, creating custom constraint annotations is pretty straightforward with Spring 3.0. JSR 303 is well thought out and the ability to group constraints is very useful for ensuring that expensive business logic checks are not performed without reason, when validation has already failed for basic data format reasons.

Thursday 22 April 2010

Thread safety, Java Beans and Hibernate

I just read "Java Concurrency in Practice" by Brian Goetz et al and found it to be a fantastic educational experience. The main thing I learned is that I am a total novice when it comes to multi-threaded programming! My excuse is that I learned programming by building websites and applications, where it is popularly imagined that multi-threading is not really an issue. Also, I'm no computer scientist, just an ex-physicist who found out that pretending to know about the internet and programming pays better than doing a real job like physics. I digress.

I started to think about the standard patterns and practices used by web programmers when building web applications, especially using my favourite frameworks (Spring and Hibernate, of course) and wondered whether I should be more worried about threads than I usually am (i.e. not at all). After some serious head-scratching and blog-reading I have come to the following conclusions.

  1. There is evidence that Java Bean based frameworks could potentially be vulnerable to multi-threading issues due to the mutability of Java Beans
  2. I wouldn't worry about it too much (as long as they are thread-confined).

I better make it clear that I am not talking about the thread-safety of Hibernate or Spring themselves. By and large, as developers we accept these frameworks and given and while we should be aware of the thread-safety issues that they may have there is not much that we can do to change them in our applications. I'm talking about the standard components that we build on top of these frameworks. The thread-safety or otherwise of these frameworks is probably a worthy topic in itself, but it's not what I'm looking at here.

Let's start with Hibernate itself. Typically, persistent classes follow the Java Beans "pattern" of a no-args constructor with accessor and mutator objects for the private fields of the class (getters and setters). Java Beans are intrinsically "mutable" objects (they have mutators, after all!). Mutability on its own is not necessarily a thread-safety hazard, but the first recommendation for building thread-safe classes is to make them immutable - so Java Beans immediately seem to be a thread-safety hazard.

There are plenty of great resources explaining why mutable classes pose thread-safety hazard, including the "Java Concurrency In Practice" book, so I'll just summarise. The Java memory model makes no particular guarantees about the visibilty of changes in state between two threads, and in fact makes no guarantees about the order in which changes in state may seem to occur in two threads. This means that if thread 1 changes the state of a Java Bean field, thread 2 may not see this change immediately, or indeed at all. A further risk is that fields that are involved in invariants (i.e. are constrained by validation rules) could be modified so as to violate the invariants by different threads, even if the mutator methods contain logic to enforce the invariants.

So if Hibernate persistent classes are usually Java Beans, and Java Beans are mutable, and mutability is bad this surely seems to point to a potential thread-safety issue. So why am I sanguine about this risk?

The reason is that in general the risks posed by mutability are reduced when the objects in questions can be "thread-confined". In other words, they are only ever used by a single thread at a time. A mutable class will not pose thread-safety hazards if it is confined in this way. So, are Hibernate Java Beans thread-confined in a web application? The answer is potentially yes, depending on whether you store them somewhere that another thread can access them (like the HttpSession).

If your web application loads a Hibernate entity from a DAO or a service object that uses JPA (for instance) and then places this entity in a request for rendering in a view, it's pretty clear that this is thread-confined up to the point where the entity is placed in the request. Up to this point, it is only ever a local variable in a series of methods and is hence thread-confined (Actually, I don't know whether Hibernate is returning a unique instance for each call to Session.load() but I believe it does).

For example, here is a very brief illustration of retrieving a Hibernate entity for display on a page.

In the service object:
public Customer getCustomer(Integer customerId) {
return em.find(Customer.class, customerId);
}
in the controller:
@ModelAttribute("customer")
public Customer getCustomer() {
return customerService.getCustomer(customerId);
}

In the above example, the Customer entity instance is always thread confined. As a @ModelAttribute is stored in the HttpServletRequest it should be thread-confined as each request runs in its own thread which ends when the request is finished.

However, if the model is stored in the HttpSession, ServletContext or in a cache, then multiple threads might access the JavaBean. You are at the mercy of the thread safety of the HttpSession, ServletContext or cache provider.

In fact, it is recommended to synchronize access to attributes stored in the HttpSession unless contained in an immutable object, because multiple threads may access it simultaneously. The same is true of the SerlvetContext. A well-designed cache should be designed with concurrency in mind and have appropriate synchronization - but you should make sure of this.

So in conclusion, if you want to avoid thread-safety problems with Java Beans, confine them to a single thread and avoid storing them in places where multiple threads could access them such as the HttpSession, ServletContext or a cache (unless you are sure that the cache is thread-safe).

Wednesday 21 April 2010

Using JSR 303 with "classic" Spring Validators (enter the SpringValidatorAdapter)

Spring 3.0 has a number of new features, one of which is support for JSR303. JSR303 adds annotation-driven validation for Java Beans which is intended to replace hand-coded validation code. This has obvious ramifications for Spring MVC as a key part of this framework includes support for validation of web forms using hand-coded Validator implementations. I'm gradually upgrading a Spring 2.x MVC application to Spring 3.0 at the moment, with the emphasis on gradual. So while I'd like to use JSR 303, I'm not ready yet to re-code the 50 odd Controller implementations to use the new annotation-driven style (even though I hate seeing warnings in Eclipse). Luckily, Spring makes it really easy to have the best of both worlds using the SpringValidatorAdapter. Put simply, this class wraps the JSR303 adapter and provides convenience methods to enable you to easily support the old style Validator interface methods. You can then use the annotations in your command/form objects and the old-school Validators in your Controller classes. Here is a simple example command object using the JSR 303 annotations. They are pretty self-evident and there are loads of blogs that explain what they do.
public class MyCommand implements Serializable {

private static final long serialVersionUID = 42L;

@NotNull
@Min(value=1L)
private Integer projectId;

@NotNull
@Min(value=1L)
private Integer employeeId;

@NotNull
@Min(value=1L)
@Max(value=999L)
private BigDecimal hoursToComplete;

     // Constructors, accessors, mutators, equals, hashcode omitted :-)
}
The Validator for this class is then very simple. Create a Validator implementation as per usual, and then inject the SpringValidatorAdapter class into it. I've done this through the constructor, as I am trying to appear clever and multi-threaded by marking the SpringValidatorAdapter instance as final. Oh yeah, feel my muscles.
public class MyCommandCommandValidator implements Validator {

private final SpringValidatorAdapter validator;

public MyCommandCommandValidator(SpringValidatorAdapter validator) {
 super();
 this.validator = validator;
}

@SuppressWarnings("unchecked")
@Override
public boolean supports(Class givenClass) {
 return validator.supports(givenClass);
}

@Override
public void validate(Object target, Errors errors) {
 validator.validate(target, errors);
 
 // More custom validation here

}
}
Note that you could just use the SpringValidationAdapter directly (without wrapping it in your own Validator implementation) if you are only doing JSR303 validation. It's also possible to write your own JSR303 custom validation routines, which might be a better long term architecture than the mixed approach above. The Spring LocalValidatorFactoryBean implements the main JSR303 Validator interface as well as SpringValidatorAdapter. So the Spring configuration is simple. You do need to have the Hibernate Validator reference implementation available on the classpath or an alternative.



   

Job done! The only other thing to note is that the message codes are set by the JSR303 Validator, so you may have less control over them. For example:

public void testValidateNotNullFields() throws Exception {

 // Perform validation
 validator.validate(command, errors);

 // Check error count
 assertEquals(Integer.valueOf(3), Integer.valueOf(errors.getErrorCount()));
 
 // Test employeeId field
 FieldError employeeIdError = errors.getFieldError("employeeId");
 assertNotNull(employeeIdError);
 assertEquals("NotNull", employeeIdError.getCode());

}

In this test, the employeeId field was not set in the command. The Validator created a field error under key "employeeId" with the error code "NotNull" as it was the @NotNull constraint that was violated (and not in a good way). In summary - using JSR303 with "classic" validators is really easy thanks to the SpringValidatorAdapter class. Woot.

Tuesday 20 April 2010

Spring Security 3.0 and Spring EL

Among the many improvements in Spring Security 3.0 is the ability to use the Spring Expression Language (SPEL) to secure methods and URLs. This immediately opens up the possibility of more sophisticated "domain object security" on service methods and URLs. To secure service methods, a number of additional attributes have been added that support the SPEL. The most immediately useful is the @PreAuthorize attribute which is similar to the old @Secured attribute in intent but with a bit of SPEL processing thrown in as well. The documentation gives the following example:
@PreAuthorize("#contact.name == principal.name)")
public void doSomething(Contact contact);
The #contact refers to the contact parameter in the method. The tag causes all of the method parameters to be injected as variables into the expression language evaluation context. Variables are referenced using the # prefix. This script basically checks that the #contact variable has a name field that matches the name field in the current principal object (principal is an implicit object that is the current Spring Security Principal implementation). There are3 other attributes that have been added for filtering and post-authorisation. You can also use SPEL to restrict access to URLs.
<http expressions="true>
<intercept-url pattern="/admin*" access="hasRole('admin') and hasIpAddress('192.168.1.0/24')">
...
</intercept-url>
</http>
A great feature of this is that the EL has access to the HttpServletRequest in the EvaluationContext for the web request, meaning that you can peek at request parameters in the EL to grant access based on their values. Another useful feature is being able to check access to a specific URL in the Spring Security taglibs before rendering content.
<sec:authorize url="/admin">

This content will only be visible to users who are authorized to send requests to the "/admin" URL.

</sec:authorize>
These are all very useful features. However, there are a number of problems with the support offered for EL base access control that I have discovered. My immediate instinct was to define EL based access control inside the security context with the <intercept-url /> and then use <sec:authorize url="/xxx" /> in JSPs to render links only when a user has access to them. This works well up to a point. Problems start to occur when you need to evaluate objects in the request in the expression and try to authorize those URLs using the tag. For example, take the following EL definition which checks that the employee id supplied in the request matches the employee id of the logged in principal.
<intercept-url pattern="/timesheetview.htm"
access="principal.employeeId ==
T(java.lang.Integer).valueOf(request.getParameter('employeeId'))" />
This on its own works well enough. If you request the URL in a browser, requests are correctly authorised (or not). However, if you then try to use the <sec:authorize url="/xxx" /> tag in a JSP to check access to this URL, things no longer work. For example, the script below seems like it should work.
<c:url value="/timesheetview.htm" var="url">
<c:param name="employeeId" value="${employeeId}>
<c:url>
<sec:authorize url="${url}">
<a href="${url}">View timesheet<a>
</sec:authorize>
The problem is that the authorize tag does not allow scripting variables in the url attribute. However, there is a further problem which means that even if it did you still can't dynamically check access based on a request parameter. My first attempt at a workaround was this:
<sec:authorize url="/timesheetview.htm?employeeId=123">
<a href="/timesheetview.htm?employeeId=123">View timesheet<a>
</sec:authorize>
This gets around the scripting issue, but fails for a more fundamental reason (above the fact that employee id must be hard-coded). The reason this doesn't work is that Spring Security issues a "dummy" request to the URL to see whether access is denied or granted. The dummy request is made using an instance of org.springframework.security.web.access.DummyRequest which is a partial implementation of HttpServletRequest. Specifically, most operations cause an OperationNotSupportedException - including HttpServletRequest.getParameter(String name). That means that when the EL expression executes, it tries to call request.getParameter() which in turns causes the OperationNotSupportedException. It is in fact impossible in Spring Security 3.0 to use an EL expression in the <intercept-url /> in combination with the <sec:authorize url="xxx"> tag in a situation where the url in question is secured with an expression that accesses the HttpServletRequest - regardless of whether the parameter is supplied in the request or not. These problems mean that this exciting feature falls quite short of expectations when used in what seems to be a fairly obvious scenario. I'd like to see the DummyRequest be able to support request parameters in a future version that are evaluated based on the contents of the url attribute. This attribute should support scripting variables to enable parameters to be passed in using <c:url> Don't get me wrong - it's still awesome. Spring Security 3.0 is a worthwhile upgrade but there is always room for improvement.

Thursday 4 February 2010

Unit testing Spring Controllers

I found this DevX blog by Edmon Begoli really useful for writing unit tests for Spring controllers using MockHttpRequest and MockHttpResponse. However, I think the ideas in it can be extended slightly to help those using Spring Security and Hibernate, particularly the Open Session In View pattern, perhaps aided by Spring's OpenSessionInViewFilter.

My first enhancement would be to load the Controller instances from Spring rather than assembling them by hand. The key to doing this with Maven is to move the "spring-servlet.xml" file that configures the controllers from the src/main/webapp/WEB-INF folder in to src/main/resources. This doesn't cause any problems as you can load the spring-servlet.xml from anywhere on the classpath.


  spring
    org.springframework.web.servlet.DispatcherServlet
    
       contextConfigLocation
       classpath:spring-servlet.xml  
     
  1

Having done this, you can then load the spring-servlet.xml application context in your Controller unit tests.

The setUp() method below shows how to do this, in addition to obtaining a reference to the Spring security AuthenticationManager and starting a Hibernate Session. The latter allows us to replicate the effects of the OpenSessionInViewFilter while the former gives us the means to log in to Spring Security before executing a test.

protected void setUp() throws Exception {
  super.setUp();
  
  // Set up Spring application context
  String[] paths = { "application-context-datasource-test.xml",
       "application-context-dao.xml",
       "application-context-facade.xml",
       "application-context-mail.xml",
       "spring-servlet.xml" };
  ctx = new ClassPathXmlApplicationContext(paths);
      
  // Get Spring AuthenticationManager
  am = (AuthenticationManager)ctx.getBean("authenticationManager");  
       
  // Create mock request and response
  request = new MockHttpServletRequest();
  response = new MockHttpServletResponse();
  
  // Start session (simulate open session in view)
  factory = (SessionFactory)ctx.getBean("sessionFactory");
  session = sessionFactory.openSession();
  TransactionSynchronizationManager.bindResource(factory, new SessionHolder(session));
}

A simple "log in" method can be provided for use in the tests.

protected void login(String username, String password) {
  Authentication auth = am.authenticate(new UsernamePasswordAuthenticationToken(username, password));
  SecurityContextHolder.getContext().setAuthentication(auth);
}

A sample test method might look like this.

public void testStuff() throws Exception {
  // Get the controller
  MyController ctrlr = (MyController ) ctx.getBean("myController");

  // Login as manager
  login("bill.business-manager", "secret");

  // Controller renders form on GET method
  request.setMethod(AbstractController.METHOD_GET);

  // Execute the request
  ModelAndView mav = ctrlr.handleRequest(request, response);
  
  // Test stuff
  assertNotNull(mav);
}

Tuesday 2 February 2010

Using database views in Hibernate (or, anything view can do, HQL can do better)

It's very easy to map database views using Hibernate, but there are a few considerations you might want to er... consider before you do it. I suspect the main reason people do it is for performance, but I think that a lot of the gains are not that great and might stem from lack of knowledge about what HQL can do.
Certainly, loading an entity and then iterating through child entities to calculate aggregate values is not going to perform as well as the equivalent view. However, as I will explain below you may be able to achieve the same result using the equivalent features in HQL.
Finally, I do admit that some databases enable indexing of views and that might be faster than the equivalent operations in Hibernate as a result.
First, I'll just look at how you go about mapping a view and then discuss some of the details a bit later.
You can map a view exactly as if it was a table. Just put the view name in the table attribute. Optionally, you can specify that the class is immutable as in most cases you won't be able to update a view-backed entity.

 
 ...
 
The first consideration with this is portability. Not all databases support views so you would be limited to supporting those that do.
However, you can use the subselect element to largely the same effect, although obviously this wouldn't benefit from indexing in the same way that a "proper" view might.

 
     
       select p.Name, sum(s.Bits) from Project p inner join Stuff s etc
     
 ...
 
However, at this point you may need to consider how your views will interact with the 2nd-level cache. The good news is that you can enable this as you would a normal entity and you can cache HQL queries on this view. I tend to do this in the Hibernate configuration file. Note again that it's worth specifying that the usage is "read-only".

The bad news is that you may get some unexpected results on your cached views when you update the tables that are joined by the view. Basically, the view queries won't reflect the current contents of the database immediately as the level 2 cache will hold stale data. Why is this data not evicted from the cache? Because Hibernate can't really guess which entities are related to your view unless you tell it.
You can let Hibernate know which other tables are linked to your view as below:

 
     <synchronize table="dbo.Project" />
     <synchronize table="dbo.Stuff" />
     <synchronize table="dbo.Things" />
     ...
 
One thing to watch for is that Hibernate is very fussy about how you specify the table attribute. It is case sensitive, and in the case of Microsoft SQL Server 2005 also requires the name to be qualified with the schema. If you get it wrong, Hibernate doesn't complain - but it also won't automatically evict your views from level 2 cache. You just need to fail your way to success, unfortunately.
By now you have got your views working with Hibernate and it is playing nice with the level 2 cache.
But did you need to do it in the first place?
I can think of two scenarios where a view might be used. One would be to conveniently load a "flattened" representation of an object graph in one efficient join query, thereby avoiding the famous "N+1 query" problem of loading object graphs in Hibernate. Two would be to calculate aggregate values on an object graph (such as a sum of a field in a child object), again in a single efficient query.
However, both of these things can be achieved in HQL. The first can be achieved using a "join fetch" query, that causes an object graph to be loaded using a single join query. The second can be achieved using the support for aggregate functions in HQL that can return scalar values in a result set.
Here is how to "eagerly" join fetch a child object using HQL, which is done in a single query.
select o from Timesheet o left join fetch o.activities where o.employee.id=? and o.date=? 
Aggregates can be easily calculated on child objects using a HQL query like this:
select timesheet, sum(activity.hours) from Timesheet timesheet join timesheet.activities activity where timesheet.timesheetId = 1 group by timesheet.timesheetId, timesheet.date, timesheet.employee.employeeId
This query needs slightly different handling in code as it returns a List of Object[] arrays, rather than a List of entities.
Query query = session.createQuery("select timesheet, sum(activity.hours) from Timesheet timesheet join timesheet.activities activity where timesheet.timesheetId = 1 group by timesheet.timesheetId, timesheet.date, timesheet.employee.employeeId");
List<Object[]> results = query.list();
for (Object[] result : results) {
  Timesheet timesheet = (TimesheetData)result[0];
  BigDecimal hours = (BigDecimal)result[1];
}
So my conclusion - views can be used in Hibernate and can be made to work well with the level 2 cache. But I would strongly advise not doing it if you can avoid it, as it "clutter" your domain model with redundant psuedo-entities. It's like the object-oriented version of denormalised data!

Wednesday 27 January 2010

Automated Integration Testing with Maven, Selenium, Failsafe, Jetty and DBUnit

Most Maven users are aware that unit tests can be executed as part of the automated build process. Maven can also automate integration tests, which are run as part of the “integration-test” and “verify” phases of the Maven build process. This article shows how to automate the integration tests using a number of useful Maven plug-ins. Integration testing tests groups of software modules (as opposed to unit testing, which tests individual units). It is intended to catch problems that arise when modules developed in isolation are assembled and used together, which is often the case when an application is being built by a team of developers. It also encompasses testing components within a container, especially if that container has been “mocked” in the unit tests. For example, a Spring controller might be unit tested with the MockHttpServletRequest and MockHttpServletResponse within the spring-test module. Business logic such as Spring service classes might have been mocked as well. An integration test in this scenario would involve firing real HTTP requests at the Spring controller running inside an application server such as Jetty or Tomcat.

The first consideration is how to create integration tests. Depending on how you define them, they could be standard NUnit tests or they could be Cactus or HTTPUnit type tests which call code executing from within the application server. However, Selenium offers a simple alternative to these approaches that can be easily integrated with Maven. Selenium consists of an IDE (a Firefox add-on) that can be used to record and automate actions (such as clicking links and selecting options in a select box) made within the browser. These can be then exported in a number of formats, including as a JUnit test (in fact, a SeleneseTestCase which extends TestCase). I’m aware that this approach to integration testing verges on functional testing. However, I think the boundaries between unit, integration and functional testing are blurry If it makes you feel any better, pretend this blog is called "Automated Functional Testing with Maven, Selenium, Failsafe, Jetty and DBUnit".

Here’s quick overview of how it all works. There are plenty of good tutorials about Selenium and using the IDE to write tests, so I won’t go into it here. After you have recorded your test case in the IDE, you can export it in Java format.
public class MyITCase extends SeleneseTestCase {

public void setUp() throws Exception {
 setUp("http://localhost:8080/", "*firefox");
}

public void testMy() throws Exception {
 selenium.open("/myapp/login.htm");
 selenium.type("j_username", "percy.project-manager");
 selenium.type("j_password", "password");
 selenium.click("//button[@type='submit']");
 selenium.waitForPageToLoad("30000");
 selenium.click("link=Client list");
 selenium.waitForPageToLoad("30000");
 selenium.click("link=View");
 selenium.waitForPageToLoad("30000");

}

}
In order to play-back the SeleneseTestCase, the Selenium Maven plug-in is needed. This is a “server” which runs an instance of the browser to be remote controlled by the SeleneseTestCase. The plug-in starts the Selenium server in readiness for test cases during the pre-integration-test phase and stops it afterwards (in post-integration-test).

org.codehaus.mojo
selenium-maven-plugin
1.0

 
  start-pre-integration
  pre-integration-test
  
   start-server
  
  
   true
  
 
 
  stop
  post-integration-test
  
   stop-server
  
 


In addition to needing the Selenium server, you will need a method to fire off the integration tests during the “integration-test” phase of the Maven build. Obviously, you could use the Surefire plug-in for this. However, the configuration of the plug-in gets a bit more tricky as you need to exclude the unit tests from the integration test and vice verse – especially the integration tests during unit testing as the Selenium server (and Jetty) won’t be running during the unit test phase.

There is a way to do this by using inclusion and exclusion filters within the configuration of the Surefire plugin and I have seen several explanations of how to do this. However, there is a fork of the Surefire plugin called Failsafe which is designed for integration testing. By default, it only runs tests with that contain IT and ITCase in the name. The main benefit is that the Failsafe plugin will continue to run after a test failure or error. That may seem to be a bit strange, but it is intentional. It is to ensure that the post-integration-test phase is executed, which might perform vital clean-up and tear-down operations that should run after the tests are finished. Additionally, it seems to have an enhanced class loader architecture compared to Surefire to handle some more exotic test scenarios – but that’s not relevant to this discussion.

Here is the necessary configuration for the Failsafe plugin.

org.codehaus.mojo
failsafe-maven-plugin
2.4.3-alpha-1

 
  integration-test
  
   integration-test
  
 
 
  verify
  
   verify
  
 


Now we have created our integration tests, and have a means of playing them back during the integration-test phase of the Maven build. However, we also need to fire up an application server to run the application itself during the integration-test phase. For this, the Jetty plug-in is ideal. It can be configured to start during the pre-integration-test phase and stop during the post-integration-test phase.


org.mortbay.jetty
maven-jetty-plugin
6.1.16

 10
 8005
 STOP


 
  start-jetty
  pre-integration-test
  
   run
  
  
   0
   true
  
 
 
  stop-jetty
  post-integration-test
  
   stop
  
 


I recommend using the jetty:run goal rather than jetty:run-war or jetty:run-exploded (although both of these work too). That is because the latter two goals cause the unit tests to run a 2nd time when the application folders are assembled in the target/ directory. However, if you don’t mind sitting through a 2nd run through of your unit tests then this doesn’t matter.

At this point you might be happy to stop, but there is one final step you might wish to take which is to initialise your database prior to the integration-test phase. This can be done with the SQL Maven plug-in (to create the schema) and the DBUnit plug-in (to insert test data). These can both be configured to run during the pre-integration-test phase. The reason for doing this is that if you are using assertions in your Selenium case (i.e. assertTrue( isElementPresent(//div[@id=’content’]/table[@id=’results’]/tbody/tr[3]/td[2])); then you need to be certain that the data in the database is going to be correct with respect to these assertions.

org.codehaus.mojo
sql-maven-plugin
1.2

 
  com.microsoft
  sqljdbc
  1.2.0
 


 com.microsoft.sqlserver.jdbc.SQLServerDriver
 jdbc:sqlserver://mssql2005server:1433;databaseName=MyDatabase;SelectMethod=cursor
 secret
 squirrel


 
  create-schema
  pre-integration-test
  
   execute
  
  
   true
   
    src/main/database/schema-mssql.sql
   
  
 


DBUnit configuration example.

org.codehaus.mojo
dbunit-maven-plugin

 
  com.microsoft
  sqljdbc
  1.2.0
 


 com.microsoft.sqlserver.jdbc.SQLServerDriver
 jdbc:sqlserver://mssql2005server:1433;databaseName=MyDatabase;SelectMethod=cursor
 secret
 squirrel
 src/test/resources/web-test-data.xml
 MSSQL_CLEAN_INSERT
 flat


 
  pre-integration-test
  
   operation
  
 


Hope it helps!