Introduction to REST APIs and OpenAPI
What are REST APIs?
REST APIs are used to interconnect systems, over a network, using HTTP.
API requests are represented as HTTP requests The parameters of the API request are encoded using the HTTP method, query parameters, header and cookie values and the request body API responses are represented as HTTP responses The parameters of the API response are encoded using the response status, header and cookie values, and the response body |
|
Read Introduction to REST for a concise overview of REST (REpresentational State Transfer). |
Why are REST APIs of interest?
An increasing number of services provide an HTTP based REST API as an interface to other network elements. REST APIs are prevalent in web-based development. For example there exist REST APIs from YouTube, Google Maps and so on. Many of these REST APIs may have utility within the scope of SS7/IMS/VoLTE services.
Historically, applications running on Rhino TAS, including Sentinel VoLTE, have had to support REST APIs by using the HTTP Resource Adaptor, and manually constructing the appropriate HTTP messages, which is time-consuming and prone to errors.
Alternatively, it is possible to write a dedicated Resource Adaptor (RA) that presents Rhino applications with a clean Java interface to a REST API. Such development is a lot of work, which must be repeated for each REST API that is to be supported. This can result in a proliferation of RAs which are very similar, if each RA only supports one API.
The Rhino REST API Framework provide tools to allow Rhino developers to easily add support for REST APIs in their applications. |
What is OpenAPI?
OpenAPI is a standard for describing REST APIs in a language-independent form. The OpenAPI Specification is maintained by the OpenAPI Initiative, an industry body with members from companies that develop and use REST APIs, including Google, Microsoft and many others. OpenAPI was previously known as Swagger.
An OpenAPI document is a text file (YAML or JSON) that describes the operations that a REST API supports. This document contains detailed information about parameters and types required by the API, and the HTTP requests and responses used by each operation.
This document is the authoritative description of an API, which can be used by developers and automated tools to build services around the API.
Developers describe their REST APIs with the OpenAPI Specification within the Rhino REST API Framework. |
OpenAPI Examples
The OpenAPI YAML excerpt below shows how a typical REST operation may be specified. This operation uses a HTTP GET request, with the path /pet/{petId}
, where {petId}
is an integer, e.g. /pet/1234
. The response will contain JSON or XML content that follows the referenced schema (in another part of the document, not shown here).
paths:
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
An interactive example can be seen at https://editor.swagger.io/. This is a web application that lets users edit their API and see the changes immediately in the generated documentation.
What OpenAPI Enables
The OpenAPI Specification has emerged as the industry standard for describing REST APIs, and this has enabled many tools for generating code and other resources. The problem of "how can my application talk to or implement this REST API" has largely been solved — tools such as openapi-generator can generate client and server code for many languages and frameworks, so getting up and running with a new REST API is a simpler task.
A standard, unambiguous way to describe REST APIs is useful as a form of documentation for the humans that use the API. But the real benefit is the automation from tooling that understands these documents. Tools that support OpenAPI can use these documents to generate clients, servers, tests or documentation for the API.
The OpenAPI document is usually sufficient to completely generate a client implementation. For example, most client generators will turn the above operation into a getPetById(long)
method that applications can call, without knowing about the underlying HTTP requests and responses. This is very powerful and means that REST APIs can be adopted easily when they are specified in OpenAPI.
The server implementation of an API cannot be completely generated as there will be application logic needed to query or update databases or other components, but the skeleton of a server implementation can be generated, with stubs for the developer to fill in the application logic.
The open source openapi-generator tool is commonly used for generating code from OpenAPI documents. It supports many programming languages and frameworks, and can be extended to generate custom code.
The openapi-generator is the basis of the Rhino REST API Framework toolchain for generating Resource Adaptors for use in Rhino TAS - Telecom Application Server. |
Rhino REST API Framework Overview
The aim of the Rhino REST API Framework is to take one or more OpenAPI documents, and generate a fully functional REST Resource Adaptor, with minimal developer effort.
Workflow
The workflow is explained in more detail in Rhino REST API Framework Users Guide, but can be summarised as follows:
-
Write or obtain the OpenAPI document for each REST API that is required.
-
For each API, create an API Module using the Rhino REST API Framework SDK tools.
-
Create an RA Module using the SDK, and add dependencies on the API Modules that the RA should support.
-
Build and publish the API Modules and RA Modules. The RA Module produces a Resource Adaptor that can be deployed in the Rhino TAS.
Apart from editing some build or properties files, no coding is required, and the developer now has a fully functional RA they can use to develop their applications.
How it works
The framework makes use of the popular open source tool openapi-generator. The openapi-generator
tool is implemented in Java, but can generate output for any language. It provides an extension mechanism so that generators for new languages and frameworks can be added. The Rhino REST API Framework includes the OpenAPI SLEE Generator, a Java library that is loaded by openapi-generator
automatically when it is available on the JVM’s classpath.
OpenAPI SLEE Generator
The Rhino REST API Framework provides Ant macros that run openapi-generator
with the necessary command-line options to invoke the OpenAPI SLEE Generator. API Modules include Ant build files to invoke the generator, which can be customized by the SDK user. For example, a user may want to pass additional options to openapi-generator
, or override some default templates.
The OpenAPI SLEE Generator uses "libraries", which is an openapi-generator
term for sets of templates that can be used with the same generator. Each library knows how to generate a particular type of SLEE component. The available libraries are:
Client RA Type |
The Java interface for SLEE applications using the API in a client role. |
---|---|
Server RA Type |
The Java interface for SLEE applications using the API in a server role. |
Client REST RA Plugin |
Extension to the REST RA Core that implements a Client RA Type. |
Server REST RA Plugin |
Extension to the REST RA Core that implements a Server RA Type. |
Client & Server RA Type |
The Java interface for SLEE applications using the API in a client and/or server role. |
Client & Server RA Plugin |
Extension to the REST RA Core that implements a Client & Server RA Type. |
Server SBB Part |
Superclass for an SBB Part that implements event handlers for the request events defined in a Server RA Type. |
Client SBB Part |
Superclass for an SBB Part that implements event handlers for the response events defined in a Client RA Type. |
Ant macros are provided that generate the various component types.
The module packs provided by the framework automatically create the necessary modules and Ant build files for the component types above. It is not necessary to create these build files from scratch. See Rhino REST API Framework Users Guide for more information. |
OpenAPI Support & Limitations
Schema |
OpenAPI documents in OpenAPI v2 and OpenAPI v3 formats are supported. |
---|---|
Callbacks |
OpenAPI v3 Callback Objects are supported. If an API declares callback operations, then the generated server RA Type will have methods so that the server can create and send a request to a client. |
Authentication & Authorization |
Currently the OpenAPI SLEE generator does not generate any code for an operation’s Security Scheme Object. The application must set any required parameters (e.g. API Key) on a request manually. |
REST RA Type Structure
Introduction
The Rhino REST API Framework generates SLEE RA Types from OpenAPI documents. Different OpenAPI documents might produce very different RA Types — this section describes the common structure shared by generated RA Types, and how they are used from an SBB.
For concrete examples we will use a test pet store API from the openapi-generator source code.
The framework can generate an RA Type for a client or server role, or an RA Type that supports both roles. Often an application will only be ever be acting in one role. For example if using an API that is hosted externally, the application does not need to be a server, unless for testing purposes. When creating an API Module, the SDK user can select the roles they need.
Read JAIN SLEE (JSR 240) to learn more about Resource Adaptors and Resource Adaptor Types |
Events
SLEE Events are how SBBs receive input from the outside world. Each REST operation defined in an OpenAPI document will generate SLEE event type definitions for the request and its defined responses. An SBB can then listen for events it is interested in.
Request Events
In a server RA Type, each REST operation maps to a distinct SLEE event type. The event name is derived from the OpenAPI operation’s name. The event vendor and version are specified in the API Module’s api.properties
file. The framework generates an event class (a Java class) containing fields for each parameter in the operation’s OpenAPI definition.
For example, consider this getPetById
operation from the example API:
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
This generates an event class like this:
@SleeEvent(id = @ComponentId(name = "com.example.petstore.api.GetPetByIdRequest",
vendor = "Example", version = "1.0"))
public class GetPetByIdRequest {
public Long getPetId() { ... }
public RestResponseBuilder create_200_SuccessResponse(String contentTypeStr, Pet responseBody) { ... }
public RestResponseBuilder create_400_ClientErrorResponse() { ... }
public RestResponseBuilder create_404_ClientErrorResponse() { ... }
...
}
The SBB developer adds event handler methods for the events they need to implement, for example:
@EventMethod(eventType = @ComponentId(name = "com.example.petstore.api.GetPetByIdRequest",
vendor = "Example", version = "1.0"), initialEvent = true)
public void onGetPetByIdRequest(GetPetByIdRequest event, ActivityContextInterface aci) {
Pet pet = storage.lookupPetById(event.getPetId());
...
}
Response Events
In a client RA Type, each response defined on a REST operation maps to a distinct SLEE event type.
Continuing the addPet
example from above, the response events generated for a client RA Type look like this:
package com.example.petstore.api;
@SleeEvent(id = @ComponentId(name = "com.example.openapi.petstore.api.AddPet_200_SuccessResponse",
vendor = "Example",
version = "1.0.0"))
public class AddPet_200_SuccessResponse {
public RestResponse getResponse() { ... }
public int getStatusCode() { ... }
@Nullable
public Pet getContent() { ... }
...
}
The event class has the appropriate @SleeEvent annotation declaring the SLEE Event Type ID. |
|
The event class name is the camel-cased operation name, concatenated with the response status code and the status code class, "Success". | |
The underlying RestResponse object can be accessed. |
|
The integer status code is accessible. | |
If the OpenAPI response definition has a content definition, the response content can be accessed with the type-safe getContent() method. |
Activities
All generated RA Types share the same activity types, defined in the rest-api-common
SLEE library:
-
com.opencloud.slee.rest.common.IncomingRestActivity
-
com.opencloud.slee.rest.common.OutgoingRestActivity
These activities represent a single REST operation — a request and its response — from the client or server point of view.
When an SBB, acting as a REST client, calls a REST operation method, the REST RA creates an OutgoingRestActivity
object. The SBB attaches to this activity so that it can receive the REST response event. When the response event is processed, the activity automatically ends.
Each incoming request automatically creates a new IncomingRestActivity
object in the REST RA, and the corresponding request event is fired on this activity. This is an initial event, in SLEE terms. The SBB receiving this event can generate a response from this activity object using IncomingRestActivity.createResponse()
. Sending the response automatically ends the activity.
All REST operations are simple request/response pairs, which is why the generated RA Types can share the common activity types. There is no benefit to generating separate activity types for each RA Type.
Any more complicated behaviour, such as sessions that span multiple requests, must be implemented at the application level.
Resource Adaptor Interface
Each generated RA Type has a "provider" interface that is the SBB’s main interface to the Unified REST RA entity running in the SLEE. Like all RAs, the provider interface is accessible in JNDI using the JNDI name that is bound to the RA entities' link name in the SBB deployment descriptor (or its SLEE annotations).
The provider interface contains a method for creating an "ApiClient" instance, which in turn provides access to the methods for the API operations. The ApiClient instance can be configured for different situations, for example using a different URL to reach the API server.
If a REST RA supports several RA Types, each has its own provider interface that can be accessed independently. Multiple RA Types can be used in the same SBB or in separate, unrelated SBBs. This is just a part of the SLEE model.
Provider Interface
Below is an example of a generated provider interface. All generated RA Types will have a similar provider interface, just the type names change.
package com.example.petstore;
public interface PetstoreProvider {
/** * Return an API Client instance. * @param configuration the configuration to use for the instance of the API. * @return a PetstoreApiClient instance. */
PetstoreApiClient getApiClient(ApiConfiguration configuration);
}
The ApiConfiguration
type is a configuration object defined in the rest-api-common
library. The SBB passes in a default or custom ApiConfiguration
in order to configure the ApiClient.
Below is an example of an SBB obtaining the provider and ApiClient in its setSbbContext()
method (where this sort of initialization is normally done).
public abstract class PetstoreSbb implements Sbb {
private PetstoreApiClient apiClient;
@Override
public void setSbbContext(SbbContext context) {
try {
Context env = (Context) new InitialContext().lookup("java:comp/env");
PetstoreProvider provider = (PetStoreProvider) env.lookup("slee/resource/petstore");
final ApiConfiguration petsApiConfig = ApiConfiguration.standardConfiguration();
petsApiConfig.set(ApiOptions.destinationUrl, "https://api.petstore.example.com");
this.apiClient = provider.getApiClient(petsApiConfig);
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
...
}
Now that the SBB has an ApiClient object, it can start invoking operations using the API.
The separate provider and ApiClient interfaces are needed because the SLEE model guarantees there is only ever one instance of PetstoreProvider
, corresponding to the REST RA entity.
The provider allows the SBB to create multiple ApiClient instances, with different configurations such as addresses or credentials. This means the same RA entity can be used by multiple services across a wide range of scenarios.
ApiClient Interface
The ApiClient interface is the SBB’s main entry point for invoking REST operations, as a client, or creating defined REST responses as a server. Readers familiar with OpenAPI may recognize this pattern from other clients generated by openapi-generator.
This interface provides access to various "Api" interfaces, corresponding to the tags in the OpenAPI definition. Tags in OpenAPI are how related operations are grouped together. Our example Pet Store API has the tags "pet", "store", and "user", generating an ApiClient interface like this:
package com.example.petstore;
public interface ExampleApiClient {
/** * Return an api object related to the PetApi API. * @return an PetApi instance. */
PetApi getPetApi();
/** * Return an api object related to the StoreApi API. * @return an StoreApi instance. */
StoreApi getStoreApi();
/** * Return an api object related to the UserApi API. * @return an UserApi instance. */
UserApi getUserApi();
}
And in the generated PetApi
interface:
package com.example.petstore.api;
public interface PetApi {
RestRequestBuilder createAddPetRequest(Pet pet);
RestRequestBuilder createDeletePetRequest(Long petId, String apiKey);
RestRequestBuilder createGetPetByIdRequest(Long petId);
RestRequestBuilder createUpdatePetRequest(Pet pet);
OutgoingRestActivity sendRequest(RestRequestBuilder requestBuilder)
throws IOException;
...
}
The createXXXRequest() methods create a RestRequestBuilder object that is pre-populated with the parameters needed for the corresponding REST operation. Additional parameters and headers may be added if necessary. |
|
The sendRequest() method sends the REST request to the target server configured in the ApiClient. |
Operations without a tag will go into the DefaultApi
interface.
The server-side PetApi
interface has methods for creating the defined responses for each operation. Equivalent methods are available on the request event object as well for convenience.
package com.example.petstore.api;
public interface PetApi {
RestResponseBuilder createAddPet_200_SuccessResponse(String contentTypeStr, Pet responseBody);
RestResponseBuilder createGetPetById_200_SuccessResponse(String contentTypeStr, Pet responseBody);
RestResponseBuilder createGetPetById_400_ClientErrorResponse();
...
void sendResponse(RestResponseBuilder responseBuilder, ActivityContextInterface aci)
throws IOException;
}
The createXXXResponse() methods create a RestResponseBuilder object that is pre-populated with the parameters needed for the corresponding REST response. Additional parameters and headers may be added if necessary. |
|
The sendResponse() method sends the REST response to the client that sent the request. This is determined by the IncomingRestActivity ACI. |
Unified REST RA
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.
Key Concepts and Terms
OpenAPI Document
A YAML or JSON text file conforming to the OpenAPI Specification. Defines the operations supported by a REST API, and the parameters and responses for each operation.
Resource Adaptor Type (RA Type)
An RA Type is a SLEE component that defines the interface between the application (SBBs) and a resource adaptor.
An RA Type contains definitions of:
-
the event types that may be fired by the RA;
-
the activity types created by the RA;
-
the resource adaptor interface. This is a Java interface that SBBs use to invoke methods on the RA.
A single resource adaptor may implement one or more RA Types.
The Rhino REST API Framework generates RA Types from OpenAPI documents, as described in Rhino REST API Framework Overview.
Read JAIN SLEE (JSR 240) to learn more about Resource Adaptors and Resource Adaptor Types |
Module Pack
A module pack is a template used for creating a buildable Ant module (or set of modules) including default source code and build files. A developer can bootstrap a new module in their project by running sdkadm create-module
with the module pack that they want to derive their new module from. The Rhino REST API Framework provides several module packs for creating REST API Modules and RA Modules.
API Module
An Ant/Ivy build module containing a single OpenAPI document, and sub-modules for generating the SLEE and RA components that will implement this API. A module is a directory containing source code, build scripts and dependency information for building an artifact or binary, in our case this is usually one or more Java jar files. These components are published as Ivy artifacts for use by other modules.
New API Modules are created from module packs using SDK tools.
RA Module
An Ant/Ivy build module that depends on the Unified REST RA Core and one or more API Modules. The REST RA Module assembles components from the desired API Modules to produce a single REST RA that supports all of the referenced APIs, and is ready to be used by SLEE applications.
REST RA Modules are created from module packs using SDK tools. Developers may create multiple REST RA Modules, each with different sets of APIs to suit different applications.
RA Plugin
An RA Plugin is a SLEE library, generated by the framework, that provides the implementation of a generated RA Type. The Unified REST RA loads an RA Plugin library for each supported RA Type. The plugin knows how to transform HTTP requests and responses into their corresponding events and operations on the RA Type used by the application. When an API Module is created from the standard module packs, an RA Plugin sub-module is automatically created alongside the RA Type sub-modules.
Unified REST RA Core
A reusable RA component that provides the HTTP transport used by generated APIs. The Unified REST RA Core by itself is not a complete resource adaptor; your RA Module will assemble it with one or more API Modules to create a deployable REST RA supporting those APIs.