JAX-RS specification provides native support for validating resource classes based on Java EE Bean Validation specification (JSR-303/349).
According to JAX-RS specification, the constraint annotations can be used at the same places where we can use @MatrixParam, @QueryParam, @PathParam, @CookieParam, @HeaderParam, @Context etc. However, the constraint annotation are not allowed in resource class constructors and property setters.
Let's see a quick example to see how that works.
Example
Maven dependency
As we are going to use Jersey in this example too, we have to add following additional Jersey extension module dependency which provides support for Bean Validation (JSR-349) API.
pom.xml<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>2.25.1</version>
</dependency>
Above extension uses hibernate-validator as bean validation implementation.
A JAX-RS resource with constraint annotations
@Path("/customers")
public class CustomerResource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String createCustomer(@NotNull @FormParam("name") String name,
@NotNull @FormParam("address") String address,
@NotNull @Pattern(regexp = "\\d{3}-\\d{3}-\\d{4}")
@FormParam("phone-number") String phoneNumber) {
System.out.println("-- in createCustomer() method --");
return String.format("created dummy customer name: %s, address: %s, phoneNumber:%s%n"
, name, address, phoneNumber);
}
}
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run-war
JAX-RS client
public class MyClient {
public static void main(String[] args) throws Exception {
Form form = new Form();
form.param("name", null)
.param("address", null)
.param("phone-number", "343-343-343");
Client client = ClientBuilder.newBuilder().build();
WebTarget target =
client.target("http://localhost:8080/customers");
Future<String> future = target.request(MediaType.APPLICATION_FORM_URLENCODED)
.buildPost(Entity.form(form)).submit(String.class);
System.out.println(future.get());
}
} OutputCaused by: java.util.concurrent.ExecutionException: javax.ws.rs.BadRequestException: HTTP 400 Bad Request at jersey.repackaged.com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299) at jersey.repackaged.com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286) at jersey.repackaged.com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) at com.logicbig.example.MyClient.main(MyClient.java:24) ... 6 more Caused by: javax.ws.rs.BadRequestException: HTTP 400 Bad Request at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1011) at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:819) at org.glassfish.jersey.client.JerseyInvocation.access$700(JerseyInvocation.java:92) at org.glassfish.jersey.client.JerseyInvocation$5.completed(JerseyInvocation.java:776) at org.glassfish.jersey.client.ClientRuntime.processResponse(ClientRuntime.java:196) at org.glassfish.jersey.client.ClientRuntime.access$300(ClientRuntime.java:74) at org.glassfish.jersey.client.ClientRuntime$2$1$1.run(ClientRuntime.java:166) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:267) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:340) at org.glassfish.jersey.client.ClientRuntime$2$1.response(ClientRuntime.java:164) at org.glassfish.jersey.client.internal.HttpUrlConnector$3.run(HttpUrlConnector.java:297) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at jersey.repackaged.com.google.common.util.concurrent.MoreExecutors$DirectExecutorService.execute(MoreExecutors.java:299) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) at jersey.repackaged.com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:50) at jersey.repackaged.com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:37) at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:293) at org.glassfish.jersey.client.ClientRuntime$2.run(ClientRuntime.java:180) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:267) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:340) at org.glassfish.jersey.client.ClientRuntime$3.run(ClientRuntime.java:208) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ... 1 more
Without constraint annotations:
Let's comment out the constraint annotations:
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String createCustomer(/*@NotNull*/ @FormParam("name") String name,
/*@NotNull*/ @FormParam("address") String address,
//@NotNull @Pattern(regexp = "\\d{3}-\\d{3}-\\d{4}")
@FormParam("phone-number") String phoneNumber) {
System.out.println("-- in createCustomer() method --");
return String.format("created dummy customer name: %s, address: %s, phoneNumber:%s%n"
, name, address, phoneNumber);
}
Output
The output on the client:
created dummy customer name: null, address: null, phoneNumber:343-343-343
In the next example, we will see how to map a custom constraint violation error message with the response.
Example ProjectDependencies and Technologies Used: - jersey-server 2.25.1: Jersey core server implementation.
- jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
- jersey-bean-validation 2.25.1:
Jersey extension module providing support for Bean Validation (JSR-349) API.
- JDK 1.8
- Maven 3.3.9
|