Fuse ESB

Developing RESTful Web Services

Version 4.4.1

Sept. 2011
Trademark Disclaimer
Third Party Acknowledgements

Updated: 06 Jun 2013

Table of Contents

1. Introduction to RESTful Web Services
2. Creating Resources
Introduction
Basic JAX-RS annotations
Root resource classes
Working with resource methods
Working with sub-resources
Resource selection method
3. Passing Information into Resource Classes and Methods
Basics of injecting data
Using JAX-RS APIs
Injecting data from a request URI
Injecting data from the HTTP message header
Injecting data from HTML forms
Specifying a default value to inject
Using Fuse Services Framework extensions
4. Returning Information to the Consumer
Returning plain Java constructs
Fine tuning an application's responses
Basics of building responses
Creating responses for common use cases
Handling more advanced responses
Returning entities with generic type information
5. Handling Exceptions
Using WebApplicaitonException exceptions to report errors
Mapping exceptions to responses
6. Publishing a Service
7. Entity Support
8. Customizing the Media Types Handled by a Resource
9. Getting and Using Context Information
Introduction to contexts
Working with the full request URI
Injecting the URI information
Working with the URI
Getting the value of URI template variables
Getting the query parameters
Getting the matrix parameters
Working with the HTTP Headers
Working with security information
Working with preconditions
Working with servlet contexts
Working with the Apache CXF context object
Adding custom contexts
10. Annotation Inheritance
Index

List of Tables

7.1. Natively supported entity mappings
7.2. Parameters used to determine if a reader can produce an entity
7.3. Parameters used to read an entity
7.4. Parameters used to read an entity
7.5. Parameters used to read an entity
7.6. Parameters used to read an entity
9.1. Context types
9.2. Methods for accessing a resource's base URI
9.3. Methods for accessing a resource's path
9.4. Methods for accessing the full request URI

List of Examples

2.1. Simple resource class
2.2. URI template syntax
2.3. Root resource class
2.4. Resource method with a valid parameter list
2.5. Resource method with an invalid parameter list
2.6. Order sub-resource
2.7. Sub-resource methods
2.8. Sub-resource locator returning a specific class
2.9. Interface for customizing resource selection
3.1. Injecting data from a URI template variable
3.2. URI with a query string
3.3. Resource method using data from a query parameter
3.4. Resource method using data from matrix parameters
3.5. Disabling URI decoding
3.6. Injecting the If-Modified-Since header
3.7. Injecting a cookie
3.8. Injecting form data into resource method parameters
3.9. Syntax for setting the default value of a parameter
3.10. Setting default values
3.11. Injecting query parameters into a bean
4.1. Getting a response builder using the Response class
4.2. Getting a response builder using the ResponseBuilderImpl class
4.3. Creating a response with an 200 response
4.4. Creating a response with a 204 status
4.5. Creating a response with a 304 status
4.6. Creating a response with a 500 status
4.7. Adding a header to a response
4.8. Adding a cookie to a response
4.9. Adding a header to a response
4.10. Adding a header to a response
4.11. Creating a GenericEntity<T> object using a subclass
4.12. Directly instantiating a GenericEntity<T> object
5.1. Creating a WebApplicationException with a status code
5.2. Creating a WebApplicationException with a status code
5.3. Sending a message with an exception
5.4. Extending WebApplicationException
5.5. Exception mapper interface
5.6. Mapping an exception to a response
5.7. Registering exception mappers with the runtime
7.1. Message reader interface
7.2. XML source entity reader
7.3. Message writer interface
7.4. XML source entity writer
7.5. Registering entity providers with the runtime
7.6. Programmatically registering an entity provider
9.1. Injecting the URI context into a class field
9.2. Getting a resource's path
9.3. Methods for returning path parameters from the URI context
9.4. Extracting path parameters from the URI context
10.1. Annotation inheritance
10.2. Overriding annotation inheritance

Fuse Services Framework provides an implementation of the Java API for RESTFul Web Services(JAX-RS). JAX-RS provides a standardized way to map POJOs to resources using annotations.

When moving from the abstract service definition to a RESTful Web service implemented using JAX-RS, you need to do the following:

  1. Create a root resource class for the resource that represents the top of the service's resource tree.

    See Root resource classes.

  2. Map the service's other resources into sub-resources.

    See Working with sub-resources.

  3. Create methods to implement each of the HTTP verbs used by each of the resources.

    See Working with resource methods.

Note

Fuse Services Framework continues to support the old HTTP binding to map Java interfaces into RESTful Web services. The HTTP binding provides basic functionality and has a number of limitations. Developers are encouraged to update their applications to use JAX-RS.

The JAX-RS APIs allow you to create two basic types of resources:

  • A root resource class is the entry point to a service's resource tree. It is decorated with the @Path annotation to define the base URI for the resources in the service.

  • Sub-resources are accessed through the root resource. They are implemented by methods that are decorated with the @Path annotation. A sub-resource's @Path annotation defines a URI relative to the base URI of a root resource.

Example 2.1 shows a simple resource class.

Example 2.1. Simple resource class

package demo.jaxrs.server;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/customerservice") 1
public class CustomerService
{
  public CustomerService()
  {
  }

  @GET 2
  public Customer getCustomer(@QueryParam("id") String id)
  {
    ...
  }

  ...
}

Two items make the class defined in Example 2.1 a resource class:

1

The @Path annotation specifies the base URI for the resource.

2

The @GET annotation specifies that the method implements the HTTP GET method for the resource.

Example 2.3 shows a root resource class that provides access to a sub-resource.

Example 2.3. Root resource class

package demo.jaxrs.server;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/customerservice/") 1
public class CustomerService
{
  public CustomerService() 2
  {
    ...
  }

  @GET 3
  public Customer getCustomer(@QueryParam("id") String id)
  {
    ...
  }

  @DELETE
  public Response deleteCustomer(@QueryParam("id") String id)
  {
    ...
  }

  @PUT
  public Response updateCustomer(Customer customer)
  {
    ...
  }

  @POST
  public Response addCustomer(Customer customer)
  {
    ...
  }

  @Path("/orders/{orderId}/") 4
  public Order getOrder(@PathParam("orderId") String orderId)
  {
    ...
  }

}

The class in Example 2.3 meets all of the requirements for a root resource class.

1

The class is decorated with the @Path annotation. The root URI for the resources exposed by the service is customerservice.

2

The class has a public constructor. In this case the no argument constructor is used for simplicity.

3

The class implements each of the four HTTP verbs for the resource.

4

The class also provides access to a sub-resource through the getOrder() method. The URI for the sub-resource, as specified using the the @Path annotation, is customerservice/order/id. The sub-resource is implemented by the Order class.

For more information on implementing sub-resources see Working with sub-resources.

Resource methods can return one of the following:

All resource methods return an HTTP status code to the requester. When the return type of the method is void or the value being returned is null, the resource method sets the HTTP status code to 200. When the resource method returns any value other than null, it sets the HTTP status code to 204.

Sub-resource locators are not decorated with one of the HTTP verb annotations and do not directly handle are request on the sub-resource. Instead, a sub-resource locator returns an instance of a resource class that can handle the request.

In addition to not having an HTTP verb annotation, sub-resource locators also cannot have any entity parameters. All of the parameters used by a sub-resource locator method must use one of the annotations described in Passing Information into Resource Classes and Methods.

As shown in Example 2.8, sub-resource locator allows you to encapsulate a resource as a reusable class instead of putting all of the methods into one super class. The processOrder() method is a sub-resource locator. When a request is made on a URI matching the URI template /orders/{orderId}/ it returns an instance of the Order class. The Order class has methods that are decorated with HTTP verb annotations. A PUT request is handled by the updateOrder() method.


Sub-resource locators are processed at runtime so that they can support polymorphism. The return value of a sub-resource locator can be a generic Object, an abstract class, or the top of a class hierarchy. For example, if your service needed to process both PayPal orders and credit card orders, the processOrder() method's signature from Example 2.8 could remain unchanged. You would simply need to implement two classes, ppOrder and ccOder, that extended the Order class. The implementation of processOrder() would instantiate the desired implementation of the sub-resource based on what ever logic is required.

The first two stages of the selection algorithm determine the resource that will handle the request. In some cases the resource is implemented by a resource class. In other cases, it is implemented by one or more sub-resources that use the same URI template. When there are multiple resources that match a request URI, resource classes are preferred over sub-resources.

If more than one resource still matches the request URI after sorting between resource classes and sub-resources, the following criteria are used to select a single resource:

In many cases, selecting a resource that matches the request URI results in a single resource method that can process the request. The method is determined by matching the HTTP verb specified in the request with a resource method's HTTP verb annotation. In addition to having the appropriate HTTP verb annotation, the selected method must also be able to handle the request entity included in the request and be able to produce the proper type of response specified in the request's metadata.

When selecting a resource produces multiple methods that can handle a request the following criteria is used to select the resource method that will handle the request:

  1. Prefer resource methods over sub-resources.

  2. Prefer sub-resource methods over sub-resource locaters.

  3. Prefer methods that use the most specific values in the @Consumes annotation and the @Produces annotation.

    For example, a method that has the annotation @Consumes(text/xml) would be preferred over a method that has the annotation @Consumes(text/*). Both methods would be preferred over a method without an @Consumes annotation or the annotation @Consumes(*/*).

  4. Prefer methods that most closely match the content type of the request body entity.

    Tip

    The content type of the request body entity is specified in the HTTP Content-Type property.

  5. Prefer methods that most closely match the content type accepted as a response.

    Tip

    The content types accepted as a response are specified in the HTTP Accept property.

In some cases, developers have reported the algorithm being somewhat restrictive in the way multiple resource classes are selected. For example, if a given resource class has been matched and if this class has no matching resource method, then the algorithm stops executing. It never checks the remaining matching resource classes.

Apache CXF provides the org.apache.cxf.jaxrs.ext.ResourceComparator interface which can be used to customize how the runtime handles multiple matching resource classes. The ResourceComparator interface, shown in Example 2.9, has to methods that need to be implemented. One compares two resource classes and the other compares two resource methods.


Custom implementations select between the two resources as follows:

  • Return 1 if the first parameter is a better match than the second parameter

  • Return -1 if the second parameter is a better match than the first parameter

If 0 is returned then the runtime will proceed with the default selection algorithm

You register a custom ResourceComparator implementation by adding a resourceComparator child to the service's jaxrs:server element.

Parameters, fields, and bean properties that are initialized using data from the HTTP request message have their values injected into them by the runtime. The specific data that is injected is specified by a set of annotations described in Using JAX-RS APIs.

The JAX-RS specification places a few restrictions on when the data is injected. It also places a few restrictions on the types of objects into which request data can be injected.

The standard JAX-RS API specifies annotations that can be used to inject values into fields, bean properties, and method parameters. The annotations can be split up into three distinct types:

One of the more common mechanisms for getting information about a resource is through the variables used in creating the URI templates for a resource. This is accomplished using the javax.ws.rs.PathParam annotation. The @PathParam annotation has a single parameter that identifies the URI template variable from which the data will be injected.

In Example 3.1 the @PathParam annotation specifies that the value of the URI template variable color is injected into the itemColor field.


The data types supported by the @PathParam annotation are different from the ones described in Supported data types. The entity into which the @PathParam annotation injects data must be of one of the following types:

  • PathSegment

    The value will be the final segment of the matching part of the path.

  • List<PathSegment>

    The value will be a list of PathSegment objects corresponding to the path segment(s) that matched the named template parameter.

  • primitives such as int, char, or long

  • Objects that have a constructor that accepts a single String argument

  • Objects that have a static valueOf() method that accepts a single String argument

A common way of passing information on the Web is to use query parameters in a URI. Query parameters appear at the end of the URI and are separated from the resource location portion of the URI by a question mark(?). They consist of one, or more, name value pairs where the name and value are separated by an equal sign(=). When more than one query parameter is specified, the pairs are separated from each other by either a semicolon(;) or an ampersand(&). Example 3.2 shows the syntax of a URI with query parameters.


Note

You can use either the semicolon or the ampersand to separate query parameters, but not both.

The javax.ws.rs.QueryParam annotation extracts the value of a query parameter and injects it into a JAX-RS resource. The annotation takes a single parameter that identifies the name of the query parameter from which the value is extracted and injected into the specified field, bean property, or parameter. The @QueryParam annotation supports the types described in Supported data types.

Example 3.3 shows a resource method that injects the value of the query parameter id into the method's id parameter.


To process an HTTP POST to /monstersforhire/daikaiju?id=jonas the updateMonster() method's type is set to daikaiju and the id is set to jonas.

URI matrix parameters, like URI query parameters, are name/value pairs that can provide additional information selecting a resource. Unlike query parameters, matrix parameters can appear anywhere in a URI and they are separated from the hierarchical path segments of the URI using a semicolon(;). /mostersforhire/daikaiju;id=jonas has one matrix parameter called id and /monstersforhire/japan;type=daikaiju/flying;wingspan=40 has two matrix parameters called type and wingspan.

Note

Matrix parameters are not evaluated when computing a resource's URI. So, the URI used to locate the proper resource to handle the request URI /monstersforhire/japan;type=daikaiju/flying;wingspan=40 is /monstersforhire/japan/flying.

The value of a matrix parameter is injected into a field, parameter, or bean property using the javax.ws.rs.MatrixParam annotation. The annotation takes a single parameter that identifies the name of the matrix parameter from which the value is extracted and injected into the specified field, bean property, or parameter. The @MatrixParam annotation supports the types described in Supported data types.

Example 3.4 shows a resource method that injects the value of the matrix parameters type and id into the method's parameters.


To process an HTTP POST to /monstersforhire;type=daikaiju;id=whale the updateMonster() method's type is set to daikaiju and the id is set to whale.

Note

JAX-RS evaluates all of the matrix parameters in a URI at once, so it cannot enforce constraints on a matrix parameters location in a URI. For example /monstersforhire/japan;type=daikaiju/flying;wingspan=40 , /monstersforhire/japan/flying;type=daikaiju;wingspan=40, and /monstersforhire/japan;type=daikaiju;wingspan=40/flying are all treated as equivalent by a RESTful Web service implemented using the JAX-RS APIs.

HTML forms are an easy means of getting information from a user and they are also easy to create. Form data can be used for HTTP GET requests and HTTP POST requests:

GET

When form data is sent as part of an HTTP GET request the data is appended to the URI as a set of query parameters. Injecting data from query parameters is discussed in Using query parameters.

POST

When form data is sent as part of an HTTP POST request the data is placed in the HTTP message body. The form data can be handled using a regular entity parameter that supports the form data. It can also be handled by using the @FormParam annotation to extract the data and inject the pieces into resource method parameters.

Example 3.10 shows two examples of using the @DefaultValue to specify a default value for a field whose value is injected.


The getMonster() method in Example 3.10 is invoked when a GET request is sent to baseURI/monster. The method expects two query parameters, id and type, appended to the URI. So a GET request using the URI baseURI/monster?id=1&type=fomóiri would return the Fomóiri with the id of one.

Because the @DefaultValue annotation is placed on both parameters, the getMonster() method can function if the query parameters are omitted. A GET request sent to baseURI/monster is equivalent to a GET request using the URI baseURI/monster?id=42&type=bogeyman.

The information returned to the consumer determines the exact type of object a resource method returns. This may seem obvious, but the mapping between Java return objects and what is returned to a RESTful consumer is not one-to-one. At a minimum, RESTful consumers need to be returned a valid HTTP return code in addition to any response entity body. The mapping of the data contained within a Java object to a response entity is effected by the MIME types a consumer is willing to accept.

To address the issues involved in mapping Java object to RESTful response messages, resource methods are allowed to return four types of Java constructs:

  • common Java types return basic information with HTTP return codes determined by the JAX-RS runtime.

  • JAXB objects return complex information with HTTP return codes determined by the JAX-RS runtime.

  • JAX-RS Response objects return complex information with a programmatically determined HTTP return status. The Response object also allows HTTP headers to be specified.

  • JAX-RS GenericEntity objects return complex information with HTTP return codes determined by the JAX-RS runtime. The GenericEnitity object provides more information to the runtime components serializing the data.

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.

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 4.3 shows an example of creating a response with an OK status.


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 4.4 shows an example of creating a response with an 204 status.


The Response class provides methods for handling three of the redirection response statuses.

Example 4.5 shows an example of creating a response with an 304 status.


Exception mappers are created by implementing the javax.ws.rs.ext.ExceptionMapper<E> interface. As shown in Example 5.5, the interface has a single method, toResponse(), that takes the original exception as a parameter and returns a Response object.


The Response object created by the exception mapper is processed by the runtime just like any other Response object. The resulting response to the consumer will contain the status, headers, and entity body encapsulated in the Response object.

Exception mapper implementations are considered providers by the runtime. Therefor they must be decorated with the @Provder annotation.

If an exception occurs while the exception mapper is building the Response object, the runtime will a response with a status of 500 Server Error to the consumer.

Example 5.6 shows an exception mapper that intercepts Spring AccessDeniedException exceptions and generates a response with a 403 Forbidden status and an empty entity body.


The runtime will catch any AccessDeniedException exceptions and create a Response object with no entity body and a status of 403. The runtime will then process the Response object as it would for a normal response. The result is that the consumer will receive an HTTP response with a status of 403.

Custom entity readers are responsible for mapping incoming HTTP requests into a Java type that a service's implementation can manipulate. They implement the javax.ws.rs.ext.MessageBodyReader interface.

The interface, shown in Example 7.1, has two methods that need implementing:


isReadable()

The isReadable() method determines if the reader is capable of reading the data stream and creating the proper type of entity representation. If the reader can create the proper type of entity the method returns true.

Table 7.2 describes the isReadable() method's parameters.


readFrom()

The readFrom() method reads the HTTP entity and coverts it into the desired Java object. If the reading is successful the method returns the created Java object containing the entity. If an error occurs when reading the input stream the method should throw an IOException exception. If an error occurs that requires an HTTP error response, an WebApplicationException with the HTTP response should be thrown.

Table 7.3 describes the readFrom() method's parameters.


Important

This method should not close the input stream.

Before an MessageBodyReader implementation can be used as an entity reader, it must be decorated with the javax.ws.rs.ext.Provider annotation. The @Provider annotation alerts the runtime that the supplied implementation provides additional functionality. The implementation must also be registered with the runtime as described in Registering readers and writers.

By default a custom entity provider handles all MIME types. You can limit the MIME types that a custom entity reader will handle using the javax.ws.rs.Consumes annotation. The @Consumes annotation specifies a comma separated list of MIME types that the custom entity provider reads. If an entity is not of a specified MIME type, the entity provider will not be selected as a possible reader.

Example 7.2 shows an entity reader the consumes XML entities and stores them in a Source object.

Example 7.2. XML source entity reader

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.apache.cxf.jaxrs.ext.xml.XMLSource;

@Provider
@Consumes({"application/xml", "application/*+xml", "text/xml", "text/html" })
public class SourceProvider implements MessageBodyReader<Object>
{
  public boolean isReadable(Class<?> type,
                            Type genericType,
                            Annotation[] annotations,
                            MediaType mt)
  {
    return Source.class.isAssignableFrom(type) || XMLSource.class.isAssignableFrom(type);
  }

  public Object readFrom(Class<Object> source,
                         Type genericType,
                         Annotation[] annotations,
                         MediaType mediaType, 
                         MultivaluedMap<String, String> httpHeaders,
                         InputStream is)
  throws IOException
  {
    if (DOMSource.class.isAssignableFrom(source))
    {
      Document doc = null;
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder;
      try
      {
        builder = factory.newDocumentBuilder();
        doc = builder.parse(is);
      }
      catch (Exception e)
      {
        IOException ioex = new IOException("Problem creating a Source object");
        ioex.setStackTrace(e.getStackTrace());
        throw ioex;
       }

       return new DOMSource(doc);
    }
    else if (StreamSource.class.isAssignableFrom(source) || Source.class.isAssignableFrom(source))
    {
      return new StreamSource(is);
    }
    else if (XMLSource.class.isAssignableFrom(source))
    {
      return new XMLSource(is);
    }

    throw new IOException("Unrecognized source");
  }
}

Custom entity writers are responsible for mapping Java types into HTTP entities. They implement the javax.ws.rs.ext.MessageBodyWriter interface.

The interface, shown in Example 7.3, has three methods that need implementing:


isWriteable()

The isWriteable() method determines if the entity writer can map the Java type to the proper entity type. If the writer can do the mapping, the method returns true.

Table 7.4 describes the isWritable() method's parameters.


getSize()

The getSize() method is called before the writeTo(). It returns the length, in bytes, of the entity being written. If a positive value is returned the value is written into the HTTP message's Content-Length header.

Table 7.5 describes the getSize() method's parameters.


writeTo()

The writeTo() method converts a Java object into the desired entity type and writes the entity to the output stream. If an error occurs when writing the entity to the output stream the method should throw an IOException exception. If an error occurs that requires an HTTP error response, an WebApplicationException with the HTTP response should be thrown.

Table 7.6 describes the writeTo() method's parameters.


Before a MessageBodyWriter implementation can be used as an entity writer, it must be decorated with the javax.ws.rs.ext.Provider annotation. The @Provider annotation alerts the runtime that the supplied implementation provides additional functionality. The implementation must also be registered with the runtime as described in Registering readers and writers.

By default a custom entity provider handles all MIME types. You can limit the MIME types that a custom entity writer will handle using the javax.ws.rs.Produces annotation. The @Produces annotation specifies a comma separated list of MIME types that the custom entity provider generates. If an entity is not of a specified MIME type, the entity provider will not be selected as a possible writer.

Example 7.4 shows an entity writer that takes Source objects and produces XML entities.

Example 7.4. XML source entity writer

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.apache.cxf.jaxrs.ext.xml.XMLSource;

@Provider
@Produces({"application/xml", "application/*+xml", "text/xml" })
public class SourceProvider implements MessageBodyWriter<Source>
{

  public boolean isWriteable(Class<?> type,
                             Type genericType,
                             Annotation[] annotations,
                             MediaType mt)
  {
    return Source.class.isAssignableFrom(type);
  }

  public void writeTo(Source source,
                      Class<?> clazz,
                      Type genericType,
                      Annotation[] annotations,
                      MediaType mediatype,
                      MultivaluedMap<String, Object> httpHeaders,
                      OutputStream os)
  throws IOException
  {
    StreamResult result = new StreamResult(os);
    TransformerFactory tf = TransformerFactory.newInstance();
    try
    {
      Transformer t = tf.newTransformer();
      t.transform(source, result);
    }
    catch (TransformerException te)
    {
      te.printStackTrace();
      throw new WebApplicationException(te);
    }
  }

  public long getSize(Source source,
                      Class<?> type, 
                      Type genericType, 
                      Annotation[] annotations,
                      MediaType mt)
  {
    return -1;
  }
}

The request URI contains a significant amount of information. Most of this information can be accessed using method parameters as described in Injecting data from a request URI, however using parameters forces certain constraints on how the URI is processed. Using parameters to access the segments of a URI also does not provide a resource access to the full request URI.

You can provide access to the complete request URI by injecting the URI context into a resource. The URI is provided as a UriInfo object. The UriInfo interface provides functions for decomposing the URI in a number of ways. It can also provide the URI as a UriBuilder object that allows you to construct URIs to return to clients.

The path portion of the request URI is the portion of the URI that was used to select the current resource. It does not include the base URI, but does include any URI template variable and matrix parameters included in the URI.

The value of the path depends on the resource selected. For example, the paths for the resources defined in Example 9.2 would be:

  • rootPath/monstersforhire/

  • getterPath/mostersforhire/nightstalker

    The GET request was made on /monstersforhire/nightstalker.

  • putterPath/mostersforhire/911

    The PUT request was made on /monstersforhire/911.


Table 9.3 describes the methods that return the resource path.


As described in Setting the path, resource paths can contain variable segments that are bound to values dynamically. Often these variable path segments are used as parameters to a resource method as described in Getting data from the URI's path. You can, however, also access them through the URI context.

A

annotations
@Consumes (see @Consumes)
@Context (see @Context)
@CookieParam (see @CookieParam)
@DefaultValue (see @DefaultValue)
@DELETE (see @DELETE)
@Encoded (see @Encoded)
@FormParam (see @FormParam)
@GET (see @GET)
@HEAD (see @HEAD)
@HeaderParam (see @HeaderParam)
@MatrixParam (see @MatrixParam)
@Path (see @Path)
@PathParam (see @PathParam)
@POST (see @POST)
@Produces (see @Produces)
@Provider (see @Provider)
@PUT (see @PUT)
@QueryParam (see @QueryParam)
inheritance, Annotation Inheritance

E

entity parameter, Parameters
ExceptionMapper<E>, Implementing an exception mapper

M

matrix parameters, Using matrix parameters, Getting the matrix parameters
MessageBodyReader, Custom readers
MessageBodyWriter, Custom writers

P

parameter constraints, Parameters
PathSegment, Getting the path