47.3. Fine tuning an application's responses
47.3.1. Basics of building responses
Overview
Response
class allows a resource method to have some control over the return status sent to the consumer and to specify HTTP message headers and cookies in the response.
Response
objects wrap the object representing the entity that is returned to the consumer. Response
objects are instantiated using the ResponseBuilder
class as a factory.
ResponseBuilder
class also has many of the methods used to manipulate the response's metadata. For instance the ResonseBuilder
class contains the methods for setting HTTP headers and cache control directives.
Relationship between a response and a response builder
Response
class has a protected constructor, so they cannot be instantiated directly. They are created using the ResponseBuilder
class enclosed by the Response
class. The ResponseBuilder
class is a holder for all of the information that will be encapsulated in the response created from it. The ResponseBuilder
class also has all of the methods responsible for setting HTTP header properties on the message.
Response
class does provide some methods that ease setting the proper response code and wrapping the entity. There are methods for each of the common response status codes. The methods corresponding to status that include an entity body, or required metadata, include versions that allow for directly setting the information into the associated response builder.
ResponseBuilder
class' build()
method returns a response object containing the information stored in the response builder at the time the method is invoked. After the response object is returned, the response builder is returned to a clean state.
Getting a response builder
- Using the static methods of the
Response
class as shown in Example 47.1, “Getting a response builder using theResponse
class”.Example 47.1. Getting a response builder using the
Response
classimport javax.ws.rs.core.Response; Response r = Response.ok().build();
When getting a response builder this way you do not get access to an instance you can manipulate in multiple steps. You must string all of the actions into a single method call. - Using the Apache CXF specific
ResponseBuilderImpl
class. This class allows you to work directly with a response builder. However, it requires that you manually set all of the response builders information manually.Example 47.2, “Getting a response builder using theResponseBuilderImpl
class” shows how Example 47.1, “Getting a response builder using theResponse
class” could be rewritten using theResponseBuilderImpl
class.Example 47.2. Getting a response builder using the
ResponseBuilderImpl
classimport javax.ws.rs.core.Response; import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl; ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.status(200); Response r = builder.build();
NoteYou could also simply assign theResponseBuilder
returned from aResponse
class' method to aResponseBuilderImpl
object.
More information
Response
class see the Response
class' Javadoc.
ResponseBuilder
class see the ResponseBuilder
class' Javadoc.
ResponseBuilderIml
class see the ResponseBuilderImpl
Javadoc.
47.3.2. Creating responses for common use cases
Overview
Response
class provides shortcut methods for handling the more common responses that a RESTful service will need. These methods handle setting the proper headers using either provided values or default values. They also handle populating the entity body when appropriate.
Creating responses for successful requests
OK
. An OK
response typically contains an entity that corresponds to the request. The Response
class has an overloaded ok()
method that sets the response status to 200
and adds a supplied entity to the enclosed response builder. There are five versions of the ok()
method. The most commonly used variant are:
Response.ok()
—creates a response with a status of200
and an empty entity body.Response.ok(java.lang.Object entity)
—creates a response with a status of200
, stores the supplied object in the responses entity body, and determines the entities media type by introspecting the object.
200
response” shows an example of creating a response with an OK
status.
Example 47.3. Creating a response with an 200
response
import javax.ws.rs.core.Response; import demo.jaxrs.server.Customer; ... Customer customer = new Customer("Jane", 12); return Response.ok(customer).build();
204 No Content
status instead of an 200 OK
status. The Response.noContent()
method will create an appropriate response object.
204
status” shows an example of creating a response with an 204
status.
Example 47.4. Creating a response with a 204
status
import javax.ws.rs.core.Response; return Response.noContent().build();
Creating responses for redirection
Response
class provides methods for handling three of the redirection response statuses.
303 See Other
- The
303 See Other
status is useful when the requested resource needs to permanently redirect the consumer to a new resource to process the request.TheResponse
classesseeOther()
method creates a response with a303
status and places the new resource URI in the message'sLocation
field. TheseeOther()
method takes a single parameter that specifies the new URI as ajava.net.URI
object. 304 Not Modified
- The
304 Not Modified
status can be used for different things depending on the nature of the request. It can be used to signify that the requested resource has not changed since a previousGET
request. It can also be used to signify that a request to modify the resource did not result in the resource being changed.TheResponse
classesnotModified()
methods creates a response with a304
status and sets the modified date property on the HTTP message. There are three versions of thenotModified()
method:notModified();
notModified(javax.ws.rs.core.Entity tag);
notModified(java.lang.String tag);
307 Temporary Redirect
- The
307 Temporary Redirect
status is useful when the requested resource needs to direct the consumer to a new resource, but wants the consumer to continue using this resource to handle future requests.TheResponse
classestemporaryRedirect()
method creates a response with a307
status and places the new resource URI in the message'sLocation
field. ThetemporaryRedirect()
method takes a single parameter that specifies the new URI as ajava.net.URI
object.
304
status” shows an example of creating a response with an 304
status.
Example 47.5. Creating a response with a 304
status
import javax.ws.rs.core.Response; return Response.notModified().build();
Creating responses to signal errors
Response
class provides methods to create responses for two basic processing errors:
serverError();
—creates a response with a status of500 Internal Server Error
.notAcceptable(java.util.List<javax.ws.rs.core.Variant> variants);
—creates a response with a406 Not Acceptable
status and an entity body containing a list of acceptable resource types.
500
status” shows an example of creating a response with an 500
status.
Example 47.6. Creating a response with a 500
status
import javax.ws.rs.core.Response; return Response.serverError().build();
47.3.3. Handling more advanced responses
Overview
Response
class methods provide short cuts for creating responses for common cases. When you need to address more complicated cases such as specifying cache control directives, adding custom HTTP headers, or sending a status not handled by the Response
class, you need to use the ResponseBuilder
classes methods to populate the response before using the build()
method to generate the response object.
ResponseBuilderImpl
class to create a response builder instance that can be manipulated directly.
Adding custom headers
ResponseBuilder
class' header()
method. The header()
method takes two parameters:
name
—a string specifying the name of the headervalue
—a Java object containing the data stored in the header
header()
method repeatedly.
Example 47.7. Adding a header to a response
import javax.ws.rs.core.Response; import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl; ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.header("username", "joe"); Response r = builder.build();
Adding a cookie
ResponseBuilder
class' cookie()
method. The cookie()
method takes one or more cookies. Each cookie is stored in a javax.ws.rs.core.NewCookie
object. The easiest of the NewCookie
class' contructors to use takes two parameters:
name
—a string specifying the name of the cookievalue
—a string specifying the value of the cookie
cookie()
method repeatedly.
Example 47.8. Adding a cookie to a response
import javax.ws.rs.core.Response; import javax.ws.rs.core.NewCookie; NewCookie cookie = new NewCookie("username", "joe"); Response r = Response.ok().cookie(cookie).build();
cookie()
method with a null
parameter list erases any cookies already associated with the response.
Setting the response status
Response
class' helper methods, you can use the ResponseBuilder
class' status()
method to set the response's status code. The status()
method has two variants. One takes an int that specifies the response code. The other takes a Response.Status
object to specify the response code.
Response.Status
class is an enumeration enclosed in the Response
class. It has entries for most of the defined HTTP response codes.
404 Not Found
.
Example 47.9. Adding a header to a response
import javax.ws.rs.core.Response; import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl; ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.status(404); Response r = builder.build();
Setting cache control directives
ResponseBuilder
class' cacheControl()
method allows you to set the cache control headers on the response. The cacheControl()
method takes a javax.ws.rs.CacheControl
object that specifies the cache control directives for the response.
CacheControl
class has methods that correspond to all of the cache control directives supported by the HTTP specification. Where the directive is a simple on or off value the setter method takes a boolean value. Where the directive requires a numeric value, such as the max-age
directive, the setter takes an int value.
no-store
cache control directive.
Example 47.10. Adding a header to a response
import javax.ws.rs.core.Response; import javax.ws.rs.core.CacheControl; import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl; CacheControl cache = new CacheControl(); cache.setNoCache(true); ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.cacheControl(cache); Response r = builder.build();