JAX-RS

JAX-RS is a specification, a set of interfaces and annotations offered by Java EE. Well-known Implementations are RESTEasy and Jersey.

JAX-RS 2.1 Specification

Applications

JAX-RS application has [1..] resources and [0..] providers.

Configuration: via application-supplied subclass of Application.

Publications

Applications are published in diff ways:

  1. if app runs in Java SE environment

  2. within container (is packed as .war file)

    1. app classes are packaged in WEB-INF/classes or WEB-INF/lib and required libs are packaged in WEB-INF/lib

Resources

Is a POJO that has at least one method annotated with @Path or a request method designator.

By default a new resource class instance is created for each request to that resource.

Resource methods

JAX-RS resource method designators: @GET, @POST, @PUT, @DELETE, @PATCH, @HEAD, @OPTIONS

Methods must be public.

Method parameters are mapped from the request according to the semantics of annotation:

  • @MatrixParam - extracts the value of URI matrix parameter

    • Matrix parameters are name-value pairs embedded within the path of a URI string

    • e.g. http://example.cars.com/mercedes/e55;color=black/2006

    • color=black is matrix parameter

  • @QueryParam - extracts the value of URI query parameter

  • @PathParam - extracts the value of URI template parameter

  • @CookieParam - extracts the value of a cookie

  • @HeaderParam - extracts the value of header

  • @FormParam

  • @Context - injects an instance of supported resource. ⚠️ TODO investigate later

  • @DefaultValue is used to supply a default value for parameter

  • @Encode is used to disable auto URI decoding of param value

Return type

  • void - results in an empty entity body with 204 status code

    • 204 status code means that the request was received and understood, but that there is no need to send any data back

  • Response

    • entity property of Response -mapped-> entity body

    • status property of Response -mapped-> status code

    • use Response to provide metadata; use ResponseBuilder;

  • GenericEntity

    • Entity property of GenericEntity -mapped-> entity body

  • Other

    • returned instance -mapped-> entity body

To illustrate consider a method that always returns an instance of ArrayList<String> (directly or wrapped).

Exceptions

  • Servlet-based implementation wrapper ServletException

  • JAX-WS Provider-based implementation wrapper WebServiceException

HEAD and OPTIONS

URI Templates

πŸ’‘ This is a relative path with a combination of deployment context and application path @ApplicationPath .

@Path("widget list/{id}") equivalent to @Path("widget%20list/{id}") (encoded automatically).

πŸ’‘ Annotation value can be a regex, e.g.

any request starting with widgets and containing at least one more path segment will match. E.g. widgets/small/a => the value of path will be small/a

Sub Resources

Methods of resource class annotated by @Path are either:

  • sub-resource methods => handle HTTP request directly

  • sub-resource locators => return an object or class that will handle HTTP request

    • may have all the same parameters as a normal resource method, except they must not have entity parameter

Media type capabilities

  • @Consumes

  • @Produces

Can be applied to resource method(overrides specified on class and on provider), resource class, entity provider.

πŸ’‘ Default is "*/*"

Multiple media types

When accepting multiple media types client may indicate preference by using relative quality factor q parameter (q-value ). Q-value is [0..1]

  • 0 - undesired

  • 1 - highly desired (default value)

Example for above code: GET with header Accept: "text/html; q=1, application/widgets+xml; q=0.8" will match getAsHtml instead of getAsXML because of q.

A server can also indicate media type preference using the qs parameter.

With GET request with header Accept: "application/*; q=0.5" => media type application/xml is selected due to higher qs value.

Annotation inheritance

⚠️ For consistency with other Java EE specifications, it is recommended to always repeat annotations instead of relying on annotation inheritance.

ActivityLog.getFeed() inherits @GET and @Produces from the interface.

⚠️ But, conversely

In the above case @GET annotation from ReadOnlyAtomFeed.getFeed() is not inherited. Because

If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the superclass or interface method are ignored

Providers

Annotation @Provider is used by JAX-RS runtime to automatically discover provider classes via mechanisms such as class scanning.

  • Provider must have public constructor

  • Constructor may include parameter annotated with @Context

  • Providers may be annotated with @Priority. @Priority(1) > @Priority(10)

  • Default priority for application-supplied providers is javax.ws.rs.Priorities.USER

MessageBodyReader

Message entity body -> Java type

  • implement MessageBodyReader

  • annotate with @Provider (for automatic discovery)

MessageBodyReader always operate on decoded HTTP entity body (decoded by container or JAX-RS runtime).

How entity body is mapped to Java method parameter:

MessageBodyWriter

javax.ws.rs.ext.MessageBodyWriter

Contract for a provider that supports the conversion of a Java type to a stream.

A MessageBodyWriter implementation may be annotated with @javax.ws.rs.Produces to restrict the media types for which it will be considered suitable.

Providers implementing MessageBodyWriter contract must be either programmatically registered in a JAX-RS runtime or must be annotated with @javax.ws.rs.ext.Provider annotation to be automatically discovered by the JAX-RS runtime during a provider scanning phase.

Steps for mapping return value to message entity body:

Media type capabilities

Readers and writers may restrict media types they support using @Consumes and @Produces. Absence of annotation means "*/*".

ExceptionMapper

must implement javax.ws.rs.ext.ExceptionMapper

Contract for a provider that maps Java exceptions (checker or runtime) to javax.ws.rs.core.Response. If >1 exception providers are applicable => use with highest priority.

Providers implementing ExceptionMapper contract must be either programmatically registered in a JAX-RS runtime or must be annotated with @javax.ws.rs.ext.Provider annotation to be automatically discovered by the JAX-RS runtime during a provider scanning phase.

Client API

javax.ws.rs.client

Filters

Filters execute code at an extension point but without wrapping a method invocation.

@Provider

Filters are grouped in Filter chain . There is a separate filter chain for each extension point (e.g. ClientRequest, ClientResponse, ContainerRequest, ContainerResponse, PreMatchContainerRequest).

ContainerRequestFilter annotated by @PreMatching executed upon receiving client request but before a resource method is matched.

Interceptors

Entity interceptors wrap around a method invocation at a specific extension point.

@Provider

Reader interceptor wraps around calls to MessageBodyReader readFrom().

Writer interceptor wraps around calls to MessageBodyWriter writeTo().

Binding

Global

A filter/interceptor that has no annotations is assumed to be bound globally => applies to all resource methods in application (well either Provider or register manually in Application)

Name binding

JAX-RS request processing cycle

Open questions:

  • How JAX-RS configuration is done?

Last updated

Was this helpful?