Thursday, November 28, 2013

Bookmark and Share

Note: This article originally appeared on mapstruct.org. In order to spread the word on MapStruct I thought it's a good idea to post it in this blog, too.

It is my great pleasure to announce the release of MapStruct 1.0.0.Alpha2.

This took us a bit longer than expected, but the new release offers quite a few exciting new features we hope you'll enjoy. The JARs have already been synched to Maven Central. The coordinates are:

Alternatively you can get a distribution bundle from SourceForge.

Beside several new mapping features (e.g. combining several sources into one target object) the release provides integration with CDI and Spring to make the retrieval of mapper objects more comfortable. We've added several new implicit data type conversions and there is now also support for converting Map objects.

Let's have a closer look at some of the additions.

Advanced mapping features

When working with data transfer objects (DTO) to pass data from the backend to the client, it is common to have one DTO which transports the data from several entities. For this purpose MapStruct supports now mapping methods with several source methods. The following shows an example:

1
2
3
4
5
6
7
8
9
@Mapper
public interface OrderMapper {

    @Mappings({
        @Mapping(source = "order.name", target = "name"),
        @Mapping(source = "houseNo", target = "houseNumber")
    })
    OrderDto orderAndAddressToOrderDto(Order order, Address deliveryAddress);
}

As for single parameter methods all attributes are mapped by name from the source objects to the target object, performing a type conversion if required. In case a property with the same name exists in more than one source object, the source parameter from which to retrieve the property must be specified using the @Mapping annotation as shown for the name property.

One of the core principles in MapStruct is type-safety. Therefore an error will be raised at generation time when such an ambiguity is not resolved. Note that when mapping a property which only exists once in the source objects to another target property name, it is optional to specify the source parameter's name.

Also related to type-safety and correctness of generated mappings is the new option to raise an error in case an attribute of the mapping target is not populated, as this typically indicates an oversight or configuration error. By default a compiler warning is created in this case. To change this e.g. into a compile error instead, the unmappedTargetPolicy property can be used like this:

1
2
3
4
5
@Mapper(unmappedTargetPolicy=ERROR)
public interface OrderMapper {

    //...
}

In some cases it is required to update an existing object with the properties from a given source object instead of instantiating a new target object. This use case can be addressed with help of the @MappingTarget annotation which denotes one method parameter as the target of the mapping like this:

1
2
3
4
5
@Mapper
public interface OrderMapper {

    void updateOrderEntityFromDto(OrderDto dto, @MappingTarget Order order);
}

Instead of instantiating a new Order object, the generated implementation of updateOrderEntityFromDto() method will update the given order instance with the attributes from the passed OrderDto.

More implicit type conversions

Several new implicit type conversions have been added for the case that the source and target type of a mapped property differ. BigDecimal and BigInteger can now automatically be converted into other numeric types as well as into String. You can finde a list of all supported conversions in the reference documentation.

Please beware of a possible value or precision loss when performing such conversions from larger to smaller numeric types. It is planned for the next milestone to optionally raise a warning in this case.

It is now also possible to convert Date into String and vice versa. For that purpose a new parameter has been added to the @Mapping annotation which allows to specify a format string as interpreted by SimpleDateFormat:

1
2
3
4
5
6
@Mapper
public interface OrderMapper {

    @Mapping(source="orderDate", dateFormat="dd.MM.yyyy HH:mm:ss")
    OrderDto orderToOrderDto(Order order);
}

Integration with CDI and Spring

The recommended way for obtaining mapper instances in the 1.0.0.Alpha1 release was to use the Mappers factory.

Alternatively it is now also possible to work with dependency injection. To make this possible, MapStruct can generate mappers which are CDI or Spring beans, based on which flavor of DI you prefer. In the following example MapStruct is adviced to make the generated mapper implementation a CDI bean by specifying "cdi" via the componentModel attribute in the @Mapper annotation:

1
2
3
4
5
@Mapper(componentModel="cdi")
public interface OrderMapper {

    //...
}

This allows to obtain an order mapper simply via @Inject (provided you have CDI enabled within your application):

1
2
@Inject
private OrderMapper orderMapper;

Note that all other mappers a generated mapper class references are also obtained via the configured component model. So if you e.g. hook in hand-written mapper classes via @Mapper#uses() make sure that these mappers are compliant with the chosen component model, e.g. are CDI beans themselves. Refer to the documentation which describes all the specifics in detail.

On a related note, if you prefer to work with the Mappers factory as before, you'll have to adapt your imports because this class has been moved to the new package org.mapstruct.factory.

Further info

This concludes our tour through the new features in MapStruct 1.0.0.Alpha2. You can find the complete list of addressed issues in the change log on GitHub. The reference documentation has been updated to cover all new functionality.

If you have any kind of feedback please make sure to let us know. Either post a comment here or open a discussion in the mapstruct-users group. Bugs and feature requests can be reported in the issue tracker and your pull request on GitHub is highly welcome! The contribution guide has all the info you need to get started with hacking on MapStruct.

Many thanks to Andreas Gudian and Lukasz Kryger who contributed to this release, that's awesome!

Monday, June 3, 2013

Bookmark and Share

It is a great pleasure for me to announce the first release of the MapStruct project.

MapStruct is a code generator which simplifies the implementation of mappings between Java bean types by generating mapping code at compile time, following a convention-over-configuration approach. Unlike reflection-based mapping frameworks MapStruct generates mapping code at build time which is fast, type-safe and easy to understand.

The official release announcement describes in detail what MapStruct can do for you and what's on the roadmap for the next releases. The release is available on SourceForge and Maven Central.

Give it a try, your feedback is highly welcome via the mapstruct-users Google group!

Wednesday, March 6, 2013

Bookmark and Share

Every once in a while it happens to me that TestNG tests fail to launch in Eclipse when starting in debug mode (run mode works fine). The progress bar freezes at 57% and Eclipse indefinitely hangs.

Some googling brought me to to this bug in the TestNG issue tracker. As it seems, the issue is caused by a conflict between the TestNG version used as (Maven) dependency in the project under test and the TestNG version used by the TestNG Eclipse plug-in. People commented at the issue that it helped for them to create a new Eclipse workspace. As I wanted to avoid that, I had a look into the .metadata folder of my workspace, searching for things which might be the potential cause.

And indeed I stumbled upon the folder WORKSPACE_DIR/.metadata/.plugins/org.testng.eclipse/. After deleting this folder and restarting Eclipse, TestNG tests would launch in debug mode again as expected.

Sunday, November 18, 2012

Bookmark and Share

Watching a talk from Square's CTO Bob Lee, I just learned about Dagger, a new dependency injection framework for Java and Android which is currently in the works at Square, Inc.

Considering the number of existing DI solutions in the Java space – e.g. CDI, Google Guice and Spring – one might wonder whether the world really needs yet another DI framework. According to Bob's talk, Dagger (a pun on "directed acyclic graph") is the attempt to create a modern and fast DI framework based on the insights gained during development and usage of Guice (Bob was the founder of the Guice project at Google). And indeed does Dagger come up with some quite interesting ideas which I'd like to discuss in more detail in the following.

Overview

Dagger is centered around the annotations for dependency injection defined by JSR 330 (which Bob Lee co-led). This is a good thing because it increases portability of your code between different DI solutions.

Dependencies are retrieved by annotating fields or constructors with @Inject:

1
2
3
4
5
6
7
8
9
10
11
public class Circus {

    private final Artist artist;

    @Inject    
    public Circus(Artist artist) {
        this.artist = artist;
    }

    //...
}

To satisfy dependencies, Dagger creates the required objects using their @Inject-annotated constructor (in turn creating and passing any dependencies) or the default no-args constructor.

Where that's not possible (e.g. when an implementation of an interface needs to be injected) provider methods can be used. Provider methods must be annotated with @Provides and be defined in a class annotated with @Module like this:

1
2
3
4
5
6
@Module
public class CircusModule {
    @Provides Artist provideArtist() {
        return new Juggler();
    }
}

The @Module annotation is also used to define the entry point of an application:

1
2
3
4
@Module( entryPoints=CircusApp.class )
public class CircusModule {
    //...
}

This entry point represents the root of the object graph managed by Dagger. As we'll see in a moment, explicitly defining the root allows for compile-time validation of the dependency graph. An instance of the entry point type can be retrieved from the ObjectGraph class, passing the module(s) to create the graph from:

1
2
3
ObjectGraph objectGraph = ObjectGraph.create(new CircusModule());
CircusApp circus = objectGraph.get(CircusApp.class);
circus.startPerformance();

Dagger also also provides support for qualifiers, lazy injection, injection of providers and more. The project's web site gives a good overview. Apart from that it's interesting to see what Dagger deliberately does not support to avoid an increased complexity:

  • Circular dependencies between objects
  • Method injection
  • Custom scopes (Objects are either newly created for each injection or singleton-scoped)

Code generation

DI frameworks usually make intensive use of reflection to examine annotations, find injection points, create managed objects etc. While reflection today isn't as expensive as it used to be in earlier years, it still can take a considerable amount of time to create large object graphs with lots of dependencies.

Dagger tries to improve upon that with the help of code generation. It provides a JSR 269 based annotation processor which is used at compile time to create an adapter class for each managed type. These adapter classes contain all the logic required at run time to set up the object graph by invoking constructors and populating references to other objects, without making use of reflection.

This approach promises performance benefits over reflection-based ways for creating object graphs typically used by DI frameworks. On my machine Dagger needed roughly half the time to initialize the graph of the CoffeeApp example using the generated classes compared to using reflection (which it also supports as fallback). Of course this is by no means a comprehensive benchmark and can't be compared with other frameworks but it surely shows the potential of the code generation approach.

The annotation processor also performs a validation of the object graph and its dependencies at compile time. So if for instance no matching type (or more than one) can be found for a given injection point, the build will fail with an error message describing the problem. This helps in reducing turn-around times compared to discovering this sort of error only at application start-up. Implementing this sort of checks using an annotation processor makes them available in IDEs (which typically can integrate annotation processors) as well as headless builds, e.g. on a CI server.

Object graph visualization

Not mentioned in the documentation, Dagger also provides an annotation processor which generates a GraphViz file visualizing the object graph. This may be useful to get an understanding of unknown object graphs. The following shows the graph from the CoffeeApp example:

Summary

Dagger is a new dependency injection framework for Java and Android.

While it's still in the works (the current version is 0.9 and there are still some apparent bugs), I find the concept of using an annotation processor for validating the object graph at compile time and generating code for a faster initialization at runtime very interesting. In particular on mobile devices fast start up times are essential for a good user experience.

I also like the idea of leaving out features which might provide some value but would add much complexity. One thing I'm missing though is some sort of interceptor or decorator mechanism. This would be helpful for implementing typical cross-cutting concerns.

It'll definitely be interesting to see how the code generation approach works out in practice and whether other DI solutions possibly adapt that idea.

Wednesday, August 29, 2012

Bookmark and Share

Note: This post originally appeared on beanvalidation.org. Please post any feedback over there.

Now that everybody is returning from their summer holidays, also the Bean Validation team is getting back to their desks in order to work with full steam towards revision 1.1.

As you know, the largest new feature will be method validation, that is the validation of method parameters and return values using constraint annotations. Bean Validation 1.1 early draft 1 lays the ground for this, and right now we're tackling some advanced questions still open in that area (btw. if you haven't yet tried out the reference implementation of ED1, this is the perfect time to do so and give us your feedback).

The problem

One question the EG currently is discussing is whether and, if so, how a refinement of method constraints should be allowed in sub-types. That is, if a class implements a method of an interface or overrides a method from a super class, should the sub-type be allowed to place any additional constraints?

The current draft defines the following rules for such cases (see the draft document for all the gory details):

  • No parameter constraints may be specified in addition to those constraints defined on the method in the interface or super class.
  • Return value constraints may be added in sub-types.

The rationale

The rationale behind this is the principle of behavioral sub-typing, which demands that wherever a given type T is used, it should be possible to replace T with a sub-type S of T. This means that a sub-type must not strengthen a method's preconditions (by adding parameter constraints), as this might cause client code working correctly against T to fail when working against S. A sub-type may also not weaken a method's postconditions. However, a sub-type may strengthen the method's postconditions (by adding return value constraints), as client code working against T still will work against S.

Can you show me some code, please?

To give you an example, the following shows a constraint declaration considered illegal as of the current draft, as parameter constraints are added to the placeOrder() method in a sub-class of OrderService:

1
2
3
4
5
6
7
8
9
10
11
12
public class OrderService {
    void placeOrder(@NotNull String customerCode, @NotNull Item item, int quantity) { ... }
}

public class SimpleOrderService extends OrderService {

    @Override
    public void placeOrder(
        @Size(min=3, max=20) String customerCode,
        Item item,
        @Min(1) int quantity) { ... }
}

Alternatives

While this approach works, follows principles of clean OO design and also is employed by other Programming by Contract solutions, some voices in the EG expressed doubts whether the handling of parameter constraints isn't too restrictive and thus may limit innovation in that area. In particular with respect to legacy code, the question was raised whether it shouldn't be allowed to add parameter constraints in sub-types.

One example may be a legacy interface, which technically has no constraints (that is, no parameter constraints are placed on its methods), but comes with a verbal description of preconditions in its documentation. In this case an implementor of that interface might wish to implement this contract by placing corresponding constraint annotations on the implementation.

An open question in this situation is what should the behavior be if the interface is being constrained afterwards?

Give use your feedback!

So what do you think, should such a refinement of parameter constraints be allowed or not? Possible alternatives:

  • allow such a refinement by default
  • have some sort of switch controlling the behavior (either standardized or provider-specific)

As there are pro's and con's of either approach, we'd very interested in user feedback on this.

Let us know what you think by posting a comment directly to this blog, shooting a message to the mailing list or participating in this Doodle vote. Which use cases you have encountered come to mind where the possibility to refine parameter constraints may help you?

Sunday, July 1, 2012

Bookmark and Share

While thinking about how to take advantage of Bean Validation within JavaFX 2 based applications, I just learned that JavaFX is actually part of the JDK installation since Java SE 7 Update 2. The latest JDK (Update 5) comes with JavaFX 2.1.1.

This makes it very easy to use the JavaFX API within Maven based applications; all what's required is to add the following dependency to your POM file:

1
2
3
4
5
6
7
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>javafx-runtime</artifactId>
    <scope>system</scope>
    <version>2.1.1</version>
    <systemPath>${java.home}/../jre/lib/jfxrt.jar</systemPath>
</dependency>

That was simple :)

Now to the bad news: as it seems the installation doesn't contain the JavaFX API sources or JavaDocs. But that's not really a problem, as a ZIP with the sources can be downloaded from OpenJFX's Mercurial server and the latest Javadocs can be found here.

Sunday, June 10, 2012

Bookmark and Share

The Spring framework has in general an excellent documentation. One exception to me is the reference guide's chapter on Spring AOP, which I personally find not as comprehensible as other parts of the documentation.

What I'm missing in particular is a complete example demonstrating how to use Spring AOP together with AOP Alliance MethodInterceptors. Where possible, I prefer to use AOP Alliance compliant interceptors over other Spring AOP advice types, as they foster interoperability with other AOP frameworks compatible with the AOP Alliance API, such as Google Guice.

So without further ado, an example for using AOP Alliance method interceptors with Spring AOP is shown in the following.

First define an interceptor by implementing the interface org.aopalliance.intercept.MethodInterceptor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component
public class InvocationCountInterceptor implements MethodInterceptor {

    private AtomicLong invocationCount = new AtomicLong();

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        invocationCount.incrementAndGet();
        return invocation.proceed();
    }

    public AtomicLong getInvocationCount() {
        return invocationCount;
    }
}

By specifying the @Component stereotype annotation, the interceptor is enabled to be detected automatically by the Spring container using component scanning.

Now the types/methods to which the interceptor shall be applied need to be configured. Using Spring's AOP schema, this is done by defining an advisor which references the interceptor bean and links it with a pointcut expression describing the targeted methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd      
    ">

    ...
    <aop:config>
        <aop:advisor advice-ref="invocationCountInterceptor" pointcut="within(de.gmorling.moapa.springaop.service..*)"/>
    </aop:config>
    ...

</beans>

Here the interceptor is applied to all invocations of methods defined within the de.gmorling.moapa.springaop.service package and its sub-packages. But the pointcut could also be more fine-grained and match only methods on specific types or even single methods.

If several interceptors shall be bound to the same pointcut, the pointcut expression can also be defined separately and referenced from multiple advisors like so:

1
2
3
4
5
6
7
...
<aop:config>
    <aop:pointcut id="serviceLayer" expression="within(de.gmorling.moapa.springaop.service..*)"/>
    <aop:advisor advice-ref="invocationCountInterceptor" pointcut-ref="serviceLayer"/>
    <aop:advisor advice-ref="anotherInterceptor" pointcut-ref="serviceLayer"/>
</aop:config>
... 

Note that the AspectJ weaver JAR and – when applying interceptors to classes – CGLIB 2 need to be on the class path. A complete sample Maven project can be found on GitHub.

Sunday, October 9, 2011

Bookmark and Share

While working on a little pet project based on OSGi I wanted to use the Pax Runner Eclipse plug-in to launch my OSGi application on the Apache Felix OSGi framework.

Unfortunately this attempt resulted in the following error:

1
2
3
4
5
6
7
8
9
10
java.lang.NoClassDefFoundError: org/eclipse/pde/internal/ui/launcher/LaunchArgumentsHelper
at org.ops4j.pax.cursor.Utils.getVMArgsOptions(Utils.java:216)
at org.ops4j.pax.cursor.LaunchConfiguration.getProgramArguments(LaunchConfiguration.java:156)
at org.eclipse.pde.launching.AbstractPDELaunchConfiguration.launch(AbstractPDELaunchConfiguration.java:72)
at org.eclipse.pde.launching.OSGiLaunchConfigurationDelegate.launch(OSGiLaunchConfigurationDelegate.java:47)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:853)
at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:702)
at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:923)
at org.eclipse.debug.internal.ui.DebugUIPlugin$8.run(DebugUIPlugin.java:1126)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

This looked pretty much like an incompatability between the Pax Runner plug-in and the Eclipse platform. And indeed the plug-in unfortunately doesn't seem to keep up with PDE-internal changes in recent Eclipse versions due to limited developer resources.

Further googling then led me to PAXRUNNER-353 at Pax Runner's issue tracker.

The ticket itself is not yet resolved, but the good news is that Christian Baranowski (whom I had the pleasure to meet during the OSGi code camp last week) created a fork on GitHub fixing the issue for now. So let's hope that this fix gets quickly merged into the main branch.

Until then Christian even has established a temporary Eclipse update site which makes upgrading the plug-in to the forked version a breeze.

So my kudos go to Christian (for fixing the plug-in) and to GitHub (for making forking easy) :-)

Monday, August 1, 2011

Bookmark and Share

Maybe you know it already: last week JSR 349 successfully passed the review ballot, meaning that the work on a new release of the Bean Validation API has officially started.

I'm really excited about this, because I've got the pleasure to be part of the JSR 349 expert group. I haven't been member of such a comitee before, so I guess this will be exciting times and I'll surely learn a whole lot of new things during the work on the specification.

What's most important right now is your feedback: what new features would you like to see included in Bean Validation 1.1, what problems did you face when working with BV 1.0 which you think should be addressed in the next release?

Your input and feedback is highly welcome at several places:

  • The Bean Validation feedback forum is a good platform for discussing ideas, requests for clarifications etc.
  • For concrete feature requests or bug reports you can open an issue at the Bean Validation issue tracker

As a starting point you might want to check out these two blog posts by Emmanuel Bernard (the Bean Validation spec. lead), where a lot of possible features are discussed.

Finally I'd like to point your attention to http://beanvalidation.org/, the JSR's official web site. There you'll find everything related, e.g. a news section, the road map and also the Bean Validation 1.0 spec. document for reference.

Now it's up to you – tell us what would YOU like to see included in Bean Validation 1.1.

Sunday, May 8, 2011

Bookmark and Share

Note: This article originally appeared on in.relation.to as part of the Seam Module Spotlight series. In order to spread the word on Seam Validation I thought it might be a good idea to post it in this blog, too.

Seam Validation is a relatively new Seam module which provides an integration between Hibernate Validator which is the reference implementation of the Bean Validation standard (JSR 303) and CDI. The module's functionality falls into two areas:

  • Enhanced dependency injection services for validators, validator factories and constraint validators
  • Automatic validation of method parameters and return values based on Hibernate Validator's method validation API

Let's take a closer look at these features in the following.

Dependency injection services

The Bean Validation API is an integral part of the Java EE platform. So when running on a Java EE 6 compatible application server such as JBoss AS 6 you can easily retrieve Validator and ValidatorFactory instances via dependency injection.

Unfortunately this is not working out of the box when running in non-EE environments such as plain servlet containers. But don't worry, Seam Validation comes to the rescue. By adding the module as dependency to your project, validators and validator factories can be obtained using @Inject:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Foo {

    @Inject
    private Validator validator;

    public void doSomething() {

        Bar bar = new Bar();

        Set<ConstraintViolation<Bar>> constraintViolations = validator.validate(bar);
        //examine the violations ...
    }
}

But Seam Validation goes one step further and enables dependency injection also within constraint validator implementations. For instance we might have a custom constraint @ValidLicensePlate which is used to ensure that a car has a license plate which is properly registered, still valid etc.:

1
2
3
4
5
6
7
public class Car {

    @ValidLicensePlate
    private String licensePlate;

    //constructor, getter, setter etc.
}

In order to perform the required checks the constraint's validator invokes some sort of registration service (note: accessing external services can potentially be an expensive operation, so it may be a good idea to put the constraint into a separate validation group, but that's out of scope for this article). The Seam Validation module allows to inject this service into the validator as into any other CDI bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ValidLicensePlateValidator implements ConstraintValidator<ValidLicensePlate, String> {

    @Inject
    private RegistrationService registrationService;

    @Override
    public void initialize(ValidLicensePlate constraintAnnotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {

        if (value == null) {
            return true;
        }

        //delegate to registration service
        return registrationService.isValid(value);
    }
}

There is just on more step required before the @ValidLicensePlate constraint can be used: We have to register Seam Validation's constraint validator factory with the Bean Validation provider. This happens by putting a file named validation.xml with the following content into the META-INF folder of the application:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<validation-config 
    xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">

    <constraint-validator-factory>
        org.jboss.seam.validation.InjectingConstraintValidatorFactory
    </constraint-validator-factory>
</validation-config>

Method validation

The other main feature of Seam Validation besides dependency injection is the automatic validation of method parameters and return values based on the API for method validation introduced with Hibernate Validator 4.2 (note: at the time of writing Hibernate Validator 4.2 is released as Beta version, but no major changes are expected until the final release).

This API provides an easy-to-use facility for the "Programming by Contract" approach to program design based on the concepts defined by the Bean Validation API. That means that any Bean Validation constraint can be used to describe

  • the preconditions that must be met before a method may be invoked (by annotating method parameters with constraints) and
  • the postconditions that are guaranteed after a method invocation returns (by annotating methods).

Things should become clearer with an example:

1
2
3
4
5
6
7
8
9
@AutoValidating
public class RentalStation {

    @Valid
    public Car rentCar(@NotNull CustomerPK customerPK, @NotNull @Future Date startDate, @Min(1) int durationInDays) {

        //highly complex car rental business logic ...
    }
}

Here the following pre- and postconditions are applied onto the rentCar() method:

  • The customer's primary key may not be null
  • The rental start date must not be null and must be in the future
  • The rental duration must be at least one day
  • The returned object must be valid with respect to all constraints of the Car class

By annotating the class RentalStation with @AutoValidating, all these constraints are automatically validated by a method interceptor whenever the rentCar() method is invoked. If any of the constraints can't be validated successfully, a runtime exception describing the occurred constraint violation(s) is thrown.

This approach has several advantages over traditional parameter and return value checking:

  • The checks don't have to be performed by hand. This results in less boiler-plate code to write (and to read).
  • A method's pre- and postconditions are part of its API and generated documentation. It's not necessary to add comments such as "returns never null", as this information will automatically be put into the generated JavaDoc. This results in less redundancies and hence in less potential inconsistencies between implementation and documentation.

Future steps

This concludes our short tour through the Seam Validation module. If you feel like trying out the module yourself, the module home page is the right starting point. You might also be interested in the module's reference guide, and in case you found a bug or want to create a feature request the module's JIRA instance is the place to go.

Possible future developments of Seam Validation include a closer integration with other Seam 3 modules, the possibility to chose the validation groups to be used for method validation and the evaluation of standard bean constraints upon method validation.

Saturday, March 5, 2011

Bookmark and Share

I need your help.

To be more concise, I need your vote for the 2011 JBoss Community Recognition Awards.

These awards are an effort of JBoss/Red Hat to honor significant contributions to the JBoss community over the last year and I'm more than proud to say that I've been nominated in the "New Features" category for my contributions to Hibernate Validator.

So if you appreciate my work on Hibernate Validator – e.g. the HV annotation processor or the method validation feature I've built for HV 4.2 – or the Validation module for Seam 3 (I'll blog on this in a separate post) I've recently started, just head over to the poll and give me your vote. The voting is open until April, 2nd.

And if you really like my work, go and tell your friends that they should vote for me, too.

Just in case you feel like you need some more information to make a profound vote you might also check out my nominee description.

Another nomination I'd like to mention is the one of my fellow developer Kevin Pollet in the "Bug Fixes" category. He has done some really awesome work for HV 4.2. Besides fixing many bugs he implemented several new features like the integration with the Joda time API or the support for dynamic default group sequence definitions.

So when you (and your friends) have voted for me, don't forget to vote for Kevin, too :)

Sunday, January 16, 2011

Bookmark and Share

Earlier this week the first beta version of Hibernate Validator 4.2 was released. Hardy's announcement on in.relation.to describes in detail what's new in this release, so be sure to check it out.

One of the new features I'm really excited about is method validation, which I therefore would like to discuss in more detail in the following.

What's it about?

Up to now constraint annotations were only supported at fields or at getter methods for property constraints and at type declarations for class-level constraints.

With HV 4.2 it is now also possible to use constraint annotations for a programming style known as "Programming by Contract". More specifically this means that any Bean Validation constraints (built-in as well as custom constraints) can be used to specify

  • any preconditions that must be met before a method invocation (by annotating method parameters with constraints) and
  • any postconditions that are guaranteed after a method invocation (by annotating methods)

As example let's consider the following class from a fictitious video rental application:

1
2
3
4
5
6
7
8
9
public class MovieRepository {

    public @NotNull Set<Movie> findMoviesByTitle( 
        @NotNull @Size(min = 3) String title) {

        //search movie in database ...
    }   

}

The following pre- and postconditions will hold here (provided the method validation is triggered automatically by some integration layer, see below):

  • The title parameter is guaranteed to be not null and at least 3 characters long
  • The return set of movies is guaranteed to be not null

Compared to traditional ways of parameter or result value checking this approach has two big advantages:

  • These checks don't have to be performed manually, which results in less code to write and maintain. You'll never again have to throw IllegalArgumentExceptions or similar by hand.
  • The pre- and postconditions of a method don't have to be expressed again in the method's JavaDoc, since any of it's annotations will automatically be included in the generated JavaDoc. This means less redundancy which reduces the chance of inconsistencies between implementation and comments.

Method validation is not restricted to constraints related to parameters or to return values themselves. Using the @Valid annotation it is also possible to recursively validate parameters or return values:

1
2
3
4
5
6
7
8
public class UserRepository {

    public void persistUser(@NotNull @Valid User user) {

        //persist user in database ...
    }   

}

In this example not only the @NotNull constraint at the user parameter would be checked, but also any constraints defined at the User type. As known from standard Bean Validation the @Valid annotation could also be applied to array-, Iterable- and Map-typed parameters or return values.

The MethodValidator interface

For the purposes of method validation Hibernate Validator defines the new interface MethodValidator (any type or method names are working titles and might change until HV 4.2 is final), which provides methods for parameter and return value validation:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface MethodValidator {

    public <T> Set<MethodConstraintViolation<T>> validateParameter(
        T object, Method method, Object parameterValue, 
        int parameterIndex, Class<?>... groups);

    public <T> Set<MethodConstraintViolation<T>> validateParameters(
        T object, Method method, Object[] parameterValues, Class<?>... groups);

    public <T> Set<MethodConstraintViolation<T>> validateReturnValue(
        T object, Method method, Object returnValue, Class<?>... groups);

}

To get hold of a method validator, unwrap an instance of HV's Validator implementation as follows:

1
2
3
4
5
MethodValidator validator = Validation.byProvider( HibernateValidator.class )
    .configure()
    .buildValidatorFactory()
    .getValidator()
    .unwrap( MethodValidator.class );

All of MethodValidator's methods return a set of MethodConstraintValidations which describe in detail any constraint violations that occurred during validation. MethodConstraintValidation extends the standard ConstraintViolation and provides additional information such as method and parameter causing a constraint violation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface MethodConstraintViolation<T> extends ConstraintViolation<T> {

    public static enum Kind {

        PARAMETER,

        RETURN_VALUE
    }

    Method getMethod();

    Integer getParameterIndex();

    String getParameterName();

    Kind getKind();
}

Unfortunately the byte code of a Java program normally doesn't contain any information on parameter names, therefore getParameterName() for now returns synthetic names such as arg0 etc. For a future release we are investigating approaches for parameter naming, e.g. by leveraging JSR 330's @Named annotation. I created a JIRA issue for this, so if you have any feedback on this just add a comment to the ticket.

Triggering method validation

Hibernate Validator itself only provides the engine for method validation but it does not deal with triggering such a validation.

Instead this is typically done using frameworks/APIs which provide AOP or method interception services such as AspectJ or CDI. But also plain Java dynamic proxies can basically do the trick.

Typically such a validation interceptor does the following:

  • intercept each method call to be validated,
  • validate the invocation's parameter values,
  • proceed with the method invocation and
  • finally validate the invocation's return value.

If any of the two validation steps yields one ore more constraint violations the interceptor typically throws a MethodConstraintViolationException containing the constraint violations that have occurred.

Trying it out yourself

To see whether method validation works out as intended I started a project at GitHub called methodvalidation-integration which provides validation handlers for some interception technologies popular these days.

Currently there are implementations for CDI as well as Google Guice and an InvocationHandler which can be used with JDK dynamic proxies. I also plan to add support for Spring AOP/AspectJ when time permits.

To try method validation out yourself just get the bits from GitHub and have a look at the test in each of the sub-projects. Just give it a try and let me know how everything works.

Future steps

This post introduced the new method validation feature which will be part of Hibernate Validator 4.2. The first beta release contains the basic implementations of this, so we are more than interested in you feedback on this. Please report any bugs in HV's JIRA instance, any questions or ideas for improvement are also highly welcome in HV's forum.

For HV 4.2 Beta2 we plan to add documentation on the method validation feature to HV's reference guide which will also describe some advanced topics such as using method validation with group sequences etc. We will also add support for method level constraints to the constraint meta-data API.

Two further ideas scheduled for after 4.2 are providing the ability to specify method level constraints using XML and using the programmatic constraint configuration API.

Monday, December 27, 2010

Bookmark and Share

This is more a note to myself, but in case someone else wonders how to specify the active Maven profile in IntelliJ IDEA for projects containing several profiles, that's the way to go:

  • Open the "Maven Projects" window by selecting "Window" - "Tool Windows" - "Maven Projects"
  • Expand the "Profiles" node and select the profile you want to use
Bookmark and Share

One of the new features introduced with version 3.0 of the Spring framework is the Spring Expression Language or short "SpEL". This language is tailored for the needs when working with Spring and can be used when creating XML/annotation based Spring bean definitions for instance.

So I thought it would be nice if it was possible to use SpEL together with Hibernate Validator's @ScriptAssert constraint which allows to express validation routines using script or expression languages.

Unfortunately this does not work since currently no SpEL language binding for JSR 223 ("Scripting for the JavaTM Platform") exists. As @ScriptAssert's validator uses JSR 223 for expression evaluation at least for now SpEL can't be used along with @ScriptAssert (there is an issue in Spring's JIRA addressing this problem).

But as shown in previous posts it is very simple to create new constraint annotations for the Bean Validation API. So the idea is to build a new constraint @SpelAssert which resembles HV's @ScriptAssert but works with SpEL instead of the JSR 223 API.

Defining the annotation type is straight-forward:

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15

@Target({ TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = SpelAssertValidator.class)
@Documented
public @interface SpelAssert {


    String message() default "{de.gmorling.moapa.bvspel.SpelAssert.message}";

    Class<?>[] groups() default {};


    Class<? extends Payload>[] payload() default {};

    String value();


}

Besides the standard attributes message(), groups() and payload() mandated by the BV specification we define one more attribute value(), which takes the SpEL expression to evaluate.

Now let's come to the validator:

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
public class SpelAssertValidator implements

ConstraintValidator<SpelAssert, Object> {

    @Inject
    private ExpressionParser parser;

    private Expression expression;


    @Override
    public void initialize(SpelAssert constraintAnnotation) {

    String rawExpression = constraintAnnotation.value();


        if (rawExpression == null) {
            throw new IllegalArgumentException("The expression specified in @"

                + SpelAssert.class.getSimpleName() + " must not be null.");
        }

        expression = parser.parseExpression(rawExpression);
    }


    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        if (value == null) {

            return true;
        }

        return Boolean.TRUE.equals(expression.getValue(value, Boolean.class));

    }
}

In initialize() we use an ExpressionParser to parse the specified SpEL expression (so this happens only once) and evaluate the given object against it in isValid().

But wait a minute, where does the ExpressionParser come from, it is not instantiated here?

Right, the cool thing is Spring comes with it's own ConstraintValidatorFactory which performs dependency injection on constraint validators. A validator relying on that feature of course is not portable, but as this validator is based on SpEL and Spring anyways this is not an issue here.

In order to have this working a parser bean must be part of the Spring application context. We just register a SpelExpressionParser:

1

2
3
4
5
6
7
8
9
10

11
12
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="parser"
        class="org.springframework.expression.spel.standard.SpelExpressionParser"/>


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

This context also shows how to provide a BV Validator for dependency injection leveraging Spring's LocalValidatorFactoryBean.

Now let's have a look at the @SpelAssert constraint in action. The following shows the canonical example of a class CalendarEvent where the start date shall always be earlier than the end date:

1

2
3
4
5
6
7
8
9
10

@SpelAssert("startDate < endDate")
public class CalendarEvent {


    private Date startDate;

    private Date endDate;


    // getters, setters etc.

}

Note how SpEL allows dates to be compared using the "<" operator and that no alias for the evaluated bean is required, as all unqualified attribute/method names are resolved against the annotated object.

Finally we should have a test showing that the validator works as expected by validating a valid and an invalid CalendarEvent instance:

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration
public class SpelAssertTest {

    @Inject
    private Validator validator;


    private Date startDate;
    private Date endDate;

    @Before

    public void setUpDates() {

        Calendar start = Calendar.getInstance();
        start.set(2010, 13, 24);

        startDate = start.getTime();

        Calendar end = Calendar.getInstance();
        end.set(2010, 13, 26);

        endDate = end.getTime();
    }

    @Test
    public void validEvent() {


        CalendarEvent event = new CalendarEvent();
        event.setStartDate(startDate);
        event.setEndDate(endDate);

        assertTrue(validator.validate(event).isEmpty());

    }

    @Test
    public void invalidEventYieldsConstraintViolation() {

        CalendarEvent event = new CalendarEvent();

        event.setStartDate(endDate);
        event.setEndDate(startDate);

        Set<ConstraintViolation<CalendarEvent>> violations = 
            validator.validate(event);

        assertEquals(1, violations.size());

        ConstraintViolation<CalendarEvent> violation = 
            violations.iterator().next();
        assertEquals(

            "SpEL expression \"startDate < endDate\" didn't evaluate to true.",
            violation.getMessage());
    }

}

The complete sources for this post can be found at GitHub, so don't hesistate to give it a try or use it in your projects if you like. Any feedback or ideas for improvement are warmly welcome.

Wednesday, November 17, 2010

Bookmark and Share
At my day job we are using the SVN property "svn:keywords" to let SVN replace the string "$Id$" with author name, revision number etc. within each Java source file.

One can add this property automatically when creating new files with the help of SVN's auto props feature. But from time to time someone, e.g. a new developer not knowing about auto props, checks in files without having the "svn:keywords" property set.

So I wondered how to identify such files in the repository. SVN doesn't provide a command answering that question, you only can retrieve all files having a certain property set.

But no problem, some shell magic to the rescue:

1
comm -23 <(sort <(sed 's/\.\///g' <(find . -name "*.java"))) <(sort <(sed 's/ - Id//g' <(svn propget svn:keywords * -R)))

So what's happening here? The basic idea is to list those files with the svn:keywords property set (svn propget) and compare this to a list with all files (find).

The outputs of both commands are brought into the same format using sed, sorted and then passed as parameters to the comm command, which compares two input files to each other. The -23 parameter causes only those lines to be put out which are only contained in file1 but not in file2, which are exactly the names of those files lacking the "svn:keywords" property.

I tested the command successfully on Mac OS X, but I think it should work pretty much the same way on other Unix systems, too.

Sunday, August 15, 2010

Bookmark and Share

While developing an Eclipse plug-in for a small spare-time project of mine I wondered where to find the sources of the Java Development Tools (JDT). They used to be part of the Eclipse RCP/plug-in developers package in previous releases, but this isn't the case anymore with Eclipse 3.6 (Helios).

After some googling I found the reason: as of release 3.6 the RCP distribution (now named "Eclipse for RCP and RAP Developers") no longer contains any sources (except those for the actual platform plug-ins) in order to reduce the size of the download package.

If you want to get the sources for plug-ins such as JDT which are not part of the core platform you have to retrieve them separately. To do so you can use the new plug-in import wizard which allows to fetch source projects corresponding to plug-ins of the target platform directly from the Eclipse CVS.

Just open the "Plug-ins" view, right-click on the plug-in you want to retrieve (e.g. org.eclipse.jdt.ui) and select "Import as" > "Project from a Repository ...". Confirm the next dialog by clicking "Finish", and the check-out starts. Afterwards the new project will automatically replace the plug-in JAR as dependency in any dependent projects within your workspace.

Saturday, July 24, 2010

Bookmark and Share

In the last couple of days I spent some time experimenting a little bit with CDI, the standard of the Java EE 6 platform for dependency injection services.

I must say that I really like that spec, as it hits the sweet spot between specifying features that provide a value out of the box (type-safe DI, eventing, interceptor services etc.) and being open enough to allow people to build totally new stuff based on it (using portable extensions).

I've got the feeling we're going to see a lot of exciting things based on CDI within the near future. Actually this reminds me a bit of Java annotations. Having been introduced with Java 5, just over time people started using them for more and more use cases that had not been foreseen in the first place.

Anyway, to do something practical with CDI I built a small portable extension which allows to retrieve JSR 223 scripting engines using dependency injection.

Just annotate any injection points of type javax.script.ScriptEngine with one of the qualifier annotations @Language, @Extension or @MimeType. The following code extract shows an example of a JavaScript engine (for example the Rhino engine shipping with Java 6) being injected into some managed bean, where it can be used for arbitrary script evaluations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestScoped
public class MyBean {

    @Inject 
    @Language("javascript") 
    private ScriptEngine jsEngine;

    // ...

    public void foo() throws ScriptException {

        assert 42.0d == (Double)jsEngine.eval("2 * 21");
        // ...
    }
}

The extension can be found in my Maven repository. Just add the following dependency to your POM in order to use it:

1
2
3
4
5
<dependency>
    <groupId>de.gmorling.cdi.extensions</groupId>
    <artifactId>scripting-extension</artifactId>
    <version>0.1</version>
</dependency>

In case you want to take a look at the source code (which is just a few lines), you can check it out from GitHub. As always, any ideas for improvement or other feedback are highly appreciated.

Monday, June 28, 2010

Bookmark and Share

I'm very proud to report that today Hibernate Validator 4.1.0 Final has been released. Besides many bug fixes this release adds also a lot of new features to the code base.

The changes fall into four areas, which I'm going to discuss in detail in the following:

  • New constraint annotations
  • ResourceBundleLocator API
  • API for programmatic constraint creation
  • Constraint annotation processor

New constraint annotations

In addition to the constraints defined in the Bean Validation spec and those custom constraints already part of HV 4.0, the new release ships with the following new constraint annotations:

  • @CreditCardNumber: Validates that a given String represents a valid credit card number using the Luhn algorithm. Useful to detect mis-entered numbers for instance.
  • @NotBlank: Validates that a given String is neither null nor empty nor contains only whitespaces.
  • @URL: Validates that a given String is a valid URL. Can be restricted to certain protocols if required: @URL(protocol = "http") private String url;
  • @ScriptAssert: Allows to use scripting or expression languages for the definition of class-level validation routines.

Let's have a closer look at the @ScriptAssert constraint, which I'm particularly excited about as I have implemented it :-).

The intention behind it is to provide a simplified way for expressing validation logic that is based on multiple attributes of a given type. Instead of having to implement dedicated class-level constraints the @ScriptAssert constraint allows to express such validation routines in an ad hoc manner using a wide range of scripting and expression languages.

In order to use this constraint an implementation of the Java Scripting API as defined by JSR 223 ("Scripting for the JavaTM Platform") must be part of the class path. This is automatically the case when running on Java 6. For older Java versions, the JSR 223 RI can be added manually to the class path.

As example let's consider a class representing calendar events. The start date of such an event shall always be earlier than the end date. Using JavaScript (for which an engine comes with Java 6) this requirement could be expressed as follows:

1
2
3
4
5
6
7
8
9
@ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")
public class CalendarEvent {

    private Date startDate;

    private Date endDate;

    //...
}

So all you have to do is to specify a scripting expression returning true or false within the script attribute. The expression must be implemented in the language given within the language attribute. The language name must be the language's name as registered with the JSR 223 ScriptEngineManager. Within the expression the annotated element can be accessed using the alias _this by default.

The cool thing is that the @ScriptConsert constraint can be used with any other scripting language for which a JSR 223 binding exists. Let's take JEXL from the Apache Commons project for instance. Using Maven you only have to add the following dependency:

1
2
3
4
5
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl</artifactId>
    <version>2.0.1</version>
</dependency>

With JEXL dates can be compared using the "<" operator. Using a shorter alias for the evaluated object the constraint from above therefore can be rewritten as follows:

1
2
3
4
5
6
7
8
9
@ScriptAssert(lang = "jexl", script = "_.startDate < _.endDate", alias = "_")
public class CalendarEvent {

    private Date startDate;

    private Date endDate;

    //...
}

Very likely one will work with only one scripting language throughout all @ScriptAssert constraints of an application. So let's leverage the power of constraint composition to create a custom constraint which allows for an even more compact notation by setting the attributes lang and alias to fixed values:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Target({ TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
@ScriptAssert(lang = "jexl", script = "", alias = "_")
public @interface JexlAssert {

    String message() default "{org.hibernate.validator.constraints.ScriptAssert.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    @OverridesAttribute(constraint = ScriptAssert.class, name = "script")
    String value();
}

Note how the script attribute of the composing @ScriptAssert constraint is overridden using the @OverridesAttribute meta-annotation. Using this custom constraint the example finally reads as follows:

1
2
3
4
5
6
7
8
9
@JexlAssert("_.startDate < _.endDate")
public class CalendarEvent {

    private Date startDate;

    private Date endDate;

    //...
}

As shown the @ScriptAssert constraint allows to define class-level constraints in a very compact way.

But there is also a price to pay. As scripting languages are used, compile-time type-safety is lost. When for instance the startDate attribute is renamed the script expression would have to be adapted by hand. Also evaluation performance should be considered when validation logic is getting more complex.

So I recommend to try it out and choose what ever fits your needs best.

The ResourceBundleLocator API

The Bean Validation API defines the MessageInterpolator interface which allows to plug in custom strategies for message interpolation and resource bundle loading.

As it turned out, most users only want to customize the latter aspect (e.g. in order to load message bundles from a database) but would like to re-use the interpolation algorithm provided by Hibernate Validator.

Therefore Hibernate Validator 4.1 introduces the interface ResourceBundleLocator which is used by HV's default MessageInterpolator implementation ResourceBundleMessageInterpolator to do the actual resource bundle loading.

The interface defines only one method, in which implementations have to return the bundle for a given locale:

1
2
3
4
5
public interface ResourceBundleLocator {

    ResourceBundle getResourceBundle(Locale locale);

}

The ResourceBundleLocator to be used can be set when creating a ValidatorFactory:

1
2
3
4
5
6
7
ValidatorFactory validatorFactory = Validation
    .byProvider(HibernateValidator.class)
    .configure()
    .messageInterpolator(
        new ResourceBundleMessageInterpolator(
            new MyCustomResourceBundleLocator()))
    .buildValidatorFactory();

The default ResourceBundleLocator implementation used by Hibernate Validator is PlatformResourceBundleLocator which simply loads bundles using ResourceBundle.loadBundle(). Another implementation provided out of the box is AggregateResourceBundleLocator, which allows to retrieve message texts from multiple bundles by merging them into a single aggregate bundle. Let's look at an example:

1
2
3
4
5
6
7
8
9
10
11
HibernateValidatorConfiguration configuration = Validation
    .byProvider(HibernateValidator.class)
    .configure();

ValidatorFactory validatorFactory = configuration
    .messageInterpolator(
        new ResourceBundleMessageInterpolator(
            new AggregateResourceBundleLocator(
                Arrays.asList("foo", "bar"), 
                configuration.getDefaultResourceBundleLocator())))
    .buildValidatorFactory();

Here messages from bundles "foo" and "bar" could be used in constraints. In case the same key was contained in both bundles, the value from bundle "foo" would have precedence, as it comes first in the list. If a given key can't be found in any of the two bundles as fallback the default locator (which provides access to the ValidationMessages bundle as demanded by the JSR 303 spec) will be tried.

API for programmatic constraint creation

Using the Bean Validation API constraints can be declared using either annotations and/or XML descriptor files. Hibernate Validator 4.1 introduces a third approach by providing an API for programmatic constraint declaration.

This API can come in handy for instance in dynamic scenarios where constraints change upon runtime or for testing scenarios.

As example let's consider two classes, Customer and Order, from a web shop application for which the following constraints shall apply:

  • each customer must have a name
  • each order must have a customer
  • each order must comprise at least one order line

With help of the programmatic constraint API these constraints can be declared as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
ConstraintMapping mapping = new ConstraintMapping();

mapping
    .type(Order.class)
        .property("customer", ElementType.FIELD)
            .constraint(NotNullDef.class)
        .property("orderLines", ElementType.FIELD)
            .constraint(SizeDef.class)
                .min(1)
                .message("An order must contain at least one order line")
    .type(Customer.class)
        .property("name", ElementType.FIELD)
            .constraint(NotNullDef.class);  

As the listing shows the API is designed in a fluent style with the class ConstraintMapping as entry point. Constraints are declared by chaining method calls which specify to which property of which type which constraints should be added.

The API provides constraint definition classes such as NotNullDef etc. for all built-in constraints, which allow to access their properties (min(), message() etc.) in a type-safe way. For custom constraints you could either provide your own constraint definition class or you could make use of GenericConstraintDef which allows to identify properties by name.

Having created a constraint mapping it has to be registered with the constraint validator factory. As the programmatic API is not part of the Bean Validation spec, we must explicitely specify Hibernate Validator as the BV provider to be used:

1
2
3
4
5
6
Validator validator = Validation
    .byProvider(HibernateValidator.class)
    .configure()
    .addMapping(mapping)
    .buildValidatorFactory()
    .getValidator();

If you now use this validator to validate an Order object which has no customer set a constraint violation will occur, just as if the "customer" property was annotated with @NotNull.

Constraint annotation processor

The Hibernate Validator annotation processor might become your new favourite tool if you find yourself accidentally doing things like

  • annotating Strings with @Min to specify a minimum length (instead of using @Size)
  • annotating the setter of a JavaBean property (instead of the getter method)
  • annotating static fields/methods with constraint annotations (which is not supported)

Normally you would notice such mistakes only during run-time. The annotation processor helps in saving your valuable time by detecting these and similar errors already upon compile-time by plugging into the build process and raising compilation errors whenever constraint annotations are incorrectly used.

The processor can be used in basically every build environment (plain javac, Apache Ant, Apache Maven) as well as within all common IDEs. Just be sure to use JDK 6 or later, as the processor is based on the "Pluggable Annotation Processing API" defined by JSR 269 which was introduced with Java 6.

The HV reference guide describes in detail how to integrate the processor into the different environments, so I'll spare you the details here. As example the following screenshot shows some compilation errors raised by the processor within the Eclipse IDE (click to enlarge):

Hibernate Validator Annotation Processor in Eclipse IDE

Just for the record it should be noted that the annotation processor already works pretty well but is currently still under development and is considered as an experimental feature as of HV 4.1. If you are facing any problems please report them in JIRA. Some known issues are also discussed in the reference guide.

Summary

The focus for Hibernate Validator 4.0 was to provide a feature-complete, production-ready reference implementation of the Bean Validation spec.

While strictly staying spec-compliant, HV 4.1 goes beyond what is defined in JSR 303 and aims at generating even more user value by providing new constraints, new API functionality as well as an annotation processor for compile-time annotation checking.

In order to try out the new features yourself just download the release from SourceForge. Of course HV 4.1 can also be retrieved from the JBoss Maven repository.

If you are already using HV 4.0.x, the new release generally should work as drop-in replacement. The only exception is that we had to move the class ResourceBundleMessageInterpolator to the new package messageinterpolation. So if you're directly referencing this class, you'll have to update your imports here.

The rationale behind this relocation was to clearly separate those packages which can safely be accessed by HV users from packages intended for internal use only. The public packages are:

  • org.hibernate.validator
  • org.hibernate.validator.cfg
  • org.hibernate.validator.constraints
  • org.hibernate.validator.messageinterpolation
  • org.hibernate.validator.resourceloading

Of course we'd be very happy on any feedback. Questions and comments can be posted in the HV forum, while any issues or feature requests should be reported in JIRA.