This chapter describes how to develop WebLogic Web services that conform to the Representational State Transfer (REST) architectural style using Java API for RESTful Web Services (JAX-RS).
This chapter includes the following sections:
Defining the Relative URI of the Root Resource and Subresources
Customizing Media Types for the Request and Response Messages
Mapping HTTP Request and Response Entity Bodies Using Entity Providers
For information about developing RESTful Web service clients using Oracle JDeveloper, see "Creating RESTful Web Services and Clients" in Developing Applications with Oracle JDeveloper.
JAX-RS is a Java programming language API that uses annotations to simplify the development of RESTful Web services. JAX-RS annotations are runtime annotations. When you deploy the Java EE application archive containing JAX-RS resource classes to WebLogic Server, as described in Chapter 4, "Packaging and Deploying RESTful Web Services," the runtime configures the resources, generates the helper classes and artifacts, and exposes the resource to clients.
The following sections provide more information about RESTful Web service development:
Table 2-1 summarizes a subset of the tasks that are required to develop RESTful Web service using JAX-RS annotations. For more information about advanced tasks, see More Advanced RESTful Web Service Tasks.
In addition to the development tasks described below, you may wish to create a class that extends javax.ws.rs.core.Application
to define the components of a RESTful Web service application deployment and provides additional metadata. For more information, see Packaging With an Application Subclass.
Table 2-1 Summary of Tasks to Develop RESTful Web Services
Task | More Information |
---|---|
Define the root resource class. |
|
Define the relative URI of the root resource class and its methods using the If you define the |
Defining the Relative URI of the Root Resource and Subresources |
Map incoming HTTP requests to your Java methods using |
|
Customize the request and response messages, as required, to specify the MIME media types of representations a resource can produce and consume. |
Customizing Media Types for the Request and Response Messages |
Extract information from the request. |
|
Build custom response messages to customize response codes or include additional metadata. |
|
Access information about the application deployment context or the context of individual requests. |
|
Build new or extend existing resource URIs. |
|
Evaluate one or more preconditions before processing a GET request, potentially reducing bandwidth and improving server performance. |
|
Access the WADL. |
|
Secure your RESTful Web services. |
Example 2-1 provides a simple example of a RESTful Web service. In this example:
The helloWorld
class is a resource with a relative URI path defined as /helloworld
. At runtime, if the context root for the WAR file is defined as http://examples.com
, the full URI to access the resource is http://examples.com/helloworld
. For more information, see Defining the Relative URI of the Root Resource and Subresources.
The sayHello
method supports the HTTP GET method. For more information, see Mapping Incoming HTTP Requests to Java Methods.
The sayHello
method produces content of the MIME media type text/plain
. For more information, see Customizing Media Types for the Request and Response Messages.
Additional examples are listed in Learn More About RESTful Web Services.
Example 2-1 Simple RESTful Web Service
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; // Specifies the path to the RESTful service @Path("/helloworld") public class helloWorld { // Specifies that the method processes HTTP GET requests @GET @Produces("text/plain") public String sayHello() { return "Hello World!"; } }
A root resource class is a Plain Old Java Object (POJO) for which one or both of the following statements are true:
Is annotated with @Path
. For more information, see Defining the Relative URI of the Root Resource and Subresources.
Has at least one method annotated with @Path
or with a request method designator, such as @GET
, @POST
, @PUT
, or @DELETE
. A resource method is a method in the resource class that is annotated using a request method designator. For more information, see Mapping Incoming HTTP Requests to Java Methods.
Add the javax.ws.rs.Path
annotation at the class level of the resource to define the relative URI of the RESTful Web service. Such classes are referred to a root resource classes. You can add @Path
on methods of the root resource class as well, to define subresources to group specific functionality.
The following sections describe how to define the relative URI of the root resource and subresources:
The @Path
annotation defines the relative URI path for the resource, and can be defined as a constant or variable value (referred to as "URI path template"). You can add the @Path
annotation at the class or method level.
To define the URI as a constant value, pass a constant value to the @Path
annotation. Preceding and ending slashes (/) are optional.
In Example 2-2, the relative URI for the resource class is defined as the constant value, /helloworld
.
Example 2-2 Defining the Relative URI as a Constant Value
package samples.helloworld; import javax.ws.rs.Path; ... // Specifies the path to the RESTful service @Path("/helloworld") public class helloWorld {. . .}
To define the URI as a URI path template, pass one or more variable values enclosed in braces in the @Path
annotation. Then, you can use the javax.ws.rs.PathParam
annotation to extract variable information from the request URI, defined by the @Path
annotation, and initialize the value of the method parameter, as described in How to Extract Variable Information from the Request URI (@PathParam).
In Example 2-3, the relative URI for the resource class is defined using a variable, enclosed in braces, for example, /users/{username}
.
Example 2-3 Defining the Relative URI as a Variable Value
package samples.helloworld; import javax.ws.rs.Path; ... // Specifies the path to the RESTful service @Path("/users/{username}") public class helloWorld {. . .} }
To further customize the variable, you can override the default regular expression of "[^/]+?" by specifying the expected regular expression as part of the variable definition. For example:
@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]}")
In this example, the username
variable will match only user names that begin with one uppercase or lowercase letter followed by zero or more alphanumeric characters or the underscore character. If the username does not match the requirements, a 404 (Not Found)
response will be sent to the client.
For more information about the @Path
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/Path.html
.
Add the javax.ws.rs.Path
annotation to the method of a resource to define a subresource. Subresources enable users to group specific functionality for a resource.
In Example 2-3, if the request path of the URI is users/list
, then the getUserList
subresource method is matched and a list of users is returned.
The base URI is constructed as follows:
http://myHostName/contextPath/servletURI/resourceURI
myHostName
—DNS name mapped to the Web Server. You can replace this with host:port
which specifies the name of the machine running WebLogic Server and the port used to listen for requests.
contextPath
—Name of the standalone Web application. The Web application name is specified in the META-INF/application.xml
deployment descriptor in an EAR file or the weblogic.xml
deployment descriptor in a WAR file. If not specified, it defaults to the name of the WAR file minus the .war
extension. For more information, see "context-root" in Developing Web Applications, Servlets, and JSPs for Oracle WebLogic Server.
servletURI
—Base URI for the servlet context path. This path is configured as part of the packaging options defined in Table 4-1. Specifically, you can define the servlet context path by:
Updating the web.xml
deployment descriptor to define the servlet mapping.
Adding a javax.ws.rs.ApplicationPath
annotation to the class that extends javax.ws.rs.core.Application
, if defined.
If the servlet context path is configured using both options above, then the servlet mapping takes precedence. If you do not configure the servlet context path in your configuration using either of the options specified above, the WebLogic Server provides a default RESTful Web service application context path, resources
. For more information, see About RESTful Web Service Packaging and Deployment.
resourceURI
—@Path
value specified for the resource or subresource. This path may be constructed from multiple resources and subresources @Path
values.
In Example 2-2, at runtime, if the context path for the WAR file is defined as rest
and the default URI for the servlet (resources
) is in effect, the base URI to access the resource is http://myServer:7001/rest/resources/helloworld
.
In Example 2-3, at runtime, the base URI will be constructed based on the value specified for the variable. For example, if the user entered johnsmith
as the username, the base URI to access the resource is http://myServer:7001/rest/resources/users/johnsmith
.
JAX-RS uses Java annotations to map an incoming HTTP request to a Java method. Table 2-2 lists the annotations available, which map to the similarly named HTTP methods.
Table 2-2 javax.ws.rs Annotations for Mapping HTTP Requests to Java Methods
Annotation | Description | Idempotent |
---|---|---|
|
Transmits a representation of the resource identified by the URI to the client. The format might be HTML, plain text, JPEG, and so on. See How to Transmit a Representation of the Resource (@GET). |
Yes |
|
Creates or updates the representation of the specified resource identified by the URI. See How to Create or Update the Representation of the Resource (@PUT). |
Yes |
|
Deletes the representation of the resource identified by the URI. See How to Delete a Representation of the Resource (@DELETE). |
Yes |
|
Creates, updates, or performs an action on the representation of the specified resource identified by the URI. See How to Create, Update, or Perform an Action on a Representation of the Resource (@POST). |
No |
|
Returns the response headers only, and not the actual resource (that is, no message body). This is useful to save bandwidth to check characteristics of a resource without actually downloading it. For more information, see The |
Yes |
|
Returns the communication options that are available on the request/response chain for the specified resource identified by the URI. The The |
Yes |
|
Indicates that the annotated method should be used to handle HTTP requests. For more information, see |
N/A |
The following sections provide more information about the JAX-RS annotations used for mapping HTTP requests to Java methods.
How to Create or Update the Representation of the Resource (@PUT)
How to Create, Update, or Perform an Action on a Representation of the Resource (@POST)
The examples referenced in the following sections are excerpted from the bookmark sample that is delivered with Jersey 1.13 JAX-RS RI. The bookmark sample provides a Web application that maintains users and the browser bookmarks that they set.
The following table summarizes the resource classes in the sample, their associated URI path, and the HTTP methods demonstrated by each class.
Table 2-3 About the Jersey Bookmark Sample
Resource Class | URI Path | HTTP Methods Demonstrated |
---|---|---|
|
|
GET |
|
|
GET, PUT, DELETE |
|
|
GET, POST |
|
|
GET. PUT, DELETE |
The bookmark sample, and other Jersey samples, can be accessed in one of the following ways:
Downloading the Jersey 1.13 software at https://jersey.java.net
Browsing the Maven repositories at: https://maven.java.net/content/repositories/releases/com/sun/jersey/samples
The javax.ws.rs.GET
annotation transmits a representation of the resource identified by the URI to the client. The format or the representation returned in the response entity-body might be HTML, plain text, JPEG, and so on. For more information about the @GET
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/GET.html
.
In Example 2-5, the annotated Java method, getBookmarkAsJsonArray
, from the BookmarksResource
class in the Jersey bookmark sample, will process HTTP GET requests. For more information about the Jersey bookmark sample, see About the Jersey Bookmark Sample.
Example 2-5 Mapping the HTTP GET Request to a Java Method (BookmarksResource Class)
import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarksResource { ... @Path("{bmid: .+}") public BookmarkResource getBookmark(@PathParam("bmid") String bmid) { return new BookmarkResource(uriInfo, em, userResource.getUserEntity(), bmid); } @GET @Produces("application/json") public JSONArray getBookmarksAsJsonArray() { JSONArray uriArray = new JSONArray(); for (BookmarkEntity bookmarkEntity : getBookmarks()) { UriBuilder ub = uriInfo.getAbsolutePathBuilder(); URI bookmarkUri = ub. path(bookmarkEntity.getBookmarkEntityPK().getBmid()). build(); uriArray.put(bookmarkUri.toASCIIString()); } return uriArray; } ... }
In Example 2-6, the annotated Java method, getBookmark
, from the BookmarkResource
class in the Jersey bookmark sample, will process HTTP GET requests. This example shows how to process the JSON object that is returned. For more information about the Jersey bookmark sample, see About the Jersey Bookmark Sample.
Example 2-6 Mapping the HTTP GET Request to a Java Method (BookmarkResource Class)
import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @GET @Produces("application/json") public JSONObject getBookmark() { return asJson(); } ... public JSONObject asJson() { try { return new JSONObject() .put("userid", bookmarkEntity.getBookmarkEntityPK().getUserid()) .put("sdesc", bookmarkEntity.getSdesc()) .put("ldesc", bookmarkEntity.getLdesc()) .put("uri", bookmarkEntity.getUri()); } catch (JSONException je){ return null; } } }
The javax.ws.rs.PUT
annotation creates or updates the representation of the specified resource identified by the URI. For more information about the @PUT
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/PUT.html
.
In Example 2-7, the annotated Java method, putBookmark
, from the BookmarkResource
class in the Jersey bookmark sample, will process HTTP PUT requests and update the specified bookmark. For more information about the Jersey bookmark sample, see About the Jersey Bookmark Sample.
Example 2-7 Mapping the HTTP PUT Request to a Java Method
import javax.ws.rs.PUT; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @PUT @Consumes("application/json") public void putBookmark(JSONObject jsonEntity) throws JSONException { bookmarkEntity.setLdesc(jsonEntity.getString("ldesc")); bookmarkEntity.setSdesc(jsonEntity.getString("sdesc")); bookmarkEntity.setUpdated(new Date()); TransactionManager.manage(new Transactional(em) { public void transact() { em.merge(bookmarkEntity); }}); } }
The javax.ws.rs.DELETE
annotation deletes the representation of the specified resource identified by the URI. The response entity-body may return a status message or may be empty. For more information about the @DELETE
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/DELETE.html
.
In Example 2-8, the annotated Java method, deleteBookmark
, from the BookmarkResource
class in the Jersey bookmark sample, will process HTTP DELETE requests, and delete the specified bookmark. For more information about the Jersey bookmark sample, see About the Jersey Bookmark Sample.
Example 2-8 Mapping the HTTP DELETE Request to a Java Method
import javax.ws.rs.DELETE; import javax.ws.rs.Produces; import javax.ws.rs.Path; ... public class BookmarkResource { ... @DELETE public void deleteBookmark() { TransactionManager.manage(new Transactional(em) { public void transact() { UserEntity userEntity = bookmarkEntity.getUserEntity(); userEntity.getBookmarkEntityCollection().remove(bookmarkEntity); em.merge(userEntity); em.remove(bookmarkEntity); }}); } }
The javax.ws.rs.POST
annotation creates, updates, or performs an action on the representation of the specified resource identified by the URI. For more information about the @POST
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/POST.html
.
In Example 2-9, the annotated Java method, postForm
, from the BookmarksResource
class in the Jersey bookmark sample, will process HTTP POST requests, and update the specified information. For more information about the Jersey bookmark sample, see About the Jersey Bookmark Sample.
Example 2-9 Mapping the HTTP POST Request to a Java Method
import javax.ws.rs.POST; import javax.ws.rs.Produces; ... public class BookmarksResource { ... @POST @Consumes("application/json") public Response postForm(JSONObject bookmark) throws JSONException { final BookmarkEntity bookmarkEntity = new BookmarkEntity( getBookmarkId(bookmark.getString("uri")), userResource.getUserEntity().getUserid()); bookmarkEntity.setUri(bookmark.getString("uri")); bookmarkEntity.setUpdated(new Date()); bookmarkEntity.setSdesc(bookmark.getString("sdesc")); bookmarkEntity.setLdesc(bookmark.getString("ldesc")); userResource.getUserEntity().getBookmarkEntityCollection().add(bookmarkEntity); TransactionManager.manage(new Transactional(em) { public void transact() { em.merge(userResource.getUserEntity()); }}); URI bookmarkUri = uriInfo.getAbsolutePathBuilder(). path(bookmarkEntity.getBookmarkEntityPK().getBmid()). build(); return Response.created(bookmarkUri).build(); } }
Add the javax.ws.rs.Consumes
or javax.ws.rs.Produces
annotation at the class level of the resource to customize the request and response media types, as described in the following sections:
How To Customize Media Types for the Request Message (@Consumes)
How To Customize Media Types for the Response Message (@Produces)
What Happens At Runtime: How the Resource Method Is Selected for Response Messages
The javax.ws.rs.Consumes
annotation enables you to specify the MIME media types of representations a resource can consume that were sent from the client. The @Consumes
annotation can be specified at both the class and method levels and more than one media type can be declared in the same @Consumes
declaration.
If there are no methods in a resource that can consume the specified MIME media types, the runtime returns an HTTP 415 Unsupported Media Type
error.
For more information about the @Consumes
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/Consumes.html
.
In Example 2-11, the @Consumes
annotation defined for the Java class, helloWorld
, specifies that the class produces messages using the text/plain
MIME media type.
Example 2-10 Customizing the Media Types for the Request Message Using @Consumes
package samples.consumes; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/helloworld") public class helloWorld { ... @POST @Consumes("text/plain") public void postMessage(String message) { // Store the message } }
The javax.ws.rs.Produces
annotation enables you to specify the MIME media types of representations a resource can produce and send back to the client. The @Produces
annotation can be specified at both the class and method levels and more than one media type can be declared in the same @Produces
declaration.
If there are no methods in a resource that can produce the specified MIME media types, the runtime returns an HTTP 406 Not Acceptable
error.
For more information about the @Produces
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/Produces.html
.
In Example 2-11, the @Produces
annotation specified for the Java class, SomeResource
, specifies that the class produces messages using the text/plain
MIME media type. The doGetAsPlainText
method defaults to the MIME media type specified at the class level. The doGetAsHtml
method overrides the class-level setting and specifies that the method produces HTML rather than plain text.
Example 2-11 Customizing the Media Types for the Response Using @Produces
package samples.produces; import javax.ws.rs.Produces; import javax.ws.rs.Path; @Path("/myResource") @Produces("text/plain") public class SomeResource { @GET public String doGetAsPlainText() { ... } @GET @Produces("text/html") public String doGetAsHtml() { ... } }
If a resource class is capable of producing more that one MIME media type, then the resource method that is selected corresponds to the acceptable media type declared in the Accept
header of the HTTP request. In Example 2-11, if the Accept
header is Accept: text/html
, then the doGetAsPlainText
method is invoked.
If multiple MIME media types are included in the @Produces
annotation and both are acceptable to the client, the first media type specified is used. In Example 2-11, if the Accept
header is Accept: application/html, application/text
, then the doGetAsHtml
method is invoked and the application/html
MIME media type is used as it is listed first in the list.
The javax.ws.rs
package defines a set of annotations, shown in Table 2-2, that enable you extract information from the request message to inject into parameters of your Java method.
Table 2-4 javax.ws.rs Annotations for Extracting Information From the Request Message
Annotation | Description |
---|---|
|
Extract information from the HTTP cookie-related headers to initialize the value of a method parameter. For more information, see |
|
Define the default value of the request metadata that is bound using one of the following annotations: |
|
Enable encoding of a parameter value that is bound using one of the following annotations: |
|
Extract information from an HTML form of the type |
|
Extract information from the HTTP headers to initialize the value of a method parameter. For more information, see |
|
Extract information from the URI path segments to initialize the value of a method parameter. For more information, see |
|
Define the relative URI as a variable value (referred to as "URI path template"). For more information, see How to Extract Variable Information from the Request URI (@PathParam). |
|
Extract information from the query portion of the request URI to initialize the value of a method parameter. For more information, see How to Extract Request Parameters (@QueryParam). |
Add the javax.ws.rs.PathParam
annotation to the method parameter of a resource to extract the variable information from the request URI and initialize the value of the method parameter. You can define a default value for the variable value using the @DefaultValue
annotation, as described in How to Define the DefaultValue (@DefaultValue).
In Example 2-3, the @PathParam
annotation assigns the value of the username
variable that is defined as part of the URI path by the @Path
annotation to the userName
method parameter.
Example 2-12 Extracting Variable Information From the Request URI
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.PathParam; // Specifies the path to the RESTful service @Path("/users") public class helloWorld { . . . @GET @Path("/{username}") @Produces("text/xml") public String getUser(@PathParam("username") String userName) { ... } }
Add the javax.ws.rs.QueryParam
annotation to the method parameter of a resource to extract information from the query portion of the request URI and initialize the value of the method parameter.
The type of the annotated method parameter can be any of the following:
Primitive type (int
, char
, byte
, and so on)
User-defined type
Constructor that accepts a single String argument
Static method named valueOf
or fromString
that accepts a single String argument (for example, integer.valueOf(String)
)
List<T>
, Set<T>
, or SortedSet<T>
If the @QueryParam
annotation is specified but the associated query parameter is not present in the request, then the parameter value will set as an empty collection for List
, Set
or SortedSet
, the Java-defined default for primitive types, and NULL for all other object types. Alternatively, you can define a default value for the parameter using the @DefaultValue
annotation, as described in How to Define the DefaultValue (@DefaultValue).
For more information about the @QueryParam
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/QueryParam.html
.
In Example 2-13, if the step
query parameter exists in the query component of the request URI, the value will be assigned to the step
method parameter as an integer value. If the value cannot be parsed as an integer value, then a 400 (Client Error)
response is returned. If the step
query parameter does not exist in the query component of the request URI, then the value is set to NULL.
Add the javax.ws.rs.DefaultValue
annotation to define the default value of the request metadata that is bound using one of the following annotations: @CookieParam
, @FormParam
, @HeaderParam
, @MatrixParam
, @PathParam
, or @QueryParam
. For more information about the @DefaultValue
annotation, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/DefaultValue.html
.
In Example 2-14, if the step
query parameter does not exist in the query component of the request URI, the default value of 2 will be assigned to the step
parameter.
Add the javax.ws.rs.Encode
annotation at the class or method level to enable the encoding of a parameter value that is bound using one of the following annotations: @FormParam
, @MatrixParam
, @PathParam
, or @QueryParam
. If specified at the class level, parameters for all methods in the class will be encoded. For more information, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/Encoded.html
.
In Example 2-15, the @Encode
annotation enables the encoding of parameter values bound using the @PathParam
annotation.
Example 2-15 Encoding Parameter Values
package samples.helloworld; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.PathParam; import javax.ws.rs.Encode; // Specifies the path to the RESTful service @Path("/users") public class helloWorld { . . . @GET @Path("/{username}") @Produces("text/xml") @Encode public String getUser(@PathParam("username") String userName) { ... } }
By default, JAX-RS responds to HTTP requests using the default response codes defined in the HTTP specification, such as 200 OK
for a successful GET request and 201 CREATED
for a successful PUT request.
In some cases, you may want to customize the response codes returned or include additional metadata information in the response. For example, you might want to include the Location
header to specify the URI to the newly created resource. You can modify the response message returned using the javax.ws.rs.core.Response
class.
An application can extend the Response
class directly or use one of the static Response
methods, defined in Table 2-5, to create a javax.ws.rs.core.Response.ResponseBuilder
instance and build the Response
instance. For more information about the Response
methods, see the Javadoc at http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/core/Response.html
.
Table 2-5 Creating a Response Instance Using the ResponseBuilder Class
Method | Description |
---|---|
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
|
Creates a new |
Once you create a ResponseBuilder
instance, you can call the methods defined in Table 2-6 to build a custom response. Then, call the build()
method to create the final Response
instance. For more information about the ResponseBuilder
class and its methods, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/core/Response.ResponseBuilder.html
.
Table 2-6 ResponseBuilder Methods for Building a Custom Response
Method | Description |
---|---|
|
Creates the Response instance from the current |
|
Sets the cache control. |
|
Create a copy of the |
|
Sets the content location. |
|
Add cookies to the response. |
|
Defines the entity. |
|
Sets the expiration date. |
|
Adds a header to the response. |
|
Sets the language. |
|
Set the last modified date. |
|
Sets the location. |
|
Creates a new |
|
Sets the status. |
|
Sets an entity tag. |
|
Sets the response media type. |
|
Set representation metadata. |
|
Add a |
Example 2-16 shows how to build a Response
instance using ResponseBuilder
. In this example, the standard status code of 200 OK
is returned and the media type of the response is set to text/html
. A call to the build()
method creates the final Response
instance.
Example 2-16 Building a Custom Response
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.ResponseBuilder; ... @Path("/content") public class getDocs { @GET @Path("{id}") public Response getHTMLDoc(@PathParm("id") int docId) { Document document = ...; ResponseBuilder response = Response.ok(document); response.type("text/html"); return response.build(); } }
If you wish to build an HTTP response using a generic type, to avoid type erasure at runtime you need to create a javax.ws.rs.core.GenericEntity
object to preserve the generic type. For more information, see http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/core/GenericEntity.html
.
Example 2-17 provides an example of how to build an HTTP response using GenericEntity
to preserve the generic type.
Example 2-17 Building a Custom Response Using a Generic Type
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.ResponseBuilder; javax.ws.rs.core.GenericEntity; ... @Path("/content") public class getDocs { @GET @Path("{id}") public Response getHTMLDoc(@PathParm("id") int docId) { Document document = ...; List<String> list = new ArrayList<String>(); GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {}; ... ResponseBuilder response = Response.ok(document); response.entity(entity); return response.build(); } }
Table 2-7 lists the Java types that are supported automatically by HTTP request and response entity bodies.
Table 2-7 Java Types Supported for HTTP Request and Response Entity Bodies
Java Type | Supported Media Types |
---|---|
|
All media types (*/*) |
|
All media types (*/*) |
|
All media types (*/*) |
|
All media types (*/*) |
|
All media types (*/*) |
|
All media types (*/*) |
|
XML media types ( |
|
XML media types ( |
|
Form content ( |
|
All media types (*/*), |
If your RESTful Web service utilizes a type that is not listed in Table 2-7, you must define an entity provider, by implementing one of the interfaces defined in Table 2-8, to map HTTP request and response entity bodies to method parameters and return types.
Table 2-8 Entity Providers for Mapping HTTP Request and Response Entity Bodies to Method Parameters and Return Types
Entity Provider | Description |
---|---|
|
Maps an HTTP request entity body to a method parameter for an HTTP request. Optionally, you can use the For example: @Consumes("application/x-www-form-urlencoded") @Provider public class FormReader implements MessageBodyReader<NameValuePair> { ... } |
|
Maps the return value to an HTTP response entity body for an HTTP response. Optionally, you can use the For example: @Produces("text/html") @Provider public class FormWriter implements MessageBodyWriter<Hashtable<String, String>> { ... } |
Note:
Jersey JSON provides a set of JAX-RS MessageBodyReader
and MessageBodyWriter
providers distributed with the jersey-json module. For more information, see "JSON Support" in the Jersey User Guide
at: https://jersey.java.net/documentation/1.13/user-guide.html#json
.
The following code excerpt provides an example of a class that contains a method (getClass
) that returns a custom type, and that requires you to write an entity provider.
public class Class1 { public String hello() { return "Hello"; } public Class2 getClass(String name) { return new Class2(); }; } public class Class2 { public Class2() { } }
The javax.ws.rs.core.Context
annotation enables you to access information about the application deployment context and the context of individual requests. Table 2-9 summarizes the context types that you can access using the @Context
annotation. For more information, see the Javadoc at http://docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/core/Context.html
.
Use this context type . . . | To . . . |
---|---|
|
Access HTTP header information. |
|
Lookup Provider instances based on a set of search criteria. |
|
Determine the best matching representation variant and to evaluate whether the current state of the resource matches any preconditions defined. For more information, see Using Conditional GETs. |
|
Access the security context and secure the RESTful Web service. For more information, see Securing RESTful Web Services Using SecurityContext. |
|
Access application and request URI information. For more information, see Building URIs. |
You can use javax.ws.rs.core.UriInfo
to access application and request URI information. Specifically, UriInfo
can be used to return the following information:
Deployed application's base URI
Request URI relative to the base URI
Absolute path URI (with or without the query parameters)
Using UriInfo
you can return a URI or javax.ws.rs.core.UriBuilder
instance. UriBuilder
simplifies the process of building URIs, and can be used to build new or extend existing URIs.
The UriBuilder
methods perform contextual encoding of characters not permitted in the corresponding URI component based on the following rules:
application/x-www-form-urlencoded
media type for query parameters, as defined in "Forms" in the HTML specification at the following URL: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
RFC 3986 for all other components, as defined at the following URL: http://www.ietf.org/rfc/rfc3986.txt
Example 2-18 shows how to obtain an instance of UriInfo
using @Context
and use it to return an absolute path of the request URI as a UriBuilder
instance. Then, using UriBuilder
build a URI for a specific user resource by adding the user ID as a path segment and store it in an array. In this example, the UriInfo
instance is injected into a class field. This example is excerpted from the bookmark sample, as described in About the Jersey Bookmark Sample.
import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Context; ... @Path("/users/") public class UsersResource { @Context UriInfo uriInfo; ... @GET @Produces("application/json") public JSONArray getUsersAsJsonArray() { JSONArray uriArray = new JSONArray(); for (UserEntity userEntity : getUsers()) { UriBuilder ub = uriInfo.getAbsolutePathBuilder(); URI userUri = ub.path(userEntity.getUserid()).build(); uriArray.put(userUri.toASCIIString()); } return uriArray; } }
A conditional GET enables you to evaluate one or more preconditions before processing a GET request. If the preconditions are met, a Not Modified (304)
response can be returned rather than the normal response, potentially reducing bandwidth and improving server performance.
JAX-RS provides the javax.ws.rs.core.Request
contextual interface enabling you to perform conditional GETs. You call the evaluatePreconditions()
method and pass a javax.ws.rs.core.EntityTag
, the last modified timestamp (as a java.util.Date
object), or both. The values are compared to the If-None-Match
or If-Not-Modified
headers, respectively, if these headers are sent with the request.
If headers are included with the request and the precondition values match the header values, then the evaluatePreconditions()
methods returns a predefined ResponseBuilder
response with a status code of Not Modified (304)
. If the precondition values do no match, the evaluatePreconditions()
method returns null and the normal response is returned, with 200, OK
status.
Example 2-19 shows how to pass the EntityTag
to the evaluatePreconditions()
method and build the response based on whether the preconditions are met.
Example 2-19 Using Conditional GETs
... @Path("/employee/{joiningdate}") public class Employee { Date joiningdate; @GET @Produces("application/xml") public Employee(@PathParam("joiningdate") Date joiningdate, @Context Request req, @Context UriInfo ui) { this.joiningdate = joiningdate; ... this.tag = computeEntityTag(ui.getRequestUri()); if (req.getMethod().equals("GET")) { Response.ResponseBuilder rb = req.evaluatePreconditions(tag); // Preconditions met if (rb != null) { return rb.build(); } // Preconditions not met rb = Response.ok(); rb.tag(tag); return rb.build(); } } }
The Web Application Description Language (WADL) is an XML-based file format that describes your RESTful Web services application. By default, a basic WADL is generated at runtime and can be accessed from your RESTful Web service by issuing a GET
on the /application.wadl
resource at the base URI of your RESTful application. For example:
GET http://<path_to_REST_app>/application.wadl
Alternatively, you can use the OPTIONS
method to return the WADL for particular resource.
Example 2-20 shows an example of a WADL for the simple RESTful Web service shown in Example 2-1.
Example 2-20 Example of a WADL
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <application xmlns="http://research.sun.com/wadl/2006/10"> <doc xmlns:jersey="http://jersey.dev.java.net/" jersey:generatedBy="Jersey: 0.10-ea-SNAPSHOT 08/27/2008 08:24 PM"/> <resources base="http://localhost:9998/"> <resource path="/helloworld"> <method name="GET" id="sayHello"> <response> <representation mediaType="text/plain"/> </response> </method> </resource> </resources> </application>
For more information about advanced RESTful Web service development tasks, including those listed below, see the Jersey 1.13 User Guide at http://jersey.java.net/nonav/documentation/1.13/user-guide.html
.
Integrating JAX-RS with EJB technology and Contexts and Dependency Injection (CDI)
Using JAXB and JSON