|  | <?xml version="1.0"?> | 
|  | <!-- | 
|  |  | 
|  | Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. | 
|  |  | 
|  | This program and the accompanying materials are made available under the | 
|  | terms of the Eclipse Public License v. 2.0, which is available at | 
|  | http://www.eclipse.org/legal/epl-2.0. | 
|  |  | 
|  | This Source Code may also be made available under the following Secondary | 
|  | Licenses when the conditions for such availability set forth in the | 
|  | Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | 
|  | version 2 with the GNU Classpath Exception, which is available at | 
|  | https://www.gnu.org/software/classpath/license.html. | 
|  |  | 
|  | SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | 
|  |  | 
|  | --> | 
|  |  | 
|  | <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents; ]> | 
|  | <chapter xmlns="http://docbook.org/ns/docbook" | 
|  | version="5.0" | 
|  | xml:lang="en" | 
|  | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
|  | xmlns:xi="http://www.w3.org/2001/XInclude" | 
|  | xmlns:xlink="http://www.w3.org/1999/xlink" | 
|  | xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd | 
|  | http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd" | 
|  | xml:id="representations"> | 
|  | <title>Representations and Responses</title> | 
|  |  | 
|  | <section xml:id="reps-and-types"> | 
|  | <title>Representations and Java Types</title> | 
|  | <para>Previous sections on &jaxrs.Produces; and &jaxrs.Consumes; annotations | 
|  | referred to media type of an entity representation. Examples above depicted resource | 
|  | methods that could consume and/or produce String Java type for a number of | 
|  | different media types. This approach is easy to understand and relatively | 
|  | straightforward when applied to simple use cases. | 
|  | </para> | 
|  |  | 
|  | <para>To cover also other cases, handling non-textual data for example or handling data stored in the file system, etc., | 
|  | JAX-RS implementations are required to support also other kinds of media type | 
|  | conversions where additional, non-String, Java types are being utilized. Following is a short listing of the Java types | 
|  | that are supported out of the box with respect to supported media type: | 
|  | <itemizedlist> | 
|  | <listitem>All media types (<literal>*/*</literal>) | 
|  | <itemizedlist> | 
|  | <listitem><literal>byte[]</literal></listitem> | 
|  | <listitem><literal>java.lang.String</literal></listitem> | 
|  | <listitem><literal>java.io.Reader</literal> (inbound only)</listitem> | 
|  | <listitem><literal>java.io.File</literal></listitem> | 
|  | <listitem><literal>javax.activation.DataSource</literal></listitem> | 
|  | <listitem><literal>javax.ws.rs.core.StreamingOutput</literal> (outbound only)</listitem> | 
|  | </itemizedlist> | 
|  | </listitem> | 
|  | <listitem>XML media types (<literal>text/xml</literal>, <literal>application/xml</literal> and <literal>application/...+xml</literal>) | 
|  | <itemizedlist> | 
|  | <listitem><literal>javax.xml.transform.Source</literal></listitem> | 
|  | <listitem><literal>javax.xml.bind.JAXBElement</literal></listitem> | 
|  | <listitem>Application supplied JAXB classes (types annotated with | 
|  | <link xlink:href="http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlRootElement.html">@XmlRootElement</link> | 
|  | or<link xlink:href="http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlType.html">@XmlType</link>)</listitem> | 
|  | </itemizedlist> | 
|  | </listitem> | 
|  | <listitem>Form content (<literal>application/x-www-form-urlencoded</literal>) | 
|  | <itemizedlist> | 
|  | <listitem><literal>MultivaluedMap<String,String></literal></listitem> | 
|  | </itemizedlist> | 
|  | </listitem> | 
|  | <listitem>Plain text (<literal>text/plain</literal>) | 
|  | <itemizedlist> | 
|  | <listitem><literal>java.lang.Boolean</literal></listitem> | 
|  | <listitem><literal>java.lang.Character</literal></listitem> | 
|  | <listitem><literal>java.lang.Number</literal></listitem> | 
|  | </itemizedlist> | 
|  | </listitem> | 
|  | </itemizedlist> | 
|  | </para> | 
|  |  | 
|  | <para>Unlike method parameters that are associated with the extraction of | 
|  | request parameters, the method parameter associated with the | 
|  | representation being consumed does not require annotating. In other words the | 
|  | representation (entity) parameter does not require a specific 'entity' annotation. A method parameter | 
|  | without an annotation is an entity. A maximum of | 
|  | one such unannotated method parameter may exist since there may only be a | 
|  | maximum of one such representation sent in a request. | 
|  | </para> | 
|  |  | 
|  | <para>The representation being produced corresponds to what is returned by | 
|  | the resource method. For example JAX-RS makes it simple to produce images | 
|  | that are instance of | 
|  | <literal>File</literal> | 
|  | as follows: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Using | 
|  | <code>File</code> | 
|  | with a specific media type to produce a response | 
|  | </title> | 
|  | <programlisting language="java" linenumbering="numbered">@GET | 
|  | @Path("/images/{image}") | 
|  | @Produces("image/*") | 
|  | public Response getImage(@PathParam("image") String image) { | 
|  | File f = new File(image); | 
|  |  | 
|  | if (!f.exists()) { | 
|  | throw new WebApplicationException(404); | 
|  | } | 
|  |  | 
|  | String mt = new MimetypesFileTypeMap().getContentType(f); | 
|  | return Response.ok(f, mt).build(); | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>The | 
|  | <literal>File</literal> type can also be used when consuming a representation (request entity). | 
|  | In that case a temporary file will be created from the incoming request entity and passed as a | 
|  | parameter to the resource method. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | The <literal>Content-Type</literal> response header | 
|  | (if not set programmatically as described in the next section) | 
|  | will be automatically set based on the media types declared by &jaxrs.Produces; annotation. | 
|  | Given the following method, the most acceptable media type is used when multiple output media types are allowed: | 
|  | </para> | 
|  | <para> | 
|  | <programlisting language="java" linenumbering="numbered">@GET | 
|  | @Produces({"application/xml", "application/json"}) | 
|  | public String doGetAsXmlOrJson() { | 
|  | ... | 
|  | }</programlisting> | 
|  |  | 
|  | If <literal>application/xml</literal> is the most acceptable media type defined | 
|  | by the request (e.g. by header <literal>Accept: application/xml</literal>), then the | 
|  | <literal>Content-Type</literal> response header | 
|  | will be set to <literal>application/xml</literal>. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Building Responses</title> | 
|  |  | 
|  | <para>Sometimes it is necessary to return additional | 
|  | information in response to a HTTP request. Such information may be built | 
|  | and returned using &jaxrs.core.Response; and &jaxrs.core.Response.ResponseBuilder;. | 
|  | For example, a common RESTful pattern for the creation of a new resource | 
|  | is to support a POST request that returns a 201 (Created) status code and | 
|  | a | 
|  | <literal>Location</literal> | 
|  | header whose value is the URI to the newly | 
|  | created resource. This may be achieved as follows: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Returning 201 status code and adding | 
|  | <literal>Location</literal> | 
|  | header in response to POST request | 
|  | </title> | 
|  | <programlisting language="java" linenumbering="numbered">@POST | 
|  | @Consumes("application/xml") | 
|  | public Response post(String content) { | 
|  | URI createdUri = ... | 
|  | create(content); | 
|  | return Response.created(createdUri).build(); | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>In the above no representation produced is returned, this can be | 
|  | achieved by building an entity as part of the response as follows: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Adding an entity body to a custom response</title> | 
|  | <programlisting language="java" linenumbering="numbered">@POST | 
|  | @Consumes("application/xml") | 
|  | public Response post(String content) { | 
|  | URI createdUri = ... | 
|  | String createdContent = create(content); | 
|  | return Response.created(createdUri).entity(Entity.text(createdContent)).build(); | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>Response building provides other functionality such as setting the | 
|  | entity tag and last modified date of the representation. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>WebApplicationException and Mapping Exceptions to Responses</title> | 
|  |  | 
|  | <para>Previous section shows how to return HTTP responses, | 
|  | that are built up programmatically. | 
|  | It is possible to use the very same mechanism | 
|  | to return HTTP errors directly, | 
|  | e.g. when handling exceptions in a try-catch block. | 
|  | However, to better align with the Java programming model, | 
|  | JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. | 
|  | </para> | 
|  |  | 
|  | <para>The following example shows throwing | 
|  | <literal>CustomNotFoundException</literal> | 
|  | from a resource method in order to return an error HTTP response to the client: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Throwing exceptions to control response</title> | 
|  | <programlisting language="java" linenumbering="numbered">@Path("items/{itemid}/") | 
|  | public Item getItem(@PathParam("itemid") String itemid) { | 
|  | Item i = getItems().get(itemid); | 
|  | if (i == null) { | 
|  | throw new CustomNotFoundException("Item, " + itemid + ", is not found"); | 
|  | } | 
|  |  | 
|  | return i; | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>This exception is an application specific exception that extends &jaxrs.WebApplicationException; | 
|  | and builds a HTTP response with the 404 status code and an optional | 
|  | message as the body of the response: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Application specific exception implementation</title> | 
|  | <programlisting language="java" linenumbering="numbered">public class CustomNotFoundException extends WebApplicationException { | 
|  |  | 
|  | /** | 
|  | * Create a HTTP 404 (Not Found) exception. | 
|  | */ | 
|  | public CustomNotFoundException() { | 
|  | super(Responses.notFound().build()); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Create a HTTP 404 (Not Found) exception. | 
|  | * @param message the String that is the entity of the 404 response. | 
|  | */ | 
|  | public CustomNotFoundException(String message) { | 
|  | super(Response.status(Responses.NOT_FOUND). | 
|  | entity(message).type("text/plain").build()); | 
|  | } | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>In other cases it may not be appropriate to throw instances of &jaxrs.WebApplicationException;, | 
|  | or classes that extend &jaxrs.WebApplicationException;, and instead it may be preferable to map an existing exception to a | 
|  | response. For such cases it is possible to use a custom exception mapping provider. The provider must implement | 
|  | the &jaxrs.ext.ExceptionMapper; interface. For example, the following | 
|  | maps the | 
|  | <link xlink:href="http://docs.oracle.com/javaee/5/api/javax/persistence/EntityNotFoundException.html">EntityNotFoundException</link> | 
|  | to a HTTP 404 (Not Found) response: | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Mapping generic exceptions to responses</title> | 
|  | <programlisting language="java" linenumbering="numbered">@Provider | 
|  | public class EntityNotFoundMapper implements ExceptionMapper<javax.persistence.EntityNotFoundException> { | 
|  | public Response toResponse(javax.persistence.EntityNotFoundException ex) { | 
|  | return Response.status(404). | 
|  | entity(ex.getMessage()). | 
|  | type("text/plain"). | 
|  | build(); | 
|  | } | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>The above class is annotated with &jaxrs.ext.Provider;, this declares that the class is of interest to the JAX-RS runtime. Such a | 
|  | class may be added to the set of classes of the &jaxrs.core.Application; instance that is configured. When an application throws an | 
|  | <link xlink:href="http://docs.oracle.com/javaee/6/api/javax/persistence/EntityNotFoundException.html">EntityNotFoundException</link> | 
|  | the | 
|  | <literal>toResponse</literal> | 
|  | method of the | 
|  | <literal>EntityNotFoundMapper</literal> | 
|  | instance will be invoked. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | Jersey supports extension of the exception mappers. These extended mappers must implement | 
|  | the <literal>org.glassfish.jersey.spi.ExtendedExceptionMapper</literal> interface. This interface additionally | 
|  | defines method <literal>isMappable(Throwable)</literal> which will be invoked by the Jersey runtime | 
|  | when exception is thrown and this provider is considered as mappable based on the exception type. Using this | 
|  | method the provider can reject mapping of the exception before the method <literal>toResponse</literal> | 
|  | is invoked. The provider can for example check the exception parameters and based on them return false | 
|  | and let other provider to be chosen for the exception mapping. | 
|  | </para> | 
|  |  | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Conditional GETs and Returning 304 (Not Modified) Responses</title> | 
|  |  | 
|  | <para>Conditional GETs are a great way to reduce bandwidth, and | 
|  | potentially improve on the server-side performance, depending on how the information used | 
|  | to determine conditions is calculated. A well-designed web site may for example return | 
|  | 304 (Not Modified) responses for many of static images it serves. | 
|  | </para> | 
|  |  | 
|  | <para>JAX-RS provides support for conditional GETs using the contextual interface &jaxrs.core.Request;. | 
|  | </para> | 
|  |  | 
|  | <para>The following example shows conditional GET support:</para> | 
|  |  | 
|  | <para> | 
|  | <example> | 
|  | <title>Conditional GET support</title> | 
|  | <programlisting language="java" linenumbering="numbered">public SparklinesResource( | 
|  | @QueryParam("d") IntegerList data, | 
|  | @DefaultValue("0,100") @QueryParam("limits") Interval limits, | 
|  | @Context Request request, | 
|  | @Context UriInfo ui) { | 
|  | if (data == null) { | 
|  | throw new WebApplicationException(400); | 
|  | } | 
|  |  | 
|  | this.data = data; | 
|  | this.limits = limits; | 
|  |  | 
|  | if (!limits.contains(data)) { | 
|  | throw new WebApplicationException(400); | 
|  | } | 
|  |  | 
|  | this.tag = computeEntityTag(ui.getRequestUri()); | 
|  |  | 
|  | if (request.getMethod().equals("GET")) { | 
|  | Response.ResponseBuilder rb = request.evaluatePreconditions(tag); | 
|  | if (rb != null) { | 
|  | throw new WebApplicationException(rb.build()); | 
|  | } | 
|  | } | 
|  | }</programlisting> | 
|  | </example> | 
|  | </para> | 
|  |  | 
|  | <para>The constructor of the | 
|  | <literal>SparklinesResource</literal> | 
|  | root | 
|  | resource class computes an entity tag from the request URI and then calls | 
|  | the | 
|  | <link xlink:href="&jaxrs.javadoc.uri;/core/Request.html#evaluatePreconditions(javax.ws.rs.core.EntityTag)">request.evaluatePreconditions</link> | 
|  | with that entity tag. If a client request contains an | 
|  | <literal>If-None-Match</literal> | 
|  | header with a value that contains the | 
|  | same entity tag that was calculated then the | 
|  | <link xlink:href="&jaxrs.javadoc.uri;/core/Request.html#evaluatePreconditions(javax.ws.rs.core.EntityTag)">evaluatePreconditions</link> | 
|  | returns a pre-filled out response, with the 304 status code and entity tag | 
|  | set, that may be built and returned. Otherwise, | 
|  | <link xlink:href="&jaxrs.javadoc.uri;/core/Request.html#evaluatePreconditions(javax.ws.rs.core.EntityTag)">evaluatePreconditions</link> | 
|  | returns | 
|  | <literal>null</literal> | 
|  | and the normal response can be | 
|  | returned. | 
|  | </para> | 
|  |  | 
|  | <para>Notice that in this example the constructor of a resource class is used | 
|  | to perform actions that may otherwise have to be duplicated to | 
|  | be invoked for each resource method. The life cycle of resource classes is per-request | 
|  | which means that the resource instance is created for each request and therefore | 
|  | can work with request parameters and for example make changes to the request processing by | 
|  | throwing an exception as it is shown in this example. | 
|  | </para> | 
|  | </section> | 
|  | </chapter> |