Monday, May 20, 2013

Handling different subresources with JAX-RS subresource locator

1   Introduction


 In this article I won't explain what a resource or subresource is, since there are several pages that explain perfectly well its meaning. For example, you can check Oracle tutorial or Jersey documentation. I will focus on implementing a RESTful service with a subresource locator which will decide at runtime what type of subresource will be returned.

You can check the source code on github.


2   Configuration


You need to include the JAX-RS reference implementation libraries:
The first two dependencies are necessary if you want to develop services, while the third contains the implementation to convert your classes to JSON.

Next step is to define the Jersey servlet that will handle requests to our services. Include the content below on your web.xml file:
I have included two init parameters:

  • com.sun.jersey.config.property.packages: Required. It must define one or more packages separated by ";". These are the packages where your resource classes must be located.

  • com.sun.jersey.api.json.POJOMappingFeature: Activates POJO support, which means that it will use the Jackson library to convert your Java Objects to JSON and the other way back.

We are done with the configuration, let's implement the resources.


3   The root resource


To declare a root resource you must annotate your class with @Path.
The @GET annotated getWarehouseInfo() method will handle requests to the root resource, so when the user enters the following URI:

http://localhost:8080/rest-subresources/rest/warehouse


It will return the warehouse information.

Take into account that if I had included the @Path annotation in conjunction with @GET, I would be declaring a subresource method.

The getItem method is annotated with @Path but not with any request method designator (get, post...). This is because I'm declaring a subresource locator. This subresource locator will return an object  that will be capable of handling the HTTP request, but which one? It will depend on the id parameter. Both the TypeAResource and TypeBResource implement the same interface ItemResource, so we can return any of them.


4   Subresources


These subresources have a method with a request method designator, but no @Path annotation has been included.
The following requests will return a different subresource:

http://localhost:8080/rest-subresources/rest/warehouse/items/1: Will return a Type B resource:

{"id":1,"price":33.5,"type":"B"}

http://localhost:8080/rest-subresources/rest/warehouse/items/12: Will return a Type A resource:

{"id":12,"price":35.5,"type":"A","code":"12SS34"}


5   Possible mistakes


I'm including some errors that may occur if you fail to configure the application properly:

Fail on deploy. com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes

You did not define the packages init-param, so it will fail to find nor load your resource classes.
Fail on runtime. com.sun.jersey.api.MessageException: A message body writer for Java class [yourModelClass], and Java type class [yourModelClass], and MIME media type application/json was not found.

You did not define the JSON feature on web.xml. It won't be able to convert your object to JSON.
Fail on runtime. com.sun.jersey.api.MessageException: A message body writer for Java class [yourModelClass], and Java type class [yourModelClass], and MIME media type application/json was not found.

This error might also be produced because the JSON maven dependency was not included.
Fail on deploy. java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer.

The jersey-servlet maven dependency was not included. Older versions of Jersey included this class in jersey-core library, but in newer versions they have put it in a separate jar.

Monday, May 13, 2013

Retrieving method annotations with Spring Annotation Utils

1   Introduction

The JDK provides us with several lookup methods that allow us to retrieve annotations from a class, method, field or added to method parameters. The Spring framework included a general utility class for annotations, org.springframework.core.annotation.AnnotationUtils, which extends the basic functionalities. In this post I will explain the main features of this class, focusing on retrieving annotations from a method.


2   getAnnotation method

Signature:
This method looks up if method contains the specified annotation type and returns it if found. So, what's the difference between the JDK getAnnotation method? The Spring version handles bridge methods. You can check effects of Type Erasure and Bridge Methods tutorial to get a good explanation.

Let's see it with an example. Imagine we got a generic class Foo, and a Bar class that extends it:
Now we try to retrieve @MyAnnotation with both utility methods:
The result is as follows:



3   findAnnotation method

Signature:
This method also retrieves the specified annotation type from method. The difference between getAnnotation is that in this case, it will look up the entire inheritance hierarchy of the specified method.

Let's see another example. We got the classes below:
Trying to retrieve @MyAnnotation from anotherMethod in Bar class using the different utility methods
will get the following results: