|
Calling Your Validators
Now that your validators are complete, how do you call them? The most effective way is to use Spring
aspect oriented programming (
AOP). AOP is a
large subject, so we’ll only cover what you need to know right now.
In a nutshell, AOP allows you to implement cross-cutting concerns in ways that are not destructive
or imposing to your existing code base. The power in AOP's usage is it's ability to select a
location within an application, called a pointcut. Once a pointcut has been located, advice can be
applied. Advice is what you intend to perform at the pointcut, things like logging, validation,
security, etc. AOP is applicable in many situations, but in this case, you want to validate the
TaskService's method arguments if they are supported by a validator. Additionally, you don't need to
limit your service—you can apply validation to all service methods with at least one argument.
Basically, you need a way to intercept method calls while having knowledge of the arguments passed
to that method. Thankfully, Spring has an interceptor for the job:MethodInterceptor.
When implemented, the MethodInterceptor interface provides just about everything you need to know
about a method invocation as well as the opportunity to perform validation before a method's call.
If a validation error has occurred, you’ll throw a ValidationException like the one
shown below. If a ValidationException occurs, method invocation will not, thus giving
you peace-of-mind knowing that invalid data will not reach the task service implementation.
<ValidationException>
package jbriscoe.article.spring.validation.exception;
import java.util.List;
import org.springframework.validation.Errors;
public class ValidationException extends RuntimeException {
private List<Errors> errors;
public ValidationException(final List<Errors> errors) {
this.errors = errors;
}
public List<Errors> getErrors() {
return errors;
}
public void setErrors(final List<Errors> errors) {
this.errors = errors;
}
}
The ValidationException class contains a List of Spring validation errors that have
occurred, which should provide your calling code all the information it needs to determine what
validation failed. ValidationException is a RuntimeException that will not
force the service implementation to declare that it throws a ValidationException.
However, the TaskService interface must be updated declaring that it throws a ValidationException.
< Final TaskService Interface>
public Boolean createTask(final Task task) throws ValidationException;
Implementing the validation method interceptor is relatively simple. However, an object that is
supported by a validator (Task, Employee, etc) can contain any number of nested fields
that are themselves supported by a validator. For instance, the Address class is
supported by the AddressValidator but, in order to validate it, you’ll need code that
recursively inspects a validator supported class and it's fields, and it's fields, and so on, until
all fields that can be validated have been. Therefore, no limitations have been made on the depth of
objects that can be validated. The only limitation is: a class you would want to be validated must
be contained by a class that can be validated. For example, suppose the Employee class
contained another object called Floor. If Floor did not have a validator,
any fields within Floor that have a validator will not be validated—including the Floor
class. The final implementation of MethodInterceptor is shown in
Listing 8.
The MethodArgValidationInterceptor contains a List of Validators (TaskValidator,
EmployeeValidator, and AddressValidator). You need to update the tasklist-core.xml
file, which tells Spring about the new interceptor and where to apply it. As stated earlier,
pointcuts describe a location to apply advice. The RegexpMethodPointcutAdvisor is one
of a few pointcuts Spring offers. With it, you specify the task service with a regular expression
like jbriscoe.article.spring.validation.service.*. This regular expression allows you
to select any class within the service package. You’ll use the RegexpMethodPointcutAdvisor
in this app as it meets all of the task service's needs. Now that you’ve selected a pointcut, you
need to provide the advice by setting the advice property to the MethodArgValidationInterceptor
bean. The updated tasklist-core.xml file is shown below:
<Update tasklist-core.xml>
<bean id="serviceValidationAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="pattern" value="jbriscoe.article.spring.validation.service.*" />
<property name="advice">
<bean class="jbriscoe.article.spring.validation.interceptor.MethodArgValidationIntercepto r">
<property name="validators">
<list>
<bean class=
"jbriscoe.article.spring.validation.validator.TaskValidator" />
<bean class=
"jbriscoe.article.spring.validation.validator.EmployeeValidator" />
<bean class=
"jbriscoe.article.spring.validation.validator.AddressValidator" />
</list>
</property>
</bean>
</property>
</bean>
<bean id="advisorAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
There’s enough in place now to perform a test—this time with invalid data. When you execute the createTask
method on the task service this time, expect the task creation to not occur and receive a ValidationException.
Create a new invalid Task object in the tasklist-test.xml file similar to
the one shown in
Listing 9.
Add the new task object as a protected property, to be injected into the TaskServiceTest.
Then add a new test with new assertions (
Listing 10).
Run your test case. You should see output similar to that in
Figure 3.

Figure 3. Running Your Last Test Case:
You should see similar output to this when you run your last test case.
A Consistent—If Not Perfect—Solution
This is one approach to validating your objects in a Spring Framework application. The task of
validating data will never go away—you’ll always need to address it in some way or another and
there is no silver bullet. But by using Spring and AOP together, you can at least ensure that your
applications handle it consistently.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|