Root resource classes are POJOs (Plain Old Java Objects) that are either annotated with@Path or have at least one method annotated with @Path or a request method designator such as @GET, @PUT, @POST, or @DELETE. Resource methods are methods of a resource class annotated with a request method designator. This section describes how to use Jersey to annotate Java objects to create RESTful web services.
The JAX-RS API for developing RESTful web services is a Java programming language API designed to make it easy to develop applications that use the REST architecture.
The JAX-RS API uses Java programming language annotations to simplify the development of RESTful web services. Developers decorate Java programming language class files with HTTP-specific annotations to define resources and the actions that can be performed on those resources. Jersey annotations are runtime annotations, therefore, runtime reflection will generate the helper classes and artifacts for the resource, and then the collection of classes and artifacts will be built into a web application archive (WAR). The resources are exposed to clients by deploying the WAR to a Java EE or web server.
The following code sample is a very simple example of a root resource class using JAX-RS annotations. The sample shown here is from the samples that ship with Jersey, and which can be found in the following directory of that installation: jersey/samples/helloworld/src/main/java/com/sun/jersey/samples/helloworld/resources/HelloWorldResource.java.
package com.sun.jersey.samples.helloworld.resources; import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; // The Java class will be hosted at the URI path "/helloworld" @Path("/helloworld") public class HelloWorldResource { // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/plain" @Produces("text/plain") public String getClichedMessage() { // Return some cliched textual content return "Hello World"; } }
The following annotations are used in this example:
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.
The @GET annotation is a request method designator, along with@POST, @PUT, @DELETE, and @HEAD, that is defined by JAX-RS, and which correspond to the similarly named HTTP methods. In the example above, the annotated Java method will process HTTP GET requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
The @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client. In this example, the Java method will produce representations identified by the MIME media type "text/plain".
The @Consumes annotation is used to specify the MIME media types of representations a resource can consume that were sent by the client. The above example could be modified to set the cliched message as shown here:
@POST @Consumes("text/plain") public void postClichedMessage(String message) { // Store the message }
Here is a listing of some of the Java programming annotations that are defined by JAX-RS, with a brief description of how each is used. Further information on the JAX-RS API's can be viewed at https://jsr311.dev.java.net/nonav/javadoc/index.html.
Table 3–1 Summary of Jersey Annotations
Annotation |
Description |
---|---|
@Path |
The @Path annotation's value is a relative URI path indicating where the Java class will be hosted, for example, /helloworld. You can also embed variables in the URIs to make a URI path template. For example, you could ask for the name of a user, and pass it to the application as a variable in the URI, like this, /helloworld/{username}. |
@GET |
The @GET annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP GET requests. The behavior of a resource is determined by the HTTP method to which the resource is responding. |
@POST |
The @POST annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP POST requests. The behavior of a resource is determined by the HTTP method to which the resource is responding. |
@PUT |
The @PUT annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP PUT requests. The behavior of a resource is determined by the HTTP method to which the resource is responding. |
@DELETE |
The @DELETE annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP DELETE requests. The behavior of a resource is determined by the HTTP method to which the resource is responding. |
@HEAD |
The @HEAD annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP HEAD requests. The behavior of a resource is determined by the HTTP method to which the resource is responding. |
@PathParam |
The @PathParam annotation is a type of parameter that you can extract for use in your resource class. URI path parameters are extracted from the request URI, and the parameter names correspond to the URI path template variable names specified in the @Path class-level annotation. |
@QueryParam |
The @QueryParam annotation is a type of parameter that you can extract for use in your resource class. Query parameters are extracted from the request URI query parameters. |
@Consumes |
The @Consumes annotation is used to specify the MIME media types of representations a resource can consume that were sent by the client. |
@Produces |
The @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client, for example, "text/plain". |
@Provider |
The @Provider annotation is used for anything that is of interest to the JAX-RS runtime, such as MessageBodyReader and MessageBodyWriter. For HTTP requests, the MessageBodyReader is used to map an HTTP request entity body to method parameters. On the response side, a return value is mapped to an HTTP response entity body using a MessageBodyWriter. If the application needs to supply additional metadata, such as HTTP headers or a different status code, a method can return a Response that wraps the entity, and which can be built using Response.ResponseBuilder. |
The @Path annotation identifies the URI path template to which the resource responds, and is specified at the class level of a resource. The @Path annotation's value is a partial URI path template relative to the base URI of the server on which the resource is deployed, the context root of the WAR, and the URL pattern to which the Jersey helper servlet responds.
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}")
In this type of example, a user will be prompted to enter their name, and then a Jersey web service configured to respond to requests to this URI path template will respond. For example, if the user entered their user name 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 @PathParamannotation may be used on the method parameter of a request method, as shown in the following code example.
@Path("/users/{username}") public class UserResource { @GET @Produces("text/xml") public String getUser(@PathParam("username") String userName) { ... } }
If it is required that a user name must only consist of lower and upper case numeric characters, it is possible to declare a particular regular expression that will override the default regular expression, "[^/]+?". The following example shows how this could be used with the @Path annotation.
@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]}")
In this type of example the username variable will only match user names that begin with one upper or lower case letter and zero or more alpha numeric characters and the underscore character. If a user name does not match that template, then a 404 (Not Found) response will occur.
An @Path value may or may not begin with a forward slash (/), it makes no difference. Likewise, by default, an @Path value may or may not end in a forward lash (/), it makes no difference, and thus request URLs that end or do not end with a forward slash will both be matched. However, Jersey has a redirection mechanism, which, if enabled, automatically performs redirection to a request URL ending in a / if a request URL does not end in a / and the matching @Path does end in a /.
A URI path template has one or more variables, with each variable name surrounded by curly braces, { to begin the variable name and } to end it. In the example above, username is the variable name. At runtime, a resource configured to respond to the above URI path template will attempt to process the URI data that corresponds to the location of {username} in the URI as the variable data for username.
For example, if you want to deploy a resource that responds to the URI path template http://example.com/myContextRoot/jerseybeans/{name1}/{name2}/, you must deploy the WAR to a Java EE server that responds to requests to the http://example.com/myContextRoot URI, and then decorate your resource with the following @Path annotation:
@Path("/{name1}/{name2}/") public class SomeResource { ... }
In this example, the URL pattern for the Jersey helper servlet, specified in web.xml, is the default:
<servlet-mapping> <servlet-name>My Jersey Bean Resource</servlet-name> <url-pattern>/jerseybeans/*</url-pattern> </servlet-mapping>
A variable name can be used more than once in the URI path template.
If a character in the value of a variable would conflict with the reserved characters of a URI, the conflicting character should be substituted with percent encoding. For example, spaces in the value of a variable should be substituted with %20.
Be careful when defining URI path templates that the resulting URI after substitution is valid.
The following table lists some examples of URI path template variables and how the URIs are resolved after substitution. The following variable names and values are used in the examples:
name1:jay
name2: gatsby
name3:
location: Main%20Street
question: why
The value of the name3 variable is an empty string.
URI Path Template |
URI After Substitution |
---|---|
http://example.com/{name1}/{name2}/ |
http://example.com/jay/gatsby/ |
http://example.com/{question}/ {question}/{question}/ |
http://example.com/why/why/why/ |
http://example.com/maps/{location} |
http://example.com/maps/Main%20Street |
http://example.com/{name3}/home/ |
http://example.com//home/ |
The behavior of a resource is determined by the HTTP methods (typically, GET, POST, PUT, DELETE) to which the resource is responding.
A request method designatorannotations are runtime annotations, defined by JAX-RS, and which correspond to the similarly named HTTP methods. Within a resource class file, HTTP methods are mapped to Java programming language methods using the request method designator annotations. The behavior of a resource is determined by which of the HTTP methods the resource is responding to. Jersey defines a set of request method designators for the common HTTP methods: @GET, @POST, @PUT, @DELETE, @HEAD, but you can create your own custom request method designators. Creating custom request method designators is outside the scope of this document.
The following example is an extract from the storage service sample that shows the use of the PUTmethod to create or update a storage container.
@PUT public Response putContainer() { System.out.println("PUT CONTAINER " + container); URI uri = uriInfo.getAbsolutePath(); Container c = new Container(container, uri.toString()); Response r; if (!MemoryStore.MS.hasContainer(c)) { r = Response.created(uri).build(); } else { r = Response.noContent().build(); } MemoryStore.MS.createContainer(c); return r; }
By default the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method (if present) and ignore the response entity (if set). For OPTIONS, the Allow response header will be set to the set of HTTP methods support by the resource. In addition Jersey will return a WADL document describing the resource.
Methods decorated with request method designators must return void, a Java programming language type, or a javax.ws.rs.core.Response object. Multiple parameters may be extracted from the URI using the PathParam or QueryParam annotations as described in Extracting Request Parameters. Conversion between Java types and an entity body is the responsibility of an entity provider, such as MessageBodyReader or MessageBodyWriter. Methods that need to provide additional metadata with a response should return an instance of Response. The ResponseBuilder class provides a convenient way to create a Response instance using a builder pattern. The HTTP PUT and POST methods expect an HTTP request body, so you should use a MessageBodyReader for methods that respond to PUT and POST requests.
Entity providers supply mapping services between representations and their associated Java types. There are two types of entity providers: MessageBodyReader and MessageBodyWriter. For HTTP requests, the MessageBodyReader is used to map an HTTP request entity body to method parameters. On the response side, a return value is mapped to an HTTP response entity body using a MessageBodyWriter. If the application needs to supply additional metadata, such as HTTP headers or a different status code, a method can return a Response that wraps the entity, and which can be built using Response.ResponseBuilder.
The following list contains the standard types that are supported automatically for entities. You only need to write an entity provider if you are not choosing one of the following, standard types.
byte[] — All media types (*/*)
java.lang.String — All text media types (text/*)
java.io.InputStream — All media types (*/*)
java.io.Reader — All media types (*/*)
java.io.File — All media types (*/*)
javax.activation.DataSource — All media types (*/*)
javax.xml.transform.Source — XML types (text/xml, application/xml and application/*+xml)
javax.xml.bind.JAXBElement and application-supplied JAXB classes XML media types (text/xml, application/xml and application/*+xml)
MultivaluedMap<String, String> — Form content (application/x-www-form-urlencoded)
StreamingOutput — All media types (*/*), MessageBodyWriter only
The following example shows how to use MessageBodyReader with the @Consumes and @Provider annotations:
@Consumes("application/x-www-form-urlencoded") @Provider public class FormReader implements MessageBodyReader<NameValuePair> {
The following example shows how to use MessageBodyWriter with the @Produces and @Provider annotations:
@Produces("text/html") @Provider public class FormWriter implements MessageBodyWriter<Hashtable<String, String>> {
The following example shows how to use ResponseBuilder:
@GET public Response getItem() { System.out.println("GET ITEM " + container + " " + item); Item i = MemoryStore.MS.getItem(container, item); if (i == null) throw new NotFoundException("Item not found"); Date lastModified = i.getLastModified().getTime(); EntityTag et = new EntityTag(i.getDigest()); ResponseBuilder rb = request.evaluatePreconditions(lastModified, et); if (rb != null) return rb.build(); byte[] b = MemoryStore.MS.getItemData(container, item); return Response.ok(b, i.getMimeType()). lastModified(lastModified).tag(et).build(); }
The information sent to a resource and then passed back to the client is specified as a MIME media type in the headers of an HTTP request or response. You can specify which MIME media types of representations a resource can respond to or produce by using the javax.ws.rs.Consumes and javax.ws.rs.Produces annotations.
By default, a resource class can respond to and produce all MIME media types of representations specified in the HTTP request and response headers.
The @Produces annotation is used to specify the MIME media types or representations a resource can produce and send back to the client. If @Produces is applied at the class level, all the methods in a resource can produce the specified MIME types by default. If it is applied at the method level, it overrides any @Produces annotations applied at the class level.
If no methods in a resource are able to produce the MIME type in a client request, the Jersey runtime sends back an HTTP “406 Not Acceptable” error.
The value of @Produces is an array of String of MIME types. For example:
@Produces({"image/jpeg,image/png"})
The following example shows how to apply @Produces at both the class and method levels:
@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 media type of the @Produces annotation at the class level. The doGetAsHtml method's @Produces annotation overrides the class-level @Produces setting, and specifies that the method can produce HTML rather than plain text.
If a resource class is capable of producing more that one MIME media type, the resource method chosen will correspond to the most acceptable media type as declared by the client. More specifically, the Accept header of the HTTP request declared what is most acceptable. For example if the Accept header is Accept: text/plain, the doGetAsPlainText method will be invoked. Alternatively if the Accept header is Accept: text/plain;q=0.9, text/html, which declares that the client can accept media types of text/plain and text/html, but prefers the latter, then the doGetAsHtml method will be invoked.
More than one media type may be declared in the same @Produces declaration. The following code example shows how this is done.
@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. The examples above refer explicitly to MIME media types for clarity. It is possible to refer to constant values, which may reduce typographical errors. For more information, see the constant field values of MediaType.
The @Consumes annotation is used to specify which MIME media types of representations a resource can accept, or consume, from the client. If @Consumes is applied at the class level, all the response methods accept the specified MIME types by default. If @Consumes is applied at the method level, it overrides any @Consumes annotations applied at the class level.
If a resource is unable to consume the MIME type of a client request, the Jersey runtime sends back an HTTP “415 Unsupported Media Type” error.
The value of @Consumes is an array of String of acceptable MIME types. For example:
@Consumes({"text/plain,text/html"})
The following example shows how to apply @Consumes at both the class and method levels:
@Path("/myResource") @Consumes("multipart/related") public class SomeResource { @POST public String doPost(MimeMultipart mimeMultipartData) { ... } @POST @Consumes("application/x-www-form-urlencoded") public String doPost2(FormURLEncodedProperties formData) { ... } }
The doPost method defaults to the MIME media type of the @Consumes annotation at the class level. The doPost2 method overrides the class level @Consumes annotation to specify that it can accept URL-encoded form data.
If no resource methods can respond to the requested MIME type, an HTTP 415 error (Unsupported Media Type) is returned to the client.
The HelloWorld example discussed previously in this section can be modified to set the cliched message using @Consumes, as shown in the following code example.
@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 HTTP 204 (No Content) will be returned.
Parameters of a resource method may be annotated with parameter-based annotations to extract information from a request. A previous example presented the use of the @PathParam parameter to extract a path parameter from the path component of the request URL that matched the path declared in @Path. There are six types of parameters you can extract for use in your resource class: query parameters, URI path parameters, form parameters, cookie parameters, header parameters, and matrix parameters.
Query parameters are extracted from the request URI query parameters, and are specified by using the javax.ws.rs.QueryParam annotation in the method parameter arguments. The following example (from the sparklines sample application) demonstrates using @QueryParam to extract query parameters from the Query component of the request URL.
@Path("smooth") @GET public Response smooth( @DefaultValue("2") @QueryParam("step") int step, @DefaultValue("true") @QueryParam("min-m") boolean hasMin, @DefaultValue("true") @QueryParam("max-m") boolean hasMax, @DefaultValue("true") @QueryParam("last-m") boolean hasLast, @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor, @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor, @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor ) { ... }
If a query parameter "step" exists in the query component of the request URI, then the "step" value will be extracted and parsed as a 32–bit signed integer and assigned to the step method parameter. If "step" does not exist, then a default value of 2, as declared in the @DefaultValue annotation, will be assigned to the step method parameter. If the "step" value cannot be parsed as a 32–bit signed integer, then an HTTP 400 (Client Error) response is returned.
User-defined Java types such as ColorParam may be used. The following code example shows how to implement this.
public class ColorParam extends Color { public ColorParam(String s) { super(getRGB(s)); } private static int getRGB(String s) { if (s.charAt(0) == '#') { try { Color c = Color.decode("0x" + s.substring(1)); return c.getRGB(); } catch (NumberFormatException e) { throw new WebApplicationException(400); } } else { try { Field f = Color.class.getField(s); return ((Color)f.get(null)).getRGB(); } catch (Exception e) { throw new WebApplicationException(400); } } } }
@QueryParam and @PathParam can only be used on the following Java types:
All primitive types except char
All wrapper classes of primitive types except Character
Have a constructor that accepts a single String argument
Any class with the static method named valueOf(String) that accepts a single String argument
Any class with a constructor that takes a single String as a parameter
List<T>, Set<T>, or SortedSet<T>, where T matches the already listed criteria. Sometimes parameters may contain more than one value for the same name. If this is the case, these types may be used to obtain all values.
If @DefaultValue is not used in conjunction with @QueryParam, and the query parameter is not present in the request, then value will be an empty collection for List, Set, or SortedSet; null for other object types; and the Java-defined default for primitive types.
URI path parameters are extracted from the request URI, and the parameter names correspond to the URI path template variable names specified in the @Path class-level annotation. URI parameters are specified using the javax.ws.rs.PathParam annotation in the method parameter arguments. The following example shows how to use @Path variables and the @PathParam annotation in a method:
@Path("/{userName}") public class MyResourceBean { ... @GET public String printUserName(@PathParam("userName") String userId) { ... } }
In the above snippet, the URI path template variable name userName is specified as a parameter to the printUserName method. The @PathParam annotation is set to the variable name userName. At runtime, before printUserName is called, the value of userName is extracted from the URI and cast to a String. The resulting String is then available to the method as the userId variable.
If the URI path template variable cannot be cast to the specified type, the Jersey runtime returns an HTTP 400 Bad Request error to the client. If the @PathParam annotation cannot be cast to the specified type, the Jersey runtime returns an HTTP 404 Not Found error to the client.
The @PathParam parameter and the other parameter-based annotations, @MatrixParam, @HeaderParam, @CookieParam, and @FormParam obey the same rules as @QueryParam.
Cookie parameters (indicated by decorating the parameter with javax.ws.rs.CookieParam) extract information from the cookies declared in cookie-related HTTP headers. Header parameters (indicated by decorating the parameter with javax.ws.rs.HeaderParam) extracts information from the HTTP headers. Matrix parameters (indicated by decorating the parameter with javax.ws.rs.MatrixParam) extracts information from URL path segments. These parameters are beyond the scope of this tutorial.
Form parameters (indicated by decorating the parameter with javax.ws.rs.FormParam) extract 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. The following example extracts the form parameter named "name" from the POSTed form data.
@POST @Consumes("application/x-www-form-urlencoded") public void post(@FormParam("name") String name) { // Store the message }
If it is necessary to obtain a general map of parameter names to values, use code such as that shown in the following example , for query and path parameters.
@GET public String get(@Context UriInfo ui) { MultivaluedMap<String, String> queryParams = ui.getQueryParameters(); MultivaluedMap<String, String> pathParams = ui.getPathParameters(); }
Or code such as the following for header and cookie parameters:
@GET public String get(@Context HttpHeaders hh) { MultivaluedMap<String, String> headerParams = hh.getRequestHeaders(); Map<String, Cookie> pathParams = hh.getCookies(); }
In general @Context can be used to obtain contextual Java types related to the request or response.
For form parameters it is possible to do the following:
@POST @Consumes("application/x-www-form-urlencoded") public void post(MultivaluedMap<String, String> formParams) { // Store the message }
The following documents contain information that you might find useful when creating applications using Jersey and JAX-RS.
Overview of JAX-RS 1.0 Features
This document contains some of the information from this tutorial, as well as additional topics such as Representations and Java types, Building Responses, Sub-resources, Building URIs, WebApplicationException and mapping Exceptions to Responses, Conditional GETs and Returning 304 (Not Modified) Responses, Life-cycle of root resource classes, Security, Rules of Injection, Use of @Context, and APIs defined by JAX-RS.
Overview of Jersey 1.0 Features
This document contains the following topics: Deployment, Web-Deployment Using Servlet, Embedded-Web-Deployment Using GlassFish, Embedded-Deployment Using Grizzly, Embedded-Web-Deployment Using Grizzly, Client-Side API, Client-Side Filters, Integration with Spring, JSON, JAXB, Module View Controller with JSPs, Resource Class Life-Cycle, Resource Class Instantiation, Web Application Description Language (WADL) Support, Pluggable Templates for Model View Controller, Server-Side Filters URI utilities, Web Application Reloading, Pluggable Injection, Pluggable Life-Cycle, Pluggable HTTP containers, and Pluggable IoC Integration.