Chapter 60. Bean Validation

Abstract

Bean validation is a Java standard that enables you to define runtime constraints by adding Java annotations to service classes or interfaces. Apache CXF uses interceptors to integrate this feature with Web service method invocations.

60.1. Introduction

Overview

Bean Validation 1.1 (JSR-349)—which is an evolution of the original Bean Validation 1.0 (JSR-303) standard—enables you to declare constraints that can be checked at run time, using Java annotations. You can use annotations to define constraints on the following parts of the Java code:
  • Fields in a bean class.
  • Method and constructor parameters.
  • Method return values.

Example of annotated class

The following example shows a Java class annotated with some standard bean validation constraints:
// Java
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Max;
import javax.validation.Valid;
...
public class Person {
    @NotNull private String firstName;
    @NotNull private String lastName;
    @Valid @NotNull private Person boss;
 
    public @NotNull String saveItem( @Valid @NotNull Person person, @Max( 23 ) BigDecimal age ) {
        // ...
    }
}

Bean validation or schema validation?

In some respects, bean validation and schema validation are quite similar. Configuring an endpoint with an XML schema is a well established way to validate messages at run time on a Web services endpoint. An XML schema can check many of the same constraints as bean validation on incoming and outgoing messages. Nevertheless, bean validation can sometimes be a useful alternative for one or more of the following reasons:
  • Bean validation enables you to define constraints independently of the XML schema (which is useful, for example, in the case of code-first service development).
  • If your current XML schema is too lax, you can use bean validation to define stricter constraints.
  • Bean validation lets you define custom constraints, which might be impossible to define using XML schema language.

Dependencies

The Bean Validation 1.1 (JSR-349) standard defines just the API, not the implementation. Dependencies must therefore be provided in two parts:
  • Core dependencies—provide the bean validation 1.1 API, Java unified expression language API and implementation.
  • Hibernate Validator dependencies—provides the implementation of bean validation 1.1.

Core dependencies

To use bean validation, you must add the following core dependencies to your project's Maven pom.xml file:
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <!-- use 3.0-b02 version for Java 6 -->
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <!-- use 3.0-b01 version for Java 6 -->
    <version>3.0.0</version>
</dependency>
Note
The javax.el/javax.el-api and org.glassfish/javax.el dependencies provide the API and implementation of Java's unified expression language. This expression language is used internally by bean validation, but is not important at the application programming level.

Hibernate Validator dependencies

To use the Hibernate Validator implementation of bean validation, you must add the following additional dependencies to your project's Maven pom.xml file:
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.3.Final</version>
</dependency>

Resolving the validation provider in an OSGi environment

The default mechanism for resolving a validation provider involves scanning the classpath to find the provider resource. In the case of an OSGi (Apache Karaf) environment, however, this mechanism does not work, because the validation provider (for example, the Hibernate validator) is packaged in a separate bundle and is thus not automatically available in your application classpath. In the context of OSGi, the Hibernate validator needs to be wired to your application bundle, and OSGi needs a bit of help to do this successfully.

Configuring the validation provider explicitly in OSGi

In the context of OSGi, you need to configure the validation provider explicitly, instead of relying on automatic discovery. For example, if you are using the common validation feature (see the section called “Bean validation feature”) to enable bean validation, you must configure it with a validation provider, as follows:
<bean id="commonValidationFeature" class="org.apache.cxf.validation.BeanValidationFeature">
    <property name="provider" ref="beanValidationProvider"/>
</bean>

<bean id="beanValidationProvider" class="org.apache.cxf.validation.BeanValidationProvider">
    <constructor-arg ref="validationProviderResolver"/>
</bean>

<bean id="validationProviderResolver" class="org.example.HibernateValidationProviderResolver"/>
Where the HibernateValidationProviderResolver is a custom class that wraps the Hibernate validation provider.

Example HibernateValidationProviderResolver class

The following code example shows how to define a custom HibernateValidationProviderResolver, which resolves the Hibernate validator:
// Java
package org.example;

import static java.util.Collections.singletonList;
import org.hibernate.validator.HibernateValidator;
import javax.validation.ValidationProviderResolver;
import java.util.List;


/**
 * OSGi-friendly implementation of {@code javax.validation.ValidationProviderResolver} returning
 * {@code org.hibernate.validator.HibernateValidator} instance.
 *
 */
public class HibernateValidationProviderResolver implements ValidationProviderResolver {

    @Override
    public List getValidationProviders() {
        return singletonList(new HibernateValidator());
    }
}
When you build the preceding class in a Maven build system, which is configured to use the Maven bundle plug-in, your application will be wired to the Hibernate validator bundle at deploy time (assuming you have already deployed the Hibernate validator bundle to the OSGi container).