JAX-RS

RESTful

JAX-RS


1. What is JAX-RS

JAX-RS means JAVA API for RESTful Web Services. The certification requires the knowledge of JAX-RS 1.1 (also it isn't the last version). JAX-RS has many implementations: Jersey, RESTlet, RESTeasy. We will use Jersey 1.17 in our examples. Main items of JAX-RS are root resources, sub-resources, resource methods, sub-resource methods and sub-resource locators

2. Root Resources

Root resources are Java classes annotated with the @Path annotation or have at least one method annotated with @Path or a request method designator (@GET, @PUT, @DELETE or @POST). Resource methods are methods of the resource class annotated with a request method designator and without @Path annotation.

Example 2.1. Example of creating restful web services with JAX-RS

This example is a simple example of a root resource class created with the help of JAX-RS annotations. 

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("exams")
public class ExamService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getExams() {
       ...
    }
}

2.1. @Path

@Path annotation's value represents a relative URI path. In the example 2.1 the resource can be accessed by URI /exams.

Value of @Path annotation can contain variables embedded within the URI syntax. They are called URI path templates. For example: @Path("/exams/{id}")

URI path templates can be in the form of regular expression: @Path("exams/{examname: [a-zA-Z][a-zA-Z_0-9]*}").

A @Path value may or may not begin and end with a '/', it makes no difference. So next URIs will be matched: /exams/ ,/exams.

2.2. Request Method Designators 

There are @GET, @PUT, @POST, @DELETE and @HEAD request method designators. The JAX-RS automatically supports the methods HEAD and OPTIONS by default, if not explicitly implemented. For HEAD will be invoked the implemented GET method without response entity in response. A response for the OPTIONS method depends on the requested media type defined in the 'Accept' header. The OPTIONS method will return a response with a set of supported resource methods in the 'Allow' header or a WADL document.

Example 2.2. GET and POST Restful Web Service Example

@Path("exams")
public class ExamService {
    Map<Integer, Exam> exams;

    public ExamService() {
        exams = new HashMap<Integer, Exam>();
        exams.put(1, new Exam(1, "OCEJPAD 6"));
        exams.put(2, new Exam(2, "OCEJWSD 6"));
    }

    @GET
    @Path("{id}")
    public Exam get(@PathParam("id") int id) {
        return exams.get(id);
    }

    @POST
    public String post(Exam exam) {
        exams.put(exam.getId(), exam);
        return exams.toString();
    }
}

2.3. @Produces and @Consumes Annotations

@Consumes specifies the accepted request MIME media types and @Produces - the response MIME media types.

  • These annotations can be applied at the class and method levels.
  • More than one media type may be declared in one annotation.
  • If a resource class produces several MIME media types then the resource method with the most acceptable media type is chosen. The most acceptable media type is defined by Accept header of the HTTP request.

Example 2.3. Specifying two GET methods with different output MIME type

The resource in the example contain two GET methods with different output MIME type. If the Accept header of the client request is "Accept: text/plain" then the getExams() method will be called. If the Accept header is "Accept: text/html" - getExamsHtml() method. If the Accept header is "Accept: text/plain;q=0.9, text/html", it means that the client can accept media types of "text/plain" and "text/html" both, but prefers the latter, then the getExamsHtml() method will be called.

@Path("exams")
public class ExamService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getExams() {
        ...
    }

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String getExamsHtml() {
        ...
    }
}

Example 2.4. Using multiple output MIME types with quality factor

The example shows how to declare several output media types with server quality factor.

@GET
@Produces({"application/json; qs=0.8", "application/xml"})
public String getExamsAsXmlOrJson() {
    ...
}

Example 2.5. Declare @Consumes Annotation

@POST
@Consumes("text/plain")
public void addExam(String name) {
    //...
}

3. Root Resource Classes Life-cycle

The life-cycle of root resource classes is per-request by default, which means that a new instance of a root resource class is created every time the request URI path matches the root resource. Jersey supports two additional life-cycles: per-session and singleton scopes.

  • Per-request scope. The @PerRequest annotation (or none) is used. It is a default lifecycle, when the resource instance is created for each new request and used for processing of this request. If the resource is used more than one time in the request processing, always the same instance will be used. This can happen when a resource is a sub-resource returned several times during the matching. 
  • Per-session scope. The resource instance is created per web session and stored as a session attribute. The @PerSession annotation is used.
  • Singleton scope. In this scope there is only one instance of resource per jax-rs application. Singleton resource can be annotated with @Singleton.

4. Representations and Java Types

Consumed representation. The method parameter associated with the consumed representation does not need any annotations. Methods can have only one or none unannotated parameter because only one such representation can be sent in a request.

Produced representation. The produces representation corresponds to what is returned by the resource method. The Content-Type (if not set) can be automatically set from the MIME media types declared by @Produces if the most acceptable media type is not a wild card (one that contains a *, for example "application/" or "/*").

The following table lists the supported representation content types:

Java Type Content Type Supported

java.lang.String

*/*

byte[]

*/*

java.io.InputStream

*/*

java.io.Reader

*/*

java.io.File

*/*

javax.activation.DataSource

*/*

javax.xml.transform.Source

text/xml, application/xml, application/*+xml

javax.xml.bind.JAXBElement and JAXB classes

text/xml, application/xml, application/*+xml

javax.ws.rs.core.MultivaluedMap<String, String>

application/x-www-form-urlencoded

javax.ws.rs.core.StreamingOutput (as a writer only)

*/*

 

Sources: Jersey Tutorial - Root Resource Classes.

See also How to build RESTful Web Services using Jersey



0 comments
Leave your comment: