The RestfulObjects viewer implements the Restful Object spec, meaning that it defines a well-defined set of endpoint URLs as resources, and generates a well-defined set of (JSON) representations when these resources are accessed.
By default, the Restful Objects viewer will automatically handle requests and return representations according to the RO spec.
However, its internal architecture provides the ContentNegotiationService SPI to allow alternative representations to be returned based on the standard HTTP
In response, the server uses the
Content-Type header which the client can use to know how to process the returned representation.
Another use case is to support "third party" REST clients over which you have no control. In this scenario you must not naively expose entities through the RO viewer, because over time those entities will inevitably evolve and change their structure. If the entities were exposed directly then those REST clients will break.
Instead you need to create some sort of stable facade over your domain entities, one which you will preserve even if the domain entities change. There are three ways in which you can do this:
first is to solve the problem at the domain layer by defining a regular Apache Isis view model. This is then surfaced by the RO viewer.
If the underlying entities change, then care must be taken to ensure that structure of the view model nevertheless is unchanged.
a second option is to solve the problem at the persistence layer, by defining a (SQL) view in the database. Again this is surfaced by the RO viewer.
If the underlying tables change (as the result of a change in their corresponding domain entities) then the SQL view must be refactored so that it still presents the same structure.
our third option is to solve the problem at the presentation layer, using the
ContentNegotiationServicedescribed in this section.
ContentNegotiationServiceis responsible for inspecting the HTTP
Acceptheader, and use this to select the correct representation to render.
The Apache Isis framework provides three implementations of
ContentNegotiationServicewhich inspects different elements of the HTTP
Acceptheader. One of these implementations,
ContentNegotiationServiceXRoDomainTypewill further delegate down to the companion ContentMappingService service (if configured/available), based on the value of the "x-ro-domain-type" parameter of the header.
A typical implementation of
ContentMappingServicewill convert the domain object into some sort of DTO (data transfer object) as specified by the "x-ro-domaintype". If this DTO is annotated with JAXB or Jackson mappings, then the RO viewer (courtesy of the underlying RestEasy framework) can serialize these directly.
What all that means is that, if the underlying entities change, we are required to update the mappings in the
ContentMappingServiceto map to the same DTOs.
This diagram illustrates the three options available:
Here we focus on implementing a facade at the viewer (presentation) layer:
As noted above, there can be multiple implementations of the ContentNegotiationService, each one handling a particular HTTP
Acceptheader. If the implementation does not recognize the value of the header, if can simply return
The framework provides a number of implementations; an implementation that handles the simplified representation of the Apache Isis profile; an implementation that provides support for the
x-ro-domain-typeparameter, and a default/fallback implementation that returns the representations defined by the RO spec.
The ContentMappingService is used by the implementation of ContentNegotiationService that recognizes the
x-ro-domain-type, its role being to transform a domain object (usually an entity) into some other form (usually a DTO), as specified by the
x-ro-domain-typeparameter. There can be many such implementations, each handling a different target domain type.
This diagram shows how these services collaborate:
Taken together these domain services offer a lot of flexibility in terms of the representations that can be generated from the RestfulObjects viewer.
For further details, see: