Assets

An Asset is a special entity that is returned by a resource method or is injected into a resource method as an entity parameter. The asset is used for retrieving the actual request entity or response entity.
The purpose of an asset is to act as a container of an entity data model while providing the transformation methods of the data model into data models of other representations.
Asset classes are POJOs, annotated with the @Asset annotation, that have any number of entity methods.

When an asset instance is returned from a resource method or is set as the entity on a Response instance, it is used by the Apache Wink runtime to retrieve the actual response entity by invoking the appropriate entity-producing method of the asset.

Reference

For more information on Entity-Producing Methods refer to section Entity Producing Methods.

When an asset is the entity parameter of a resource method, it is used by the Apache Wink runtime to set the actual request entity by invoking the appropriate entity-consuming method of the asset.

Assets Overview

A typical application exposes each resource in a number of representations. Some form of data model usually backs the resource, and the application business logic relies on the manipulation of that data model. The application will most likely expose resource methods allowing the consumption of the data model in more than one representation (for example Atom and XML) and the production of the data model in other representation (for example Atom, XML and JSON).

According to the JAX-RS specification, the optimal method for implementing a resource is one that consumes and produces an application data model and makes use of a different provider for every media type.

For example, if a resource implements methods that consume and produce a "Defect" bean, then a provider must be implemented for each representation of the "Defect" (Atom, XML and JSON). However, there are times that the transformation of the application data model into a representation requires information that may only be available to the resource but is unavailable to a provider (for example, a connection to the Database).

There are several solutions for dealing with the problem of a provider not having sufficient information to perform application data transformations. The following is a description of two possible solutions:

  • Passing the information as members on the resource and accessing the resource from the provider via the UriInfo context.

This solution is only plausible if the resource scope is "per request" and does not work if the resource is a singleton.

  • Passing the information from the resource to the provider via the attributes of the HttpServletRequest.

This solution is only plausible when the application is deployed in a JEE container and is not the optimal solution.
In addition to the previously mentioned problem, the creation of a provider for every data model per media type may result in the inflation of providers in the system, causing the provider selection algorithm to consider a large set of potential providers.

As a result, the selection of the actual provider from the set of potential providers is non-deterministic, because the selection between them is undefined.

Performance Degradation

An additional side effect of provider inflation is performance degradation.

The use of an asset solves the problem of passing information between a resource and a provider and reduces the amount of registered providers in the system.

Lifecycle

Resource methods can use an asset as a response entity and as a request entity. The Apache Wink runtime applies different lifecycles for each case.

Response Entity Asset

The lifecycle of an asset as a response entity is as follows:

  1. The application creates and returns the asset from the resource method.
  2. The appropriate entity-producing method is invoked by the Apache Wink runtime to retrieve the actual response entity.
  3. The appropriate message body writer as obtained from the Providers#getMessageBodyWriter() method serializes the entity obtained at the previous step.
  4. The asset is made available for garbage collection.

Request Entity Asset

The lifecycle of an asset as a request entity is as follows:

  1. An asset class is instantiated by the Apache Wink runtime by invoking the asset default constructor. Note that this implies that the asset class must have a public default constructor.
  2. The appropriate message body reader as obtained from the Providers#getMessageBodyReader() method is invoked by the Apache Wink runtime to read the request entity.
  3. The appropriate entity-consuming method is invoked on the asset to populate the asset with the request entity.
  4. The asset is injected into the resource method as the entity parameter.
  5. The asset is made available for garbage collection after returning from the resource method.

Asset Entity Methods

Asset Entity methods are the public methods of an asset annotated with either @Consumes or @Produces annotation. Annotating a method with both @Consumes and @Produces annotations is not supported and may result in unexpected behavior.

Entity Producing Methods

An Entity Producing Method is a public asset method annotated with the @Produces annotation, designating it to produce the actual response entity. Such methods produce an entity only for the media types declared in the @Produces annotation. Note that under this definition, wildcard ("/") is allowed.
The Apache Wink runtime will not invoke an entity-producing method whose effective value of @Produces does not match the request Accept header

Entity Consuming Methods

An Entity Consuming Method is a public asset method annotated with the @Consumes annotation, designating it to consume the actual request entity for populating the asset. Such methods consume an entity only for the media types declared in the @Consumes annotation. Note that under this definition, wildcard ("/") is allowed.
The Apache Wink runtime will not invoke an entity-consuming method whose effective value of @Consumes does not match the request Content-Type header.

Parameters

Asset Entity methods support the same parameter types as JAX-RS specifies for a resource method.

Return Type

Entity methods may return any type that is permissible to return from a resource method.

Exceptions

Exceptions thrown from an entity method are treated as exceptions thrown from a resource method.

Annotation Inheritance

The @Produces and @Consumes annotations are not inherited when an asset sub-class overrides an asset entity method. Asset sub-classes must re-declare the @Produces and @Consumes annotations for the overriding method to be an entity method.

Entity Method Matching

Asset classes are handled by the AssetProvider which is a JAX-RS provider that is capable of consuming and producing all media types.

Reference

For more information on Asset Providers refer to section 7.7 Assets Provider.

Request Entity Matching

The following points describe the process of selecting the asset entity-consuming method to handle the request entity. This process occurs during the invocation of the AssetProvider#isReadable() method.

  1. Collect all the entity-consuming methods of the asset. These are the public methods annotated with @Consumes annotation.
  2. Sort the collected entity-consuming methods in descending order, where methods with more specific media types precede methods with less specific media types, following the rule n/m > n/* > /.
  3. Select the first method that supports the media type of the request entity body as provided to the AssetProvider#isReadable() method, and return true.
  4. If no entity-consuming method supports the media type of the request entity body, return false. The Apache Wink runtime continues searching for a different provider to handle the asset as a regular entity.

Response Entity Matching

The following points describe the process of selecting an entity-producing method to produce the actual response entity. The following process occurs during the invocation of the AssetProvider#isWriteable() method.

  1. Collect all the entity-producing methods of the asset. These are the public methods annotated with @Produces annotation.
  2. Sort the collected entity-producing methods in descending order, where methods with more specific media types precede methods with less specific media types, following the rule n/m > n/* > /.
  3. Select the first method that supports the media type of the response entity body as provided to the AssetProvider#isWriteable()method and return true.
  4.  If no entity-producing method supports the media type of the response entity body, return false. The Apache Wink runtime continues searching for a different provider to handle the asset as a regular entity.

Asset Example

The following example illustrates the use of an asset. The "Defect" bean is a JAXB annotated class.

DefectAsset Class

The DefectAsset class is the asset backed by an instance of a "Defect" bean.

@Asset
public class DefectAsset {
    public Defect defect;
    public DefectAsset(Defect defect) {
        this.defect = defect;
    }
    @Produces("application/xml")
    public Defect getDefect() {
        return this.defect;
    }
    @Produces("text/html")
    public String getDefectAsHtml() {
        String html = ...;
        return html;
    }

    @Produces("application/atom+xml")
    public AtomEntry getDefectAsAtom() {
        AtomEntry entry = ...;
        return entry;
    }
    @Consumes("application/xml")
    public void setDefect(Defect defect) {
        this.defect = defect;
    }
}

DefectResource Class

 The DefectResource class is a resource that is anchored to the URI path "defects/{id}" within the Apache Wink runtime.

@Path("defects/{id}")
public class DefectResource {
    @GET
    public DefectAsset getDefect(@PathParam("id") String id) {
        return new DefectAsset(defects.get(id));
    }
    @PUT
    public DefectAsset updateDefect(DefectAsset defectAsset,
                                    @PathParam("id") String id) {
        defects.put(id, defectAsset.getDefect());
        return defectAsset;
    }
}

Scenario Explanation 1

  1. A client issues an HTTP GET request with a URI="/defects/1" and Accept Header= "application/xm
  2. The Apache Wink runtime analyzes the request and invokes the DefectResource#getDefect() resource method.
  3. The DefectResource#getDefect() resource method creates an instance of DefectAsset and populates it with defect "1" data
  4. The DefectResource#getDefect() resource method returns the DefectAsset instance back to Apache Wink runtim
  5. The Apache Wink runtime analyzes the asset and invokes the DefectAsset#getDefect() entity-producing method to obtain the reference to the "Defect" bean.
  6. The "Defect" bean is serialized by Apache Wink runtime as an XML using the appropriate provider.

Scenario Explanation 2

  1. A Client issues an HTTP GET request with a URI="/defects/1" and Accept Header= "text/html"
  2. The Apache Wink runtime analyzes the request and invokes the DefectResource#getDefect() resource metho
  3. The DefectResource#getDefect() resource method creates an instance of DefectAsset and populates it with defect "1" data.
  4. The DefectResource#getDefect() method returns the populated asset back to the Apache Wink runtime.
  5. The Apache Wink runtime analyzes the asset and invokes the DefectAsset#getDefectAsHtml() entity-producing method in order to obtain the reference to the "Defect" bean.
  6. The "Defect" is serialized by Apache Wink runtime as an HTML using the appropriate provider.

Scenario Explanation 3

  1. A Client issues an HTTP PUT request with a URI="/defects/1" and Accept Header= "text/html"
  2. The Apache Wink runtime analyzes the request and invokes the DefectResource#updateDefect() method with an instance of DefectAsset populated with the request entity.* A DefectAsset is instantiated by the Apache Wink runtime
  3. The DefectAsset#setDefect() entity-consuming method is invoked in order to populate the DefectAsset with the defect data.
  • No labels