/ BEAN VALIDATION

Design by contract and bean validation

I must confess that despite all benefits of defensive programming, I usually limit myself to not expose mutable attribute to the outside world. Why is that? I believe this is mostly because of readability. Have a look at the following piece of code:

public List<Person> getPersons() {
    return Collections.unmodifiableList(persons);
}

Easy enough to read and understand. Now, consider a design by contract approach, where I want to enforce pre-conditions, i.e. conditions that have to be met to run the code.

public void sendEmail(String email) {
    Assert.assertNotNull(email);
    // Real code after that
    ...
}

Not really hard. But now, I want to surface-check the email so as not to query the JNDI tree for a SMTP server for nothing.

public void sendEmail(String email) {
    Assert.assertNotNull(email);
    Validator validator = new EmailValidator(email);
    validator.validate(email);
    // Real code after that
    ...
}

It only so much harder to read…​ for now. Should I have more than one parameter and multiple checks for each parameter, complexity would quickly grow out-of-hand, and this only for pre-condition!. Post-condition checks would take place at the end of the method, and disturb readability even more. Besides, the outside world doesn’t know about those: they have to be manually written in Javadoc and kept in sync with the code.

What if those limitations could be waived? Would I be more inclined toward using design by contract? I do believe that’s the case. And when I attended Emmanuel Bernard's talk at Devoxx France, I couldn’t believe usage would be so simple. My goal can be reached by only using Bean Validation API 1.1 (aka JSR-349). This newer version reuses Bean Validation 1.0 (aka JSR-303) annotations, but where in the previous version only attributes could be annotated, now methods can too. Or to say it more generally, before state was validated, now we can design by contract.

The previous method could be updated like so:

public void sendEmail(@Email String email) {
    // Real code after that
    ...
}

You can see by yourself, not only is it more readable but it communicates my intent to the method callers: this should be an email, not just any string. Icing on the cake, the JSR is open, in all senses. You can contribute to the specs, to the implementation, to anything you like!

Kill-joys would probably object that it is nice and good, but it is still in draft. That would be true, except it is nothing like HTML5 scope. Besides, Hibernate Validator was Bean Validation API 1.0 Reference Implementation. It is only natural that it is also the case for version 1.1, with Hibernate Validator 5. However, it already provides everything we need with version 4.2. If you’re willing to use Spring, it is a breeze:

  1. Get the right dependencies in your POM
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>2.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
    </dependency>
  2. Annotate your methods as above
  3. Add the right Spring bean post-processor
    @Configuration
    public class SpringConfiguration {
    
        ...
    
        @Bean
        public static MethodValidationPostProcessor methodValidationPostProcessor() {
            return new MethodValidationPostProcessor();
        }
    }
  4. Enjoy! Really, it is over, you can use design by contract to your heart’s content.

Sources for this article can be found in Eclipse/Maven format here.

To go further: see relevant links in the article

Regular readers of this blog may have noticed I’m using Spring Java configuration whereas I was previously an advocate of XML configuration. Please read this post.

Nicolas Fränkel

Nicolas Fränkel

Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Also double as a trainer and triples as a book author.

Read More
Design by contract and bean validation
Share this