Request and Response Entities

Request and response entities represent the main part of an HTTP request. Entities are also refered to as the "message body" or "payload". Entities are sent via a request, usually an HTTP POST and PUT method are used or they are returned in a response, this is relevant for all HTTP methods.

Unlike other distributed systems technologies, there is generally no wrapper around an entity. For example, if a request is made for a binary PNG image represented here, http://example.com/user/abcd/portrait.png , the response entity is only the PNG image binary data.

Resource methods have a single entity parameter that represents the main entity body. It is the only unannotated parameter allowed in a resource method.

When using JAX-RS, request and response entites are mapped to and from Java types by Entity Providers that implement the JAX-RS interfaces, MessageBodyReader and MessageBodyWriter. Applications may provide their own MessageBodyReaders and MessageBodyWriters that take precedent over the runtime provided ones.

Media Types (MIME) and javax.ws.rs.core.MediaType

The request and response entity can be any form of data, a way of identifying what the entities bits and bytes represent is needed. In requests and responses, the Content-Type HTTP header is used to indicate the type of entity currently being sent. The Content-Type value comes from a well known media type as registered in IANA.

Common content types include "text/plain", "text/xml", "text/html", and "application/json".

Correct Content-Type values are essential for clients and servers. "Unusual" behavior by clients such as browsers can be attributed to wrong content types.

Media Types are also used in a request Accept header to indicate what type of resource representation the client wants to receive. Clients could indicate a preference as well, such as JSON before XML.

Reference

Refer to the HTTP spec regarding the Accept header and the Content Negotiation topic.

javax.ws.rs.core.MediaType has functionality and representations related to Media Types.

@Consumes and @Produces Annotations

Annotating a class or a resource method with @Consumes and @Produces will help the JAX-RS runtime identify the appropriate methods to invoke for requests. For example:

@Path("/example")
public RootResource {
    @POST
    @Consumes("text/xml")
    @Produces("text/xml")
    public Response getOnlyXML(String incomingXML) {
        return Response.ok("only xml").type("text/xml").build();
    }

    @GET
    @Produces("text/html", "text/plain")
    public String getText() {
        return "text representation";
    }
}

In the previous code example, if a HTTP POST to "/example" was issued with a Content-Type header of "text/xml" and an Accept header of "text/xml", then the RootResource#getOnlyXML method would be invoked. If the same POST request was issued with an Accept header of "text/plain", then a 406 Not Acceptable response would be generated by the JAX-RS runtime and the method would not be invoked.

It is a good practice to return a javax.ws.rs.core.Response with a .type() or .variant() call since it would guarantee a return content type. Notice that the above getText() code supports multiple data types. A javax.ws.rs.core.Response object returned must have a single concrete Content-Type value. In orer to select the best acceptable representation in the resource method, use either the @Context HttpHeaders#getAcceptableMediaTypes() or a @Context Request#selectVariant() method.

Reference

Refer to the Context topic page for more information.

While resource methods may consume one media type for example XML and produce another such as JSON, most user requests expect the same media type that was sent in the request to be returned in the response.

If the Content-Type header is empty and there is an entity, then the JAX-RS runtime will make the Content-Type be "application/octet-stream". If an Accept header is empty, then according to the HTTP specification, the Accept header is equivalent to */* which is a wildcard that matches anything.

Important Note

Note that the resource method ultimately has control over the response content. If a javax.ws.rs.core.Response is returned, then the developer can return whatever Content-Type is desired. The @Consumes and @Produces is primarily useful only when processing request information and determining which resource method is possible to invoke. If a specific Response content type is not specified via a returned javax.ws.rs.core.Response object, the response media type is determined by a combination of the @Produces annotation values and the available MessageBodyWriters for the response entity's Java type. This can lead to undesired results if there is no @Produces annotation or if the @Produces annotation has multiple media types listed.

Reference

Refer to the JAX-RS specification for the effective algorithm used.

JAX-RS Standard Entity Parameter Types

JAX-RS requires certain parameters to be supported for virtually any content type. The following table lists the supported content types:

Java Type

Content Type Supported

Special Notes

java.lang.String

*/*

byte[]

*/*

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
and JAXB classes

text/xml, application/xml, application/*+xml

javax.ws.rs.core
.MultivaluedMap
<String, String>

application/x-www-form-urlencoded

javax.ws.rs
.core.StreamingOutput

*/*

As a writer only

Developers can use the previous Java types as entity parameters for requests and responses.

@Path("/example")
public class RootResource {

    @GET
    @Produces("text/xml")
    public Response getInfo() {
        byte[] entity = /* get the entity into a byte array */
        return Response.ok(entity).type("text/xml").build();
    }

    @POST
    @Consumes("application/json")
    @Produces("application/json")
    public StreamingOutput createItem(InputStream requestBodyStream) {
        /* read the requestBodyStream like a normal input stream */
        return new StreamingOutput() {

            public void write(OutputStream output) throws IOException, WebApplicationException {
                byte[] out = /* get some bytes to write */
                output.write(out);
            }
        })
    }
}

Transfer Encoding

Transfer or "chunked" encoding is handled by the container for incoming requests. The container or the application must do any transfer encoding for outgoing responses.

Content Encoding

Content for example "gzip" and or "deflate" encoding is handled by the application. However, some containers handle content encoding for developers and will uncompress content automatically or will with various configuration set. Check the container documentation.

  • No labels