60.2. Developing Services with Bean Validation
60.2.1. Annotating a Service Bean
Overview
The first step in developing a service with bean validation is to apply the relevant validation annotations to the Java classes or interfaces that represent your services. The validation annotations enable you to apply constraints to method parameters, return values, and class fields, which are then checked at run time, every time the service is invoked.
Validating simple input parameters
To validate the parameters of a service method—where the parameters are simple Java types—you can apply any of the constraint annotations from the bean validation API (
javax.validation.constraints
package). For example, the following code example tests both parameters for nullness (@NotNull
annotation), whether the id
string matches the \\d+
regular expression (@Pattern
annotation), and whether the length of the name
string lies in the range 1 to 50:
import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; ... @POST @Path("/books") public Response addBook( @NotNull @Pattern(regexp = "\\d+") @FormParam("id") String id, @NotNull @Size(min = 1, max = 50) @FormParam("name") String name) { // do some work return Response.created().build(); }
Validating complex input parameters
To validate complex input parameters (object instances), apply the
@Valid
annotation to the parameter, as shown in the following example:
import javax.validation.Valid; ... @POST @Path("/books") public Response addBook( @Valid Book book ) { // do some work return Response.created().build(); }
The
@Valid
annotation does not specify any constraints by itself. When you annotate the Book parameter with @Valid
, you are effectively telling the validation engine to look inside the definition of the Book
class (recursively) to look for validation constraints. In this example, the Book
class is defined with validation constraints on its id
and name
fields, as follows:
import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; ... public class Book { @NotNull @Pattern(regexp = "\\d+") private String id; @NotNull @Size(min = 1, max = 50) private String name; // ... }
Validating return values (non-Response)
To apply validation to regular method return values (non-Response), add the annotations in front of the method signature. For example, to test the return value for nullness (
@NotNull
annotation) and to test validation constraints recursively (@Valid
annotation), annotate the getBook
method as follows:
import javax.validation.constraints.NotNull; import javax.validation.Valid; ... @GET @Path("/books/{bookId}") @Override @NotNull @Valid public Book getBook(@PathParam("bookId") String id) { return new Book( id ); }
Validating return values (Response)
To apply validation to a method that returns a
javax.ws.rs.core.Response
object, you can use the same annotations as in the non-Response case. For example:
import javax.validation.constraints.NotNull; import javax.validation.Valid; import javax.ws.rs.core.Response; ... @GET @Path("/books/{bookId}") @Valid @NotNull public Response getBookResponse(@PathParam("bookId") String id) { return Response.ok( new Book( id ) ).build(); }
60.2.2. Standard Annotations
Bean validation constraints
Table 60.1, “Standard Annotations for Bean Validation” shows the standard annotations defined in the Bean Validation specification, which can be used to define constraints on fields and on method return values and parameters (none of the standard annotations can be applied at the class level).
Annotation | Applicable to | Description |
---|---|---|
@AssertFalse | Boolean , boolean | Checks that the annotated element is false . |
@AssertTrue | Boolean , boolean | Checks that the annotated element is true . |
@DecimalMax(value=, inclusive=) | BigDecimal , BigInteger , CharSequence , byte , short , int , long and primitive type wrappers | When inclusive=false , checks that the annotated value is less than the specified maximum. Otherwise, checks that the value is less than or equal to the specified maximum. The value parameter specifies the maximum in BigDecimal string format. |
@DecimalMin(value=, inclusive=) | BigDecimal , BigInteger , CharSequence , byte , short , int , long and primitive type wrappers | When inclusive=false , checks that the annotated value is greater than the specified minimum. Otherwise, checks that the value is greater than or equal to the specified minimum. The value parameter specifies the minimum in BigDecimal string format. |
@Digits(integer=, fraction=) | BigDecimal , BigInteger , CharSequence , byte , short , int , long and primitive type wrappers | Checks whether the annotated value is a number having up to integer digits and fraction fractional digits. |
@Future | java.util.Date , java.util.Calendar | Checks whether the annotated date is in the future. |
@Max(value=) | BigDecimal , BigInteger , CharSequence , byte , short , int , long and primitive type wrappers | Checks whether the annotated value is less than or equal to the specified maximum. |
@Min(value=) | BigDecimal , BigInteger , CharSequence , byte , short , int , long and primitive type wrappers | Checks whether the annotated value is greater than or equal to the specified minimum. |
@NotNull | Any type | Checks that the annotated value is not null . |
@Null | Any type | Checks that the annotated value is null . |
@Past | java.util.Date , java.util.Calendar | Checks whether the annotated date is in the past. |
@Pattern(regex=, flag=) | CharSequence | Checks whether the annotated string matches the regular expression regex considering the given flag match. |
@Size(min=, max=) | CharSequence , Collection , Map and arrays | Checks whether the size of the annotated collection, map, or array lies between min and max (inclusive). |
@Valid | Any non-primitive type | Performs validation recursively on the annotated object. If the object is a collection or an array, the elements are validated recursively. If the object is a map, the value elements are validated recursively. |
60.2.3. Custom Annotations
Defining custom constraints in Hibernate
It is possible to define your own custom constraints annotations with the bean validation API. For details of how to do this in the Hibernate validator implementation, see the Creating custom constraints chapter of the Hibernate Validator Reference Guide.