Developers build their own Unified REST RA by combining the Unified REST RA Core with the API Modules they need for their application. This process, outlined in Rhino REST API Framework Overview, produces a REST RA that can be deployed in Rhino.
Resource Adaptor Components
The diagram below summarizes the relations between supplied and generated components of a Unified REST RA. The generated REST API components (in red) are published by a REST API module. There is a set of components for each REST API the REST RA depends on.
Component | Type | Description |
---|---|---|
REST Common |
library |
Common classes available to all APIs |
RA Plugin SPI |
library |
Classes that define the interface between the Unified REST RA Core and REST API plugins. |
Unified REST RA Core |
jar |
Provides functions common to all REST RAs — HTTP transport, configuration, loading of plugins. |
Unified REST RA |
resource-adaptor |
Generated by an RA Module, embeds the Unified REST RA Core classes and declares dependencies on REST API Modules. |
API Common Types |
library |
Library containing common types generated from the OpenAPI document. |
API Events |
event-jar |
Event jar containing definitions of SLEE events for the API. |
API RA Type |
resource-adaptor-type-jar |
RA Type jar containing definitions of RA interface, events and activities provided to SBBs. |
API RA Plugin |
library |
Implementation of the RA Type; contains code for converting between HTTP messages and SLEE events/method calls. |
The RA Type definition declares the Java interfaces that the RA provides to Rhino applications, and the activities and events that represent API operations. These are the interfaces the SBB developer will use to interact with the REST API (as client or server).
The Unified REST RA can support multiple RA Types, and the SBB developer selects which ones they want to use by configuring RA Type bindings in their SBBs. SBBs can use any of the REST RA’s supported RA Types.
All REST RAs share the same set of configuration properties, so procedures for installing and managing these RAs do not need to be re-learned when dealing with different REST RAs.
Although Rhino 2.5+ does have some support for changing dependencies at runtime, this does not extend to RA Types. The Unified REST RA must be rebuilt from its RA Module, and redeployed when REST APIs are added or changed. |
Resource Adaptor Plugins
The RA plugin is a SLEE library containing generated classes that handle the encoding and decoding of HTTP messages for a particular REST API. Each REST API module generates an RA Plugin module for that REST API. The REST RA can use many RA plugins to support many REST APIs in the same REST RA entity.
RA Plugins perform the following functions:
-
Provide the implementation of the RA Type’s provider interface — e.g. a Java method call representing a client operation must be translated to an outgoing HTTP request. The plugin takes the method arguments and translates them into one or more URL path parameters, query parameters, HTTP headers or HTTP bodies as defined in the OpenAPI document, and instructs the REST RA to send the request
-
An incoming HTTP response to a REST request is translated into a SLEE event containing values from the response.
-
An incoming HTTP request is decoded, with the URL path parameters, query parameters, headers or body validated and turned into a SLEE event object that is fired into the SLEE.
Read JAIN SLEE (JSR 240) to learn more about SLEE libraries |
RA Plugin Discovery
RA Plugins are SLEE library components that the REST RA refers to in its deployment descriptor. This means that all RA Plugins are visible to the RA in its class loader (analogous to class path or library path in standalone programs).
When a Unified REST RA entity is created in the SLEE, the RA uses Java’s ServiceLoader
mechanism to find all available RA Plugins in the class loader.
Each plugin implements an initialization method, which the RA invokes so the plugin can bind itself to the RA and register any necessary handlers.
During initialization, a server plugin registers its "base path" with the RA, i.e. the URL path that all of its operations use.
For example our Pet Store API might have the base path /pets/v1
, and operations use paths such as /pets/v1/user/999
.
The generated RA Plugin knows its base path because it is specified in the OpenAPI document.
If multiple plugins have conflicting base paths, then the REST RA entity creation fails. This could be worked around by putting the conflicting APIs into separate REST RA Modules. |
Routing Incoming Requests
When an HTTP request arrives, the RA must determine which registered plugin should handle the request. The RA routes the request as shown below.
-
The RA’s HTTP transport receives an HTTP request from the network.
-
The RA must locate the correct plugin to handle the request. The RA queries its plugins to find one that has a base path matching the request’s URL. If there is no match, the request will be rejected with a 500 error code. If a plugin matches, the request is passed to the plugin for further processing.
-
The plugin decodes the request, inspecting its URL path and method to find a matching operation in its OpenAPI definition. If no operation matches, the request is rejected. If an operation does match, the request’s parameters (path, query, headers, cookies, body) are decoded according to their OpenAPI definitions.
-
The plugin creates the event object representing the API operation, and determines its
FireableEventType
, which identifies the event to the SLEE. It returns the event and itsFireableEventType
to the RA. -
The RA creates an
IncomingRestActivity
activity and fires the event. The event is delivered to an application SBB which will perform the service logic for the REST operation.
If the plugin could not successfully validate the request (e.g. a required parameter was missing or could not be parsed) then the request is rejected with a 400 (Bad Request) response.
Sending Responses
To make it easier for the SBB to send responses that match the operation’s OpenAPI definition, the plugin’s generated provider interface contains helper methods for creating and sending responses with the required body and headers. Generated REST Request events also include methods for creating and sending associated responses.
Refer to the Rhino REST API Framework Users Guide for more detail on Using REST APIs |
Sending Requests
When acting as a client, an SBB:
-
obtains a REST API interface via the REST RA provider
-
creates a REST request by invokes the method corresponding to the desired REST request
-
sends the request vi the REST API interface
-
The RA provider interface of the REST API RA type defines a API client interface from which API interfaces are obtained. An API interface defines a method for each possible REST API operation supported by the API. The SBB invokes the API method for the REST API operation.
-
The RA plugin’s generated ApiClient implementation creates a new REST request object and sets its path, query string, headers and body from the method arguments, encoded as specified in the operation’s OpenAPI definition.
-
The plugin passes the request object to the RA.
-
The RA creates an
OutgoingRestActivity
activity, on which the SBB will receive the response event. The RA records the plugin asssociated with the activity so it can be invoked later. TheOutgoingRestActivity
is returned to the SBB as the method’s return value, so the SBB can attach to it. -
The RA passes the request to its HTTP transport layer for transmission to the network. This will asynchronously connect to the API server and send the request.
Refer to the Rhino REST API Framework Users Guide for more detail on Using REST APIs |
Receiving Responses
When a response arrives, the RA must determine which RA plugin is going to handle it. The plugin then decodes the response and fires a response event, as described below.
-
The HTTP response is received by the HTTP transport layer and passed up to the RA core.
-
The RA matches the response to the
OutgoingRestActivity
that was responsible for sending the request. -
The RA invokes the associated plugin, passing in the response object.
-
The plugin decodes the response according to its OpenAPI definition, and returns an event object and the
FireableEventType
value for that event. -
The RA fires the event on the
OutgoingRestActivity
. It will be delivered to the calling SBB that attached to the activity when sending the request.