Guide to Standard JAX-RS Annotations

In this guide, we will learn all the standard JAX-RS annotations to develop Rest API using Java.
Jersey Framework is the reference implementation of JAX-RS and it uses all the annotations to build Restful web services.

This guide covers all the standard JAX-RS annotations used for Rest API development.

  • @Path
  • @GET
  • @POST
  • @PUT
  • @DELETE
  • @HEAD
  • @OPTIONS
  • @Produces
  • @Consumes
  • @PathParam
  • @QueryParam
  • @FormParam
  • @MatrixParam
  • @CookieParam
  • @HeaderParam
  • @Provider
  • @Context
Let's see each annotation with examples.

The @Path Annotation

The @Path annotation's value is a relative URI path. In the example above, the Java class will be hosted at the URI path /helloworld. This is an extremely simple use of the @Path annotation. What makes JAX-RS so useful is that you can embed variables in the URIs.
URI path templates are URIs with variables embedded within the URI syntax. These variables are substituted at runtime in order for a resource to respond to a request based on the substituted URI. Variables are denoted by curly braces. For example, look at the following @Path annotation:
@Path("/users/{username}")
For example, if the user entered their username as "Galileo", the web service will respond to the following URL:
http://example.com/users/Galileo
To obtain the value of the username variable the @PathParam may be used on method parameter of a request method, for example:
Example: Specifying URI path parameter
@Path("/users/{username}")
public class UserResource {
 
    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String userName) {
        ...
    }
}
If it is required that a username must only consist of lower and upper case numeric characters then it is possible to declare a particular regular expression, which overrides the default regular expression, "[^/]+", for example:
@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")
In this type of example, the username variable will only match usernames that begin with one upper or lower case letter and zero or more alphanumeric characters and the underscore character. If a username does not match that a 404 (Not Found) response will occur.
@Path value may or may not begin with a '/', it makes no difference. Likewise, by default, a @Path value may or may not end in a '/', it makes no difference, and thus request URLs that end or do not end in a '/' will both be matched.
@GET, @PUT, @POST, @DELETE, ... (HTTP Methods)

The @GET HTTP Method Annotation

Methods annotation with the @GET annotation respond to HTTP get requests.
@GET annotation used for getting operations.
Example: get all the books from the database.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllBooks() {
    List<Book> books = BookRepository.getAllBooks(); // queries database for all books
    GenericEntity<List<Book>> list = new GenericEntity<List<Book>>(books) {};
    return Response.ok(list).build();
}
Note that the GenericEntity wrapper is used to maintain the generic type of the List as Book.

The @POST HTTP Method Annotation

Methods annotated @POST respond to POST method requests.
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response saveBook(Book book) {
    book = bookRepository.saveBook(book);
    return Response.ok(book).build();
}
The POST HTTP method is commonly used to create a resource. This example code persists the new book object in the database.

The @PUT HTTP Method Annotation

The @PUT annotation is used for updating a record and method annotated this way respond to an HTTP PUT request.
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updateBook(Book book) {
    book = bookRepository.updateBook(book);
    return Response.ok(book).build();
}

The @DELETE HTTP Method Annotation

Methods annotated @DELETE are expected to delete a resource.
@DELETE
@Path("{isbn}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteBook(@PathParam("isbn") String isbn) {
    Book book = bookRepository.deleteBookByIsbn(isbn);
    return Response.ok(book).build();
}
Usually, the resource or its id is passed to the resource method parameter from the URI variable as you can see in this example.

The @OPTIONS HTTP Method Annotation

Methods annotated with @OPTIONS respond to HTTP Option requests.
@OPTIONS
public Response preflight() {
    return Response.ok().header("Allow", true).build();
}
The options method is used as a request when the client wishes to make a complex HTTP request to a different domain. It is done in order to determine if the client is allowed to make the request or not.

The @HEAD HTTP Method Annotation

The HTTP @HEAD method is identical to HTTP GET method except that the server mustn’t respond with a body in the response.
@HEAD
public Response headsUp() {
    return Response.ok().build();
}

The @Produces Annotation

The@Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client.
@Produces can be applied at both the class and method levels. Example: In this example, the Java method will produce representations identified by the MIME media type "text/plain".
@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
    @GET
    public String doGetAsPlainText() {
        ...
    }
 
    @GET
    @Produces("text/html")
    public String doGetAsHtml() {
        ...
    }
}
The doGetAsPlainText method defaults to the MIME type of the @Produces annotation at the class level. 
The doGetAsHtml method's@Produces annotation overrides the class-level @Producessetting, and specifies that the method can produce HTML rather than plain text.
More than one media type may be declared in the same @Produces declaration, for example: Using multiple output MIME types.
@GET
@Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
    ...
}
The doGetAsXmlOrJson method will get invoked if either of the media types "application/xml" and "application/json" are acceptable. If both are equally acceptable then the former will be chosen because it occurs first.
Optionally, the server can also specify the quality factor for individual media types. These are considered if several are equally acceptable by the client. For example:
Example: Server-side content negotiation
@GET
@Produces({"application/xml; qs=0.9", "application/json"})
public String doGetAsXmlOrJson() {
    ...
}

In the above sample, if client accepts both "application/xml" and "application/json" (equally), then a server always sends "application/json", since "application/xml" has a lower quality factor.

The @Consumes Annotation

The @Consumes annotation is used to specify the MIME media types of representations that can be consumed by a resource. Example: Specifying input MIME type
@POST
@Consumes("text/plain")
public void postClichedMessage(String message) {
    // Store the message
}
In this example, the Java method will consume representations identified by the MIME media type "text/plain". Notice that the resource method returns void. This means no representation is returned and response with a status code of 204 (No Content) will be returned to the client.
@Consumes can be applied at both the class and the method levels and more than one media type may be declared in the same @Consumes declaration.

The @PathParam Annotation

@PathParam to extract a path parameter from the path component of the request URL that matched the path declared in @Path. Example:
    @Path("{userid}/")
    public String getUser(@PathParam("userid") String userid) {
       // return user object as json
    }
@Path("/users/{username}")
public class UserResource {
 
    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String userName) {
        ...
    }
}

The @QueryParam Annotation

A query parameter is a value associated with the key/value pair appended to a URL after the ?symbol. So for example, in the URL: http://localhost:8080/api/books/search?keyword=Java&limit=10 the query parameters are keyword and limit and the query values are Java and 10.
To retrieve these values use the @QueryParam annotation and pass the name of the query parameter as a value to the annotation, then annotated a method parameter in the resource method that responds to a request to the URI resource /books/search.
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("search")
public Response searchBook(@QueryParam("keyword") String keyword, @QueryParam("limit") int limit) {
    List<Book> books = bookRepository.searchBook(keyword, limit);
    return Response.ok(new GenericEntity<List<Book>>(books) {}).build();
}
In the code snippet above the value of the keyword query parameter is assigned to the method parameter keyword and the value of the limit query parameter is assigned to the limit method parameter.

The @FormParam Annotation

@FormParam is slightly special because it extracts information from a request representation that is of the MIME media type "application/x-www-form-urlencoded" and conforms to the encoding specified by HTML forms, as described here. This parameter is very useful for extracting information that is POSTed by HTML forms, for example, the following extracts the form parameter named "name" from the POSTed form data. Example: Processing POSTed HTML form
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {
    // Store the message
}
On other words, You may need to read parameters sent in a POST HTTP requests directly from the body, rather than serializing it to an object. This can be done by using the @FormParam annotation.
@POST
@Produces(MediaType.APPLICATION_JSON)
public Response saveBookF(@FormParam("title") String title,
                          @FormParam("author") String author,
                          @FormParam("price") Float price) {
    return Response.ok(bookRepository.saveBook(new Book(title, author, price))).build();
}

The @MatrixParam Annotation

Matrix parameters are a set of query parameters separated by a semicolon rather than an ampersand. This may occur because the values were selected from a multiple select input box and being set via a GET request rather than a POST request. The URL might look something like this:
http://localhost:8080/api/books;author=atheedom;category=Java;language=english
The annotation @MatricParam is used to retrieve the parameter value from the URI and assign it to a method parameter.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getBookBy(@MatrixParam("author") String author,
                          @MatrixParam("category") String category,
                          @MatrixParam("language") String language) {
    return Response.ok(
            new GenericEntity<List<Book>>(
                    bookRepository.getBookBy(author, category, language)) {}).build();
}

The @CookieParam Annotation

The @CookieParam annotation allows you to inject directly into your resource method cookies sent by the client. Imagine you have sent a cookie called cartId to the clients so that you can track the customer’s shopping cart. To pull the cookie from the HTTP request just annotate the method parameter to which you want the cookie data to be assigned.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getCart(@CookieParam("cartId") int cartId) {
    return Response.ok().build();
}

The @HeaderParam Annotation

The @HeaderParam annotation is used to inject HTTP request header values into resource method parameters. You can think of it like a shortcut to using the @Context annotation to inject theHttpServletRequest or HttpHeaders instance.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getReferrer(@HeaderParam("referer") String referrer) {
    return Response.ok(referrer).build();
}

The @Provider Annotation

Providers are used to extend and customize JAX-RS by altering the behavior of the runtime to achieve a set of goals.
There are three types of providers:
Entity Providers This type of provider controls the mapping of data representations, such as JSON and XML, to their object equivalents Context Providers This type of provider controls the context that resources can access with the @Context annotation Exception Providers This type of provider controls the mapping of Java exceptions to a JAX-RS Response instance. The only thing they have in common is that they must be identified by the @Provider annotation and follow the correct rules for constructor declaration.
The @ApplicationPath Annotation Let’s start at the top of the trees with the @ApplicationPath annotation:
@ApplicationPath("/api")
public class RESTConfig extends Application {}
This is where you start defining the URI to your resources. Here we are saying that all our resources are to be found at the root /api. The URL should look something like this:
http://localhost:8080/webcontext/api/ 
where webcontext is the name of your application.

The @Context Annotation

When deploying a JAX-RS application using servlet then ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse are available using @Context.
JAX-RS provides the @Context annotation to inject a variety of resources in your RESTful services. Some of the most commonly injected components are HTTP headers, HTTP URI related information. Here is a complete list (in no specific order)
HTTP headers HTTP URI details Security Context Resource Context Request Configuration Application Providers
Examples:
@Path("testinject")
public class InjectURIDetails{
    //localhost:8080/<root-context>/testinject/httpheaders
    @GET
    @Path("httpheaders")
    public void test(@Context HttpHeaders headers){
        System.out.println("ALL headers -- "+ headers.getRequestHeaders().toString());
        System.out.println("'Accept' header -- "+ headers.getHeaderString("Accept"));
        System.out.println("'TestCookie' value -- "+ headers.getCookies().get("TestCookie").getValue());
    }
}
public class TodoResource {
    @Context
    UriInfo uriInfo;

    @Context
    Request request;

    String id;

    public TodoResource(UriInfo uriInfo, Request request, String id) {
        this.uriInfo = uriInfo;
        this.request = request;
        this.id = id;
    }
}

Conclusion

This post explained all the Standard JAX-RS Annotations.
Learn more about Jersey Rest framework on Jersey Rest Developer Guide.
All the code of this article is available over on Github. This is a Maven-based project, so it should be easy to import and run as it is.

Comments

Post a Comment