45.3. Fine tuning an application's responses

45.3.1. Basics of building responses

Overview

RESTful services often need more precise control over the response returned to a consumer than is allowed when a resource method returns a plain Java construct. The JAX-RS 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.
The 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

The 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.
The 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.
The 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

There are two ways to get a response builder:
  • Using the static methods of the Response class as shown in Example 45.1, “Getting a response builder using the Response class”.

    Example 45.1. Getting a response builder using the Response class

    import 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 45.2. Getting a response builder using the ResponseBuilderImpl class

    import javax.ws.rs.core.Response;
    import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl;
    
    ResponseBuilderImpl builder = new ResponseBuilderImpl();
    builder.status(200);
    Response r = builder.build();
    Note
    You could also simply assign the ResponseBuilder returned from a Response class' method to a ResponseBuilderImpl object.

More information

For more information about the Response class see the Response class' Javadoc.
For more information about the ResponseBuilder class see the ResponseBuilder class' Javadoc.
For more information on the Apache CXF ResponseBuilderIml class see the ResponseBuilderImpl Javadoc.

45.3.2. Creating responses for common use cases

Overview

The 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

When a request is successfully processed the application needs to send a response to acknowledge that the request has been fulfilled. That response may contain an entity.
The most common response when successfully completing a response is 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 of 200 and an empty entity body.
  • Response.ok(java.lang.Object entity)—creates a response with a status of 200, stores the supplied object in the responses entity body, and determines the entities media type by introspecting the object.
Example 45.3, “Creating a response with an 200 response” shows an example of creating a response with an OK status.

Example 45.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();
For cases where the requester is not expecting an entity body, it may be more appropriate to send a 204 No Content status instead of an 200 OK status. The Response.noContent() method will create an appropriate response object.
Example 45.4, “Creating a response with a 204 status” shows an example of creating a response with an 204 status.

Example 45.4. Creating a response with a 204 status

import javax.ws.rs.core.Response;

return Response.noContent().build();

Creating responses for redirection

The 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.
The Response classes seeOther() method creates a response with a 303 status and places the new resource URI in the message's Location field. The seeOther() method takes a single parameter that specifies the new URI as a java.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 previous GET request. It can also be used to signify that a request to modify the resource did not result in the resource being changed.
The Response classes notModified() methods creates a response with a 304 status and sets the modified date property on the HTTP message. There are three versions of the notModified() 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.
The Response classes temporaryRedirect() method creates a response with a 307 status and places the new resource URI in the message's Location field. The temporaryRedirect() method takes a single parameter that specifies the new URI as a java.net.URI object.
Example 45.5, “Creating a response with a 304 status” shows an example of creating a response with an 304 status.

Example 45.5. Creating a response with a 304 status

import javax.ws.rs.core.Response;

return Response.notModified().build();

Creating responses to signal errors

The Response class provides methods to create responses for two basic processing errors:
  • serverError();—creates a response with a status of 500 Internal Server Error.
  • notAcceptable(java.util.List<javax.ws.rs.core.Variant> variants);—creates a response with a 406 Not Acceptable status and an entity body containing a list of acceptable resource types.
Example 45.6, “Creating a response with a 500 status” shows an example of creating a response with an 500 status.

Example 45.6. Creating a response with a 500 status

import javax.ws.rs.core.Response;

return Response.serverError().build();

45.3.3. Handling more advanced responses

Overview

The 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.
Tip
As discussed in the section called “Getting a response builder”, you can use the Apache CXF ResponseBuilderImpl class to create a response builder instance that can be manipulated directly.

Adding custom headers

Custom headers are added to a response using the ResponseBuilder class' header() method. The header() method takes two parameters:
  • name—a string specifying the name of the header
  • value—a Java object containing the data stored in the header
You can set multiple headers on the message by calling the header() method repeatedly.
Example 45.7, “Adding a header to a response” shows code for adding a header to a response.

Example 45.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

Custom headers are added to a response using the 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 cookie
  • value—a string specifying the value of the cookie
You can set multiple cookies by calling the cookie() method repeatedly.
Example 45.8, “Adding a cookie to a response” shows code for adding a cookie to a response.

Example 45.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();
Warning
Calling the cookie() method with a null parameter list erases any cookies already associated with the response.

Setting the response status

When you want to return a status other than one of the statuses supported by the 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.
The Response.Status class is an enumeration enclosed in the Response class. It has entries for most of the defined HTTP response codes.
Example 45.9, “Adding a header to a response” shows code for setting the response status to 404 Not Found.

Example 45.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

The 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.
The 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.
Example 45.10, “Adding a header to a response” shows code for setting the no-store cache control directive.

Example 45.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();