-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for Red Hat Fuse
Developing RESTful Web Services
Standards based RESTful service development
Red Hat
Copyright © 2013 Red Hat, Inc. and/or its affiliates.
Abstract
Chapter 1. Introduction to RESTful Web Services
Abstract
Overview
Basic REST principles
- Application state and functionality are divided into resources.
- Resources are addressable using standard URIs that can be used as hypermedia links.
- All resources use only the four HTTP verbs.
DELETE
GET
POST
PUT
- All resources provide information using the MIME types supported by HTTP.
- The protocol is stateless.
- Responses are cacheable.
- The protocol is layered.
Resources
REST best practices
- Provide a distinct URI for each resource you wish to expose.For example, if you are building a system that deals with driving records, each record should have a unique URI. If the system also provides information on parking violations and speeding fines, each type of resource should also have a unique base. For example, speeding fines could be accessed through /speedingfines/driverID and parking violations could be accessed through /parkingfines/driverID.
- Use nouns in your URIs.Using nouns highlights the fact that resources are things and not actions. URIs such as /ordering imply an action, whereas /orders implies a thing.
- Methods that map to
GET
should not change any data. - Use links in your responses.Putting links to other resources in your responses makes it easier for clients to follow a chain of data. For example, if your service returns a collection of resources, it would be easier for a client to access each of the individual resources using the provided links. If links are not included, a client needs to have additional logic to follow the chain to a specific node.
- Make your service stateless.Requiring the client or the service to maintain state information forces a tight coupling between the two. Tight couplings make upgrading and migrating more difficult. Maintaining state can also make recovery from communication errors more difficult.
Designing a RESTful Web Service
- Define the resources the service will expose.In general, a service will expose one or more resources that are organized as a tree. For example, a driving record service could be organized into three resources:
- /license/driverID
- /license/driverID/speedingfines
- /license/driverID/parkingfines
- Define what actions you want to be able to perform on each resource.For example, you may want to be able to update a diver's address or remove a parking ticket from a driver's record.
- Map the actions to the appropriate HTTP verbs.
Implementing REST with Apache CXF
- Create a root resource class for the resource that represents the top of the service's resource tree.
- Map the service's other resources into sub-resources.
- Create methods to implement each of the HTTP verbs used by each of the resources.
Data bindings
Chapter 2. Creating Resources
Abstract
2.1. Introduction
Overview
Types of resources
- A Section 2.3, “Root resource classes” 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. - Section 2.5, “Working with 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
Example 2.1. Simple resource class
2.2. Basic JAX-RS annotations
Overview
- the URI of the service's resources
- how the class' methods are mapped to the HTTP verbs
Setting the path
@Path
annotation specifies the URI of a resource. The annotation is defined by the javax.ws.rs.Path
interface and it can be used to decorate either a resource class or a resource method. It takes a string value as its only parameter. The string value is a URI template that specifies the location of an implemented resource.
- unprocessed path components
- parameter identifiers surrounded by
{
}
NoteParameter identifiers can include regular expressions to alter the default path processing.
Example 2.2. URI template syntax
@Path("resourceName/{param1}/../{paramN}")
color
parameter is assigned to blue. The value of the number
parameter is assigned 12.
@Path
annotation is decorating. If it is placed on a root resource class, the URI template is the root URI of all resources in the tree and it is appended directly to the URI at which the service is published. If the annotation decorates a sub-resource, it is relative to the root resource URI.
Specifying HTTP verbs
javax.ws.rs.DELETE
specifies that the method maps to aDELETE
.javax.ws.rs.GET
specifies that the method maps to aGET
.javax.ws.rs.POST
specifies that the method maps to aPOST
.javax.ws.rs.PUT
specifies that the method maps to aPUT
.javax.ws.rs.HEAD
specifies that the method maps to aHEAD
.
PUT
or a POST
. Mapping it to a GET
or a DELETE
would result in unpredictable behavior.
2.3. Root resource classes
Overview
@Path
that specifies the root URI of the resources implemented by the service. Its methods either directly implement operations on the resource or provide access to sub-resources.
Requirements
- The class must be decorated with the
@Path
annotation.The specified path is the root URI for all of the resources implemented by the service. If the root resource class specifies that its path is widgets and one of its methods implements theGET
verb, then aGET
on widgets invokes that method. If a sub-resource specifies that its URI is {id}, then the full URI template for the sub-resource is widgets/{id} and it will handle requests made to URIs like widgets/12 and widgets/42. - The class must have a public constructor for the runtime to invoke.The runtime must be able to provide values for all of the constructor's parameters. The constructor's parameters can include parameters decorated with the JAX-RS parameter annotations. For more information on the parameter annotations see Chapter 3, Passing Information into Resource Classes and Methods.
- At least one of the classes methods must either be decorated with an HTTP verb annotation or the
@Path
annotation.
Example
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) { ... } }
- 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 theOrder
class.For more information on implementing sub-resources see Section 2.5, “Working with sub-resources”.
2.4. Working with resource methods
Overview
General constraints
- It must be public.
- It must be decorated with one of the HTTP method annotations described in the section called “Specifying HTTP verbs”.
- It must not have more than one entity parameter as described in the section called “Parameters”.
Parameters
- entity parameters—Entity parameters are not annotated. Their value is mapped from the request entity body. An entity parameter can be of any type for which your application has an entity provider. Typically they are JAXB objects.ImportantA resource method can have only one entity parameter.For more information on entity providers see Chapter 7, Entity Support.
- annotated parameters—Annotated parameters use one of the JAX-RS annotations that specify how the value of the parameter is mapped from the request. Typically, the value of the parameter is mapped from portions of the request URI.For more information about using the JAX-RS annotations for mapping request data to method parameters see Chapter 3, Passing Information into Resource Classes and Methods.
Example 2.4. Resource method with a valid parameter list
@POST @Path("disaster/monster/giant/{id}") public void addDaikaiju(Kaiju kaiju, @PathParam("id") String id) { ... }
Example 2.5. Resource method with an invalid parameter list
@POST @Path("disaster/monster/giant/") public void addDaikaiju(Kaiju kaiju, String id) { ... }
Return values
void
- any Java class for which the application has an entity providerFor more information on entity providers see Chapter 7, Entity Support.
- a
Response
objectFor more information onResponse
objects see Section 4.2, “Fine tuning an application's responses”. - a
GenericEntity<T>
objectFor more information onGenericEntity<T>
objects see Section 4.3, “Returning entities with generic type information”.
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
.
2.5. Working with sub-resources
Overview
@Path
annotation to a resource class' method. Sub-resources can be implemented in one of two ways:
- Sub-resource method—directly implements an HTTP verb for a sub-resource and is decorated with one of the annotations described in the section called “Specifying HTTP verbs”.
- Sub-resource locator—points to a class that implements the sub-resource.
Specifying a sub-resource
@Path
annotation. The URI of the sub-resource is constructed as follows:
- Append the value of the sub-resource's
@Path
annotation to the value of the sub-resource's parent resource's@Path
annotation.The parent resource's@Path
annotation maybe located on a method in a resource class that returns an object of the class containing the sub-resource. - Repeat the previous step until the root resource is reached.
- The assembled URI is appended to the base URI at which the service is deployed.
Example 2.6. Order sub-resource
... @Path("/customerservice/") public class CustomerService { ... @Path("/orders/{orderId}/") @GET public Order getOrder(@PathParam("orderId") String orderId) { ... } }
Sub-resource methods
@Path
annotation and one of the HTTP verb annotations. The sub-resource method is directly responsible for handling a request made on the resource using the specified HTTP verb.
getOrder()
handles HTTPGET
requests for resources whose URI matches /customerservice/orders/{orderId}/.updateOrder()
handles HTTPPUT
requests for resources whose URI matches /customerservice/orders/{orderId}/.newOrder()
handles HTTPPOST
requests for the resource at /customerservice/orders/.
Example 2.7. Sub-resource methods
... @Path("/customerservice/") public class CustomerService { ... @Path("/orders/{orderId}/") @GET public Order getOrder(@PathParam("orderId") String orderId) { ... } @Path("/orders/{orderId}/") @PUT public Order updateOrder(@PathParam("orderId") String orderId, Order order) { ... } @Path("/orders/") @POST public Order newOrder(Order order) { ... } }
Sub-resource locators
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.
Example 2.8. Sub-resource locator returning a specific class
... @Path("/customerservice/") public class CustomerService { ... @Path("/orders/{orderId}/") public Order processOrder(@PathParam("orderId") String orderId) { ... } ... } public class Order { ... @GET public Order getOrder(@PathParam("orderId") String orderId) { ... } @PUT public Order updateOrder(@PathParam("orderId") String orderId, Order order) { ... } }
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, “Sub-resource locator returning a specific class” 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.
2.6. Resource selection method
Overview
@Path("customerservice/{id}")
or @Path("customerservice/{id}/{state}")
. JAX-RS specifies a detailed algorithm for matching a resource method to a request. The algorithm compares the normalized URI, the HTTP verb, and the media types of the request and response entities to the annotations on the resource classes.
The basic selection algorithm
- Determine the root resource class.The request URI is matched against all of the classes decorated with the
@Path
annotation. The classes whose@Path
annotation matches the request URI are determined.If the value of the resource class'@Path
annotation matches the entire request URI, the class' methods are used as input into the third stage. - Determine the object will handle the request.If the request URI is longer than the value of the selected class'
@Path
annotation, the values of the resource methods'@Path
annotations are used to look for a sub-resource that can process the request.If one or more sub-resource methods match the request URI, these methods are used as input for the third stage.If the only matches for the request URI are sub-resource locaters, the resource methods of the object created by the sub-resource locater to match the request URI. This stage is repeated until a sub-resource method matches the request URI. - Select the resource method that will handle the request.The resource method whose HTTP verb annotation matches the HTTP verb in the request. In addition, the selected resource method must accept the media type of the request entity body and be capable of producing a response that conforms to the media type(s) specified in the request.
Selecting from multiple resource classes
- Prefer the resource with the most literal characters in its URI template.Literal characters are characters that are not part of a template variable. For example, /widgets/{id}/{color} has ten literal characters and /widgets/1/{color} has eleven literal characters. So, the request URI /widgets/1/red would be matched to the resource with /widgets/1/{color} as its URI template.NoteA trailing slash (
/
) counts as a literal character. So /joefred/ will be preferred over /joefred. - Prefer the resource with the most variables in its URI template.The request URI /widgets/30/green could match both /widgets/{id}/{color} and /widgets/{amount}/. However, the resource with the URI template /widgets/{id}/{color} will be selected because it has two variables.
- Prefer the resource with the most variables containing regular expressions.The request URI /widgets/30/green could match both /widgets/{number}/{color} and /widgets/{id:.+}/{color}. However, the resource with the URI template /widgets/{id:.+}/{color} will be selected because it has a variable containing a regular expression.
Selecting from multiple resource methods
@Consumes
annotation. The type of responses a resource method can produce are specified using the @Produces
annotation. For more information see Chapter 8, Customizing the Media Types Handled by a Resource.
- Prefer resource methods over sub-resources.
- Prefer sub-resource methods over sub-resource locaters.
- 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(*/*)
. - Prefer methods that most closely match the content type of the request body entity.TipThe content type of the request body entity is specified in the HTTP Content-Type property.
- Prefer methods that most closely match the content type accepted as a response.TipThe content types accepted as a response are specified in the HTTP Accept property.
Customizing the selection process
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, “Interface for customizing resource selection”, has to methods that need to be implemented. One compares two resource classes and the other compares two resource methods.
Example 2.9. Interface for customizing resource selection
package org.apache.cxf.jaxrs.ext; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.jaxrs.model.OperationResourceInfo; import org.apache.cxf.message.Message; public interface ResourceComparator { int compare(ClassResourceInfo cri1, ClassResourceInfo cri2, Message message); int compare(OperationResourceInfo oper1, OperationResourceInfo oper2, Message message); }
- 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
0
is returned then the runtime will proceed with the default selection algorithm
ResourceComparator
implementation by adding a resourceComparator
child to the service's jaxrs:server
element.
Chapter 3. Passing Information into Resource Classes and Methods
Abstract
3.1. Basics of injecting data
Overview
When data is injected
@Path
annotation or an object returned from a sub-resource locator method.
Supported data types
- 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 List<T>
,Set<T>
, orSortedSet<T>
objects where T satisfies the other conditions in the list
3.2. Using JAX-RS APIs
3.2.1. Injecting data from a request URI
Overview
Getting data from the URI's path
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.
@PathParam
annotation specifies that the value of the URI template variable color
is injected into the itemColor
field.
Example 3.1. Injecting data from a URI template variable
import javax.ws.rs.Path; import javax.ws.rs.PathParam ... @Path("/boxes/{shape}/{color}") class Box { ... @PathParam("color") String itemColor; ... }
@PathParam
annotation are different from the ones described in the section called “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 ofPathSegment
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
Using query parameters
?
). 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, “URI with a query string” shows the syntax of a URI with query parameters.
Example 3.2. URI with a query string
http://fusesource.org?name=value;name2=value2;...
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 the section called “Supported data types”.
id
into the method's id
parameter.
Example 3.3. Resource method using data from a query parameter
import javax.ws.rs.QueryParam; import javax.ws.rs.PathParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST @Path("\{type}") public void updateMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
POST
to /monstersforhire/daikaiju?id=jonas the updateMonster()
method's type
is set to daikaiju
and the id
is set to jonas
.
Using matrix parameters
;
). /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
.
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 the section called “Supported data types”.
type
and id
into the method's parameters.
Example 3.4. Resource method using data from matrix parameters
import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST public void updateMonster(@MatrixParam("type") String type, @MatrixParam("id") String id) { ... } ... }
POST
to /monstersforhire;type=daikaiju;id=whale the updateMonster()
method's type
is set to daikaiju
and the id
is set to whale
.
Disabling URI decoding
javax.ws.rs.Encoded
annotation to deactivate the URI decoding. The annotation can be used to deactivate URI decoding at the following levels:
- class level—Decorating a class with the
@Encoded
annotation deactivates the URI decoding for all parameters, field, and bean properties in the class. - method level—Decorating a method with the
@Encoded
annotation deactivates the URI decoding for all parameters of the class. - parameter/field level—Decorating a parameter or field with the
@Encoded
annotation deactivates the URI decoding for all parameters of the class.
getMonster()
method does not use URI decoding. The addMonster()
method only disables URI decoding for the type
parameter.
Example 3.5. Disabling URI decoding
@Path("/monstersforhire/") public class MonsterService { ... @GET @Encoded @Path("\{type}") public Monster getMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } @PUT @Path("\{id}") public void addMonster(@Encoded @PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
Error handling
WebApplicationException
exception wraps the original exception is generated. The WebApplicationException
exception's status is set to 404
.
3.2.2. Injecting data from the HTTP message header
Overview
Injecting information from the HTTP headers
javax.ws.rs.HeaderParam
annotation is used to inject the data from an HTTP header field into a parameter, field, or bean property. It has a single parameter that specifies the name of the HTTP header field from which the value is extracted and injected into the resource implementation. The associated parameter, field, or bean property must conform to the data types described in the section called “Supported data types”.
If-Modified-Since
header into a class' oldestDate
field.
Example 3.6. Injecting the If-Modified-Since header
import javax.ws.rs.HeaderParam; ... class RecordKeeper { ... @HeaderParam("If-Modified-Since") String oldestDate; ... }
Injecting information from a cookie
javax.ws.rs.CookieParam
annotation extracts the value from a cookie's field and injects it into a resource implementation. It takes a single parameter that specifies the name of the cookie's field from which the value is to be extracted. In addition to the data types listed in the section called “Supported data types”, entities decorated with the @CookieParam
can also be a Cookie
object.
handle
cookie into a field in the CB
class.
Example 3.7. Injecting a cookie
import javax.ws.rs.CookieParam; ... class CB { ... @CookieParam("handle") String handle; ... }
Error handling
WebApplicationException
exception wrapping the original exception is generated. The WebApplicationException
exception's status is set to 400
.
3.2.3. Injecting data from HTML forms
Overview
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 the section called “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.
Using the @FormParam
annotation to inject form data
javax.ws.rs.FormParam
annotation extracts field values from form data and injects the value into resource method parameters. The annotation takes a single parameter that specifies the key of the field from which it extracts the values. The associated parameter must conform to the data types described in the section called “Supported data types”.
@FormParam
annotation can be placed on fields, methods, and parameters. However, the @FormParam
annotation is only meaningful when placed on resource method parameters.
Example
title
, tags
, and body
—that contain string data.
Example 3.8. Injecting form data into resource method parameters
import javax.ws.rs.FormParam; import javax.ws.rs.POST; ... @POST public boolean updatePost(@FormParam("title") String title, @FormParam("tags") String tags, @FormParam("body") String post) { ... }
3.2.4. Specifying a default value to inject
Overview
javax.ws.rs.DefaultValue
annotation can be used in conjunction with the following injection annotations:
@PathParam
@QueryParam
@MatrixParam
@FormParam
@HeaderParam
@CookieParam
@DefaultValue
annotation specifies a default value to be used when the data corresponding to the injection annotation is not present in the request.
Syntax
@DefaultValue
annotation.
Example 3.9. Syntax for setting the default value of a parameter
import javax.ws.rs.DefaultValue; ... void resourceMethod(@MatrixParam("matrix") @DefaultValue("value) int someValue, ... ) ...
@DefaultValue
annotation relative to the accompanying injection annotation does not matter.
@DefaultValue
annotation takes a single parameter. This parameter is the value that will be injected into the field if the proper data cannot be extracted based on the injection annotation. The value can be any String value. The value should be compatible with type of the associated field. For example, if the associated field is of type int, a default value of blue
results in an exception.
Dealing with lists and sets
List
, Set
, or SortedSet
then the resulting collection will have a single entry mapped from the supplied default value.
Example
@DefaultValue
to specify a default value for a field whose value is injected.
Example 3.10. Setting default values
import javax.ws.rs.DefaultValue; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/monster") public class MonsterService { @Get public Monster getMonster(@QueryParam("id") @DefaultValue("42") int id, @QueryParam("type") @DefaultValue("bogeyman") String type) { ... } ... }
getMonster()
method in Example 3.10, “Setting default values” 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.
@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.
3.3. Using Apache CXF extensions
Overview
id
, type
, and size
, it could use a single @QueryParam
annotation to inject all of the parameters into a bean with corresponding fields.
Supported injection annotations
@PathParam
@QueryParam
@MatrixParam
@FormParam
Syntax
- Specify the annotation's parameter as an empty string. For example
@PathParam("")
specifies that a sequence of URI template variables are to be serialized into a bean. - Ensure that the annotated parameter is a bean with fields that match the values being injected.
Example
type
and id
. Their values are injected into the corresponding fields of the Monster
bean.
Example 3.11. Injecting query parameters into a bean
import javax.ws.rs.QueryParam; import javax.ws.rs.PathParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST public void updateMonster(@QueryParam("") Monster bean) { ... } ... } public class Monster { String type; String id; ... }
Chapter 4. Returning Information to the Consumer
Abstract
GenericEntity
object. When the resource method needs to return additional metadata along with the response entity, JAX-RS resource methods can return a Response
object containing any needed HTTP headers or other metadata.
- 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 return complex information with a programmatically determined HTTP return status. The
Response
object also allows HTTP headers to be specified. - JAX-RS 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.
4.1. Returning plain Java constructs
Overview
Returnable types
void
or any Java type for which an entity writer is provided. By default, the runtime has providers for the following:
- the Java primitives
- the
Number
representations of the Java primitives - JAXB objects
MIME types
@Produces
annotation. If it finds one, it uses the MIME type specified in the annotation. If it does not find one specified by the resource implementation, it relies on the entity providers to determine the proper MIME type.
- Java primitives and their
Number
representations are assigned a MIME type ofapplication/octet-stream
. - JAXB objects are assigned a MIME type of
application/xml
.
Response codes
204
(No Content)—the resource method's return type isvoid
204
(No Content)—the value of the returned entity isnull
200
(OK)—the value of the returned entity is notnull
4.2. Fine tuning an application's responses
4.2.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 4.1, “Getting a response builder using theResponse
class”.Example 4.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 4.2, “Getting a response builder using theResponseBuilderImpl
class” shows how Example 4.1, “Getting a response builder using theResponse
class” could be rewritten using theResponseBuilderImpl
class.Example 4.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();
TipYou 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.
4.2.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 4.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 4.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 4.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 4.6. Creating a response with a 500
status
import javax.ws.rs.core.Response; return Response.serverError().build();
4.2.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 4.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 4.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 4.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 4.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();
4.3. Returning entities with generic type information
Overview
javax.ws.rs.core.GenericEntity<T>
class provides finer control over the serializing of entities by providing a mechanism for specifying the generic type of the object representing the entity.
Using a GenericEntity<T>
object
Response
object is returned, the runtime cannot determine the generic type of the wrapped entity and the actual Java class of the object is used as the Java type.
GenericEntity<T>
object before being added to the Response
object being returned.
GenericEntity<T>
object. In practice, this approach is rarely used. The generic type information determined by reflection of an unwrapped entity and the generic type information stored for an entity wrapped in a GenericEntity<T>
object are typically the same.
Creating a GenericEntity<T>
object
GenericEntity<T>
object:
- Create a subclass of the
GenericEntity<T>
class using the entity being wrapped. Example 4.11, “Creating aGenericEntity<T>
object using a subclass” shows how to create aGenericEntity<T>
object containing an entity of typeList<String>
whose generic type will be available at runtime.Example 4.11. Creating a
GenericEntity<T>
object using a subclassimport javax.ws.rs.core.GenericEntity; List<String> list = new ArrayList<String>(); ... GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {}; Response response = Response.ok(entity).build();
TipThe subclass used to create aGenericEntity<T>
object is typically anonymous. - Create an instance directly by supplying the generic type information with the entity. Example 4.12, “Directly instantiating a
GenericEntity<T>
object” shows how to create a response containing an entity of typeAtomicInteger
.Example 4.12. Directly instantiating a
GenericEntity<T>
objectimport javax.ws.rs.core.GenericEntity; AtomicInteger result = new AtomicInteger(12); GenericEntity<AtomicInteger> entity = new GenericEntity<AtomicInteger>(result, result.getClass().getGenericSuperclass()); Response response = Response.ok(entity).build();
Chapter 5. Handling Exceptions
Abstract
WebApplicaitonException
exception. You can also provide ExceptionMapper<E>
implementations to map exceptions to appropriate responses.
5.1. Using WebApplicaitonException
exceptions to report errors
Overview
WebApplicationException
runtime exception to provide an easy way for resource methods to create exceptions that are appropriate for RESTful clients to consume. WebApplicationException
exceptions can include a Response
object that defines the entity body to return to the originator of the request. It also provides a mechanism for specifying the HTTP status code to be returned to the client if no entity body is provided.
Creating a simple exception
WebApplicaitonException
exception is to use either the no argument constructor or the constructor that wraps the original exception in a WebApplicationException
exception. Both constructors create a WebApplicaitonException
with an empty response.
500 Server Error
.
Setting the status code returned to the client
500
, you can use one of the four WebApplicaitonException
constructors that allow you to specify the status. Two of these constructors, shown in Example 5.1, “Creating a WebApplicationException
with a status code”, take the return status as an integer.
Example 5.1. Creating a WebApplicationException
with a status code
WebApplicationException(int status);
WebApplicationException(java.lang.Throwable cause,
int status);
WebApplicationException
with a status code” take the response status as an instance of Response.Status
.
Example 5.2. Creating a WebApplicationException
with a status code
WebApplicationException(javax.ws.rs.core.Response.Status status);
WebApplicationException(java.lang.Throwable cause,
javax.ws.rs.core.Response.Status status);
Providing an entity body
WebApplicationException
constructors that takes a Response
object. The runtime uses the Response
object to create the response sent to the client. The entity stored in the response is mapped to the entity body of the message and the status field of the response is mapped to the HTTP status of the message.
409 Conflict
.
Example 5.3. Sending a message with an exception
import javax.ws.rs.core.Response; import javax.ws.rs.WebApplicationException; import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl; ... ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.status(Response.Status.CONFLICT); builder.entity("The requested resource is conflicted."); Response response = builder.build(); throw WebApplicationException(response);
Extending the generic exception
WebApplicationException
exception. This would allow you to create custom exceptions and eliminate some boiler plate code.
WebApplicationException
” shows a new exception that creates a similar response to the code in Example 5.3, “Sending a message with an exception”.
Example 5.4. Extending WebApplicationException
public class ConflicteddException extends WebApplicationException { public ConflictedException(String message) { ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.status(Response.Status.CONFLICT); builder.entity(message); super(builder.build()); } } ... throw ConflictedException("The requested resource is conflicted.");
5.2. Mapping exceptions to responses
Overview
WebApplicationException
exception is impractical or impossible. For example, you may not want to catch all possible exceptions and then create a WebApplicationException
for them. You may also want to use custom exceptions that make working with your application code easier.
Response
object to send to a client. Custom exception providers are created by implementing the ExceptionMapper<E>
interface. When registered with the Apache CXF runtime, the custom provider will be used whenever an exception of type E is thrown.
How exception mappers are selected
- When a
WebApplicationException
, or one of its subclasses, with an empty entity body is thrown, the runtime will check to see if there is an exception mapper that handlesWebApplicationException
exceptions. If there is the exception mapper is used to create the response sent to the consumer. - When any exception other than a
WebApplicationException
exception, or one of its subclasses, is thrown, the runtime will check for an appropriate exception mapper. An exception mapper is selected if it handles the specific exception thrown. If there is not an exception mapper for the specific exception that was thrown, the exception mapper for the nearest superclass of the exception is selected.
ServletException
exception and passed onto the container runtime. The container runtime will then determine how to handle the exception.
Implementing an exception mapper
javax.ws.rs.ext.ExceptionMapper<E>
interface. As shown in Example 5.5, “Exception mapper interface”, the interface has a single method, toResponse()
, that takes the original exception as a parameter and returns a Response
object.
Example 5.5. Exception mapper interface
public interface ExceptionMapper<E extends java.lang.Throwable> { public Response toResponse(E exception); }
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.
@Provder
annotation.
Response
object, the runtime will a response with a status of 500 Server Error
to the consumer.
AccessDeniedException
exceptions and generates a response with a 403 Forbidden
status and an empty entity body.
Example 5.6. Mapping an exception to a response
import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import org.springframework.security.AccessDeniedException; @Provider public class SecurityExceptionMapper implements ExceptionMapper<AccessDeniedException> { public Response toResponse(AccessDeniedException exception) { return Response.status(Response.Status.FORBIDDEN).build(); } }
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
.
Registering an exception mapper
jaxrs:providers
element in the application's configuration file.
jaxrs:providers
element is a child of the jaxrs:server
element and contains a list of bean
elements. Each bean
element defines one exception mapper.
Example 5.7. Registering exception mappers with the runtime
<beans ...> <jaxrs:server id="customerService" address="/"> ... <jaxrs:providers> <bean id="securityException" class="com.bar.providers.SecurityExceptionMapper"/> </jaxrs:providers> </jaxrs:server> </beans>
Chapter 6. Publishing a Service
Abstract
Chapter 7. Entity Support
Abstract
Overview
MessageBodyReader
and MessageBodyWriter
implementations to serialize and de-serialize data between the HTTP messages and their Java representations. The readers and writers can restrict the MIME types they are capable of processing.
MessageBodyReader
interface and/or the MessageBodyWriter
interface. Custom readers and writers are registered with the runtime when the application is started.
Natively supported types
Table 7.1. Natively supported entity mappings
Java Type | MIME Type |
---|---|
primitive types | text/plain |
java.lang.Number | text/plain |
byte[] | */* |
java.lang.String | */* |
java.io.InputStream | */* |
java.io.Reader | */* |
java.io.File | */* |
javax.activation.DataSource | */* |
javax.xml.transform.Source | text/xml , application/xml , application/*+xml |
javax.xml.bind.JAXBElement | text/xml , application/xml , application/*+xml |
JAXB annotated objects | text/xml , application/xml , application/*+xml |
javax.ws.rs.core.MultivaluedMap<String, String> | application/x-www-form-urlencoded [a] |
javax.ws.rs.core.StreamingOutput | */* [b] |
[a]
This mapping is used for handling HTML form data.
[b]
This mapping is only supported for returning data to a consumer.
|
Custom readers
javax.ws.rs.ext.MessageBodyReader
interface.
Example 7.1. Message reader interface
package javax.ws.rs.ext; public interface MessageBodyReader<T> { public boolean isReadable(java.lang.Class<?> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, javax.ws.rs.core.MediaType mediaType); public T readFrom(java.lang.Class<T> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, javax.ws.rs.core.MediaType mediaType, javax.ws.rs.core.MultivaluedMap<String, String> httpHeaders, java.io.InputStream entityStream) throws java.io.IOException, WebApplicationException; }
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 returnstrue
.Table 7.2, “Parameters used to determine if a reader can produce an entity” describes theisReadable()
method's parameters.Table 7.2. Parameters used to determine if a reader can produce an entity
Parameter Type Description type
Class<T>
Specifies the actual Java class of the object used to store the entity. genericType
Type
Specifies the Java type of the object used to store the entity. For example, if the message body is to be converted into a method parameter, the value will be the type of the method parameter as returned by the Method.getGenericParameterTypes()
method.annotations
Annotation[]
Specifies the list of annotations on the declaration of the object created to store the entity. For example if the message body is to be converted into a method parameter, this will be the annotations on that parameter returned by the Method.getParameterAnnotations()
method.mediaType
MediatType
Specifies the MIME type of the HTTP entity. 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 anIOException
exception. If an error occurs that requires an HTTP error response, anWebApplicationException
with the HTTP response should be thrown.Table 7.3, “Parameters used to read an entity” describes thereadFrom()
method's parameters.Table 7.3. Parameters used to read an entity
Parameter Type Description type
Class<T>
Specifies the actual Java class of the object used to store the entity. genericType
Type
Specifies the Java type of the object used to store the entity. For example, if the message body is to be converted into a method parameter, the value will be the type of the method parameter as returned by the Method.getGenericParameterTypes()
method.annotations
Annotation[]
Specifies the list of annotations on the declaration of the object created to store the entity. For example if the message body is to be converted into a method parameter, this will be the annotations on that parameter returned by the Method.getParameterAnnotations()
method.mediaType
MediatType
Specifies the MIME type of the HTTP entity. httpHeaders
MultivaluedMap<String, String>
Specifies the HTTP message headers associated with the entity. entityStream
InputStream
Specifies the input stream containing the HTTP entity. ImportantThis method should not close the input stream.
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 the section called “Registering readers and writers”.
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.
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 writers
javax.ws.rs.ext.MessageBodyWriter
interface.
Example 7.3. Message writer interface
package javax.ws.rs.ext; public interface MessageBodyWriter<T> { public boolean isWriteable(java.lang.Class<?> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, javax.ws.rs.core.MediaType mediaType); public long getSize(T t, java.lang.Class<?> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, javax.ws.rs.core.MediaType mediaType); public void writeTo(T t, java.lang.Class<?> type, java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] annotations, javax.ws.rs.core.MediaType mediaType, javax.ws.rs.core.MultivaluedMap<String, Object> httpHeaders, java.io.OutputStream entityStream) throws java.io.IOException, WebApplicationException; }
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 returnstrue
.Table 7.4, “Parameters used to read an entity” describes theisWritable()
method's parameters.Table 7.4. Parameters used to read an entity
Parameter Type Description type
Class<T>
Specifies the Java class of the object being written. genericType
Type
Specifies the Java type of object to be written, obtained either by reflection of a resource method return type or via inspection of the returned instance. The GenericEntity
class, described in Section 4.3, “Returning entities with generic type information”, provides support for controlling this value.annotations
Annotation[]
Specifies the list of annotations on the method returning the entity. mediaType
MediatType
Specifies the MIME type of the HTTP entity. getSize()
- The
getSize()
method is called before thewriteTo()
. 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'sContent-Length
header.Table 7.5, “Parameters used to read an entity” describes thegetSize()
method's parameters.Table 7.5. Parameters used to read an entity
Parameter Type Description t
generic Specifies the instance being written. type
Class<T>
Specifies the Java class of the object being written. genericType
Type
Specifies the Java type of object to be written, obtained either by reflection of a resource method return type or via inspection of the returned instance. The GenericEntity
class, described in Section 4.3, “Returning entities with generic type information”, provides support for controlling this value.annotations
Annotation[]
Specifies the list of annotations on the method returning the entity. mediaType
MediatType
Specifies the MIME type of the HTTP entity. 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 anIOException
exception. If an error occurs that requires an HTTP error response, anWebApplicationException
with the HTTP response should be thrown.Table 7.6, “Parameters used to read an entity” describes thewriteTo()
method's parameters.Table 7.6. Parameters used to read an entity
Parameter Type Description t
generic Specifies the instance being written. type
Class<T>
Specifies the Java class of the object being written. genericType
Type
Specifies the Java type of object to be written, obtained either by reflection of a resource method return type or via inspection of the returned instance. The GenericEntity
class, described in Section 4.3, “Returning entities with generic type information”, provides support for controlling this value.annotations
Annotation[]
Specifies the list of annotations on the method returning the entity. mediaType
MediatType
Specifies the MIME type of the HTTP entity. httpHeaders
MultivaluedMap<String, Object>
Specifies the HTTP response headers associated with the entity. entityStream
OutputStream
Specifies the output stream into which the entity is written.
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 the section called “Registering readers and writers”.
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.
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; } }
Registering readers and writers
jaxrs:providers
element in the application's configuration file or using the JAXRSServerFactoryBean
class.
jaxrs:providers
element is a child of the jaxrs:server
element and contains a list of bean
elements. Each bean
element defines one entity provider.
Example 7.5. Registering entity providers with the runtime
<beans ...> <jaxrs:server id="customerService" address="/"> ... <jaxrs:providers> <bean id="isProvider" class="com.bar.providers.InputStreamProvider"/> <bean id="longProvider" class="com.bar.providers.LongProvider"/> </jaxrs:providers> </jaxrs:server> </beans>
JAXRSServerFactoryBean
class is a Apache CXF extension that provides access to the configuration APIs. It has a setProvider()
method that allows you to add instantiated entity providers to an application. Example 7.6, “Programmatically registering an entity provider” shows code for registering an entity provider programmatically.
Example 7.6. Programmatically registering an entity provider
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; ... JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); ... SourceProvider provider = new SourceProvider(); sf.setProvider(provider); ...
Chapter 8. Customizing the Media Types Handled by a Resource
Abstract
*/*
. You can restrict the media types a resource will process using annotations.
Chapter 9. Getting and Using Context Information
Abstract
9.1. Introduction to contexts
Context annotation
javax.ws.rs.core.Context
annotation. Annotating a field or parameter of one of the context types will instruct the runtime to inject the appropriate context information into the annotated field or parameter.
Types of contexts
Table 9.1. Context types
Where context information can be used
- resource classes
- resource methods
- entity providers
- exception mappers
Scope
@Context
annotation is specific to the current request. This is true in all cases including entity providers and exception mappers.
Adding contexts
Context<T>
object and registering it with the runtime.
9.2. Working with the full request URI
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.
9.2.1. Injecting the URI information
Overview
UriInfo
object is decorated with the @Context
annotation, the URI context for the current request is injected into the UriInfo
object.
Example
Example 9.1. Injecting the URI context into a class field
import javax.ws.rs.core.Context; import javax.ws.rs.core.UriInfo; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { @Context UriInfo requestURI; ... }
9.2.2. Working with the URI
Overview
UriInfo
interface provides methods for accessing the parts of the URI:
- the base URI
- the resource path
- the full URI
Getting the Base URI
@Path
annotations. For example if a service implementing the resource defined in Example 3.5, “Disabling URI decoding” were published to http://fusesource.org and a request was made on http://fusesource.org/montersforhire/nightstalker?12 the base URI would be http://fusesource.org.
Table 9.2. Methods for accessing a resource's base URI
Getting the path
rootPath
— /monstersforhire/getterPath
— /mostersforhire/nightstalkerTheGET
request was made on /monstersforhire/nightstalker.putterPath
— /mostersforhire/911ThePUT
request was made on /monstersforhire/911.
Example 9.2. Getting a resource's path
@Path("/monstersforhire/") public class MonsterService { @Context UriInfo rootUri; ... @GET public List<Monster> getMonsters(@Context UriInfo getUri) { String rootPath = rootUri.getPath(); ... } @GET @Path("\{type}") public Monster getMonster(@PathParam("type") String type, @Context UriInfo getUri) { String getterPath = getUri.getPath(); ... } @PUT @Path("\{id}") public void addMonster(@Encoded @PathParam("type") String type, @Context UriInfo putUri) { String putterPath = putUri.getPath(); ... } ... }
Table 9.3. Methods for accessing a resource's path
Getting the full request URI
Table 9.4. Methods for accessing the full request URI
getRequestUri()
methods would return http://fusesource.org/montersforhire/nightstalker?12. The getAbsolutePath()
method would return http://fusesource.org/montersforhire/nightstalker.
9.2.3. Getting the value of URI template variables
Overview
Methods for getting the path parameters
UriInfo
interface provides two methods, shown in Example 9.3, “Methods for returning path parameters from the URI context”, that return a list of the path parameters.
Example 9.3. Methods for returning path parameters from the URI context
MultivaluedMap<java.lang.String, java.lang.String> getPathParameters();
MultivaluedMap<java.lang.String, java.lang.String> getPathParameters(boolean decode);
getPathParameters()
method that does not take any parameters automatically decodes the path parameters. If you want to disable URI decoding use getPathParameters(false)
.
color
and note
.
Example
Example 9.4. Extracting path parameters from the URI context
import javax.ws.rs.Path; import javax.ws.rs.Get; import javax.ws.rs.core.Context; import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.MultivaluedMap; @Path("/monstersforhire/") public class MonsterService @GET @Path("\{type}\{size}") public Monster getMonster(@Context UriInfo uri) { MultivaluedMap paramMap = uri.getPathParameters(); String type = paramMap.getFirst("type"); String size = paramMap.getFirst("size"); } }
9.2.4. Getting the query parameters
9.2.5. Getting the matrix parameters
9.3. Working with the HTTP Headers
9.4. Working with security information
9.5. Working with preconditions
9.6. Working with servlet contexts
9.7. Working with the Apache CXF context object
9.8. Adding custom contexts
Chapter 10. Annotation Inheritance
Abstract
Overview
Inheritance rules
Kaijin
class' getMonster()
method inherits the @Path
, @GET
, and @PathParam
annotations from the Kaiju
interface.
Example 10.1. Annotation inheritance
public interface Kaiju { @GET @Path("/{id}") public Monster getMonster(@PathParam("id") int id); ... } @Path("/kaijin") public class Kaijin implements Kaiju { public Monster getMonster(int id) { ... } ... }
Overriding inherited annotations
Kaijin
class' getMonster()
method does not inherit any of the annotations from the Kaiju
interface. The implementation class overrides the @Produces
annotation which causes all of the annotations from the interface to be ignored.
Example 10.2. Overriding annotation inheritance
public interface Kaiju { @GET @Path("/{id}") @Produces("text/xml"); public Monster getMonster(@PathParam("id") int id); ... } @Path("/kaijin") public class Kaijin implements Kaiju { @GET @Path("/{id}") @Produces("application/octect-stream"); public Monster getMonster(@PathParam("id") int id) { ... } ... }
Index
Symbols
- @Consumes, Custom readers
- @Context, Context annotation, Overview
- @CookieParam, Injecting information from a cookie
- @DefaultValue, Specifying a default value to inject
- @DELETE, Specifying HTTP verbs
- @Encoded, Disabling URI decoding
- @FormParam, Injecting data from HTML forms
- @GET, Specifying HTTP verbs
- @HEAD, Specifying HTTP verbs
- @HeaderParam, Injecting information from the HTTP headers
- @MatrixParam, Using matrix parameters
- @Path, Setting the path, Requirements, Specifying a sub-resource
- @PathParam, Getting data from the URI's path
- @POST, Specifying HTTP verbs
- @Produces, Custom writers
- @Provider, Implementing an exception mapper, Custom readers, Custom writers
- @PUT, Specifying HTTP verbs
- @QueryParam, Using query parameters
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
C
- CacheControl, Setting cache control directives
- cacheControl(), Setting cache control directives
- ContextResolver<T>, Adding contexts
- cookie(), Adding a cookie
- cookies, Injecting information from a cookie
E
- entity parameter, Parameters
- ExceptionMapper<E>, Implementing an exception mapper
F
- form parameters, Injecting data from HTML forms
- forms, Injecting data from HTML forms
G
- GenericEntity<T>, Returning entities with generic type information
H
- header(), Adding custom headers
- HTML forms, Injecting data from HTML forms
- HTTP
- DELETE, Specifying HTTP verbs
- GET, Specifying HTTP verbs
- HEAD, Specifying HTTP verbs
- POST, Specifying HTTP verbs
- PUT, Specifying HTTP verbs
- HTTP headers, Injecting information from the HTTP headers, Types of contexts
- HttpHeaders, Types of contexts
M
- matrix parameters, Using matrix parameters, Getting the matrix parameters
- MessageBodyReader, Custom readers
- MessageBodyWriter, Custom writers
N
- NewCookie, Adding a cookie
- noContent(), Creating responses for successful requests
- notAcceptable(), Creating responses to signal errors
- notModified(), Creating responses for redirection
P
- parameter constraints, Parameters
- PathSegment, Getting the path
Q
- query parameters, Using query parameters, Getting the query parameters
R
- Request, Types of contexts
- ResourceComparator, Customizing the selection process
- Response, Relationship between a response and a response builder, Providing an entity body, Implementing an exception mapper
- Response.Status, Setting the status code returned to the client
- ResponseBuilder, Relationship between a response and a response builder, Getting a response builder, Handling more advanced responses
- ResponseBuilderImpl, Getting a response builder, Handling more advanced responses
- root resource
- requirements, Requirements
- root URI, Requirements, Working with the URI
S
- SecurityContext, Types of contexts
- seeOther(), Creating responses for redirection
- serverError(), Creating responses to signal errors
- status(), Setting the response status
- sub-resource locator, Sub-resource locators
- sub-resource method, Sub-resource methods
T
- temporaryRedirect(), Creating responses for redirection
U
- URI
- decoding, Disabling URI decoding
- injecting, Overview
- matrix parameters, Using matrix parameters, Getting the matrix parameters
- query parameters, Using query parameters, Getting the query parameters
- root, Requirements, Working with the URI
- template variables, Getting data from the URI's path, Getting the value of URI template variables
- UriBuilder, Getting the Base URI, Getting the full request URI
- UriInfo, Types of contexts, Working with the full request URI
W
- WebApplicationException, Using WebApplicaitonException exceptions to report errors
Legal Notice
Trademark Disclaimer
Legal Notice
Third Party Acknowledgements
- JLine (http://jline.sourceforge.net) jline:jline:jar:1.0License: BSD (LICENSE.txt) - Copyright (c) 2002-2006, Marc Prud'hommeaux
mwp1@cornell.edu
All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of JLine nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Stax2 API (http://woodstox.codehaus.org/StAX2) org.codehaus.woodstox:stax2-api:jar:3.1.1License: The BSD License (http://www.opensource.org/licenses/bsd-license.php)Copyright (c) <YEAR>, <OWNER> All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - jibx-run - JiBX runtime (http://www.jibx.org/main-reactor/jibx-run) org.jibx:jibx-run:bundle:1.2.3License: BSD (http://jibx.sourceforge.net/jibx-license.html) Copyright (c) 2003-2010, Dennis M. Sosnoski.All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - JavaAssist (http://www.jboss.org/javassist) org.jboss.javassist:com.springsource.javassist:jar:3.9.0.GA:compileLicense: MPL (http://www.mozilla.org/MPL/MPL-1.1.html)
- HAPI-OSGI-Base Module (http://hl7api.sourceforge.net/hapi-osgi-base/) ca.uhn.hapi:hapi-osgi-base:bundle:1.2License: Mozilla Public License 1.1 (http://www.mozilla.org/MPL/MPL-1.1.txt)