One of the components generated by the Rhino REST API Framework is a resource adaptor type. This component contains all the service visible classes and interfaces you need to write Rhino TAS - Telecom Application Server based services.
-
A resource adaptor Provider interface for your RA type
-
An
ACIFactory object -
A Client interface for your REST API
-
An API interface for each
tagused in your API specification -
Request and Response Events
-
Model classes and Enums
The following diagram explains the relation between the RA Provider, REST API Client and API interfaces.
Each RA Type defines one provider interface. The resource adaptor is responsible for implementing this interface. The provider defines a factory operation for fetching a Client interface. The Client defines a factory operation per API that the REST API defines.
|
|
Learn about the Rhino REST API Framework Architecture |
|
|
Learn more about Resource Adaptors from JAIN SLEE (JSR 240). |
The following sections explain how to use the classes and interfaces in the REST API resource adaptor type.
Getting a provider and ACI factory
Rhino implements the SBB component environment, and provides it to the instances of the SBB component classes through the JNDI interfaces.
You access a resource adaptor provider object using a JNDI lookup.
For example the PingPongApiServerSbbPart constructor:
Unresolved directive in <stdin> - include::/mnt/volume-01/jenkins/workspace/product/ra/rest-api-framework/release-2.1.x/Docs/rest-api-framework-docs/rest-api-framework-public-docs/rhino-rest-api-framework-users-guide/include/PingPongApiServerSbbPart.java[tag=sbbpart-constructor]
|
|
Review the generated sbb-part superclass as it contains the required annotations and code for obtaining a provider object. |
Getting an API object
The RA provider allows you to create a Client object. For example, the PetstoreApiServerProvider interface is:
public interface PetstoreApiServerProvider {
/**
* Return an API Client instance.
* @param configuration the configuration to use for the instance of the API.
* @return an PetstoreApiServerApiClient instance.
*/
PetstoreApiServerApiClient getApiClient(ApiConfiguration configuration);
}
You get a Client interface by calling getApiClient(), passing an ApiConfiguration object as a parameter.
The ApiConfiguration object defines the configuration to be used with a generated REST API such as the preferred body type
to be used when you create outgoing requests and responses.
|
|
You may call getApiClient() more than once, with different ApiConfiguration objects.
|
The PetstoreApiServerApiClient interface is:
public interface PetstoreApiServerApiClient {
/**
* Return an api object related to the PetsApi API.
* @return an PetsApi instance.
*/
PetsApi getPetsApi();
}
The client interface has one accessor method per tag/API in your OpenAPI Specification.
|
|
Refer to the following examples: |
Deriving API interfaces from an openapi spec
Each API operation may have an associated list of tags.
For example, the List Pets request in the Pet Store API has a tag of Pets.
The OpenAPI SLEE Generator uses tags to:
-
group operations into API interfaces
-
generate an accessor operation per API interface, in the Client interface.
Use tags in your openapi specifications to group related operations together in the generated API.
Model types
The OpenAPI SLEE Generator generates Java classes and Enums from the schemas subsection of the components section of your openapi specification.
|
|
See: Components. |
For example the Pet Store schema defines Pet and Pets, from which OpenAPI SLEE Generator will generate a Pet class.
The generated model types implement Serializable, so can be stored in CMP fields.
|
|
In the future these will also be FastSerializable, for more efficient storage in CMP. |
Creating and Sending requests
Create and send requests by using an API object.
For example, the following NotificationsApi interface, from a call notification REST API, would be used to create and send CallDirectionNotification and CallEventNotification requests.
public interface NotificationApi {
// ...
// Create a RestRequestBuilder for request: CallDirectionNotification
RestRequestBuilder createCallDirectionNotificationRequest(
CallEventNotification callEventNotification);
// Create a RestRequestBuilder for request: CallEventNotification
RestRequestBuilder createCallEventNotificationRequest(
CallEventNotification callEventNotification);
// Send a request
OutgoingRestActivity sendRequest(
RestRequestBuilder requestBuilder) throws IOException;
}
The content-type used is defined in your openapi specification. For example the callDirectionNotification operation is:
/calldirection/notification:
post:
summary: A new Call Direction notification
operationId: callDirectionNotification
tags:
- notification
requestBody:
required: true
description: call direction notification
content:
application/json:
schema:
$ref: "#/components/schemas/CallEventNotification"
If an operation supports JSON or XML encoding, the configured preferredBodyType (from the ApiConfiguration)
dictates which encoding to use.
If no preferredBodyType is specified, then the first JSON-compatible media type, from the list of supported types, is used.
Once the new outgoing request is created, it is sent using the API object’s sendRequest method.
This method returns an OutgoingRestActivity to which the application should attach, so it will receive the associated response.
Creating and Sending responses
There are two methods for creating and sending responses:
-
Create the response by using an API object
-
Create the response from a Request event
Create the response by using an API object
Create and send responses by using an API object.
For example, the Pet Store API PetsApi interface includes the following operations to create responses related to a ShowPetById request:
/**
* Create a {@link RestResponseBuilder} for a _200_Success response, related to a ShowPetById request.
* @param contentTypeStr the desired Content-Type, as a string. If null, the default Content-Type
* will be selected from application/json
* based on the value of {@link com.opencloud.slee.rest.common.ApiOptions#preferredBodyType}
* in the {@link com.opencloud.slee.rest.common.ApiConfiguration}
* @param responseBody a Pet, may be null
*/
RestResponseBuilder createShowPetById_200_SuccessResponse(String contentTypeStr,
Pet responseBody);
/**
* Create a {@link RestResponseBuilder} for a Default response, related to a ShowPetById request.
* @param contentTypeStr the desired Content-Type, as a string. If null, the default Content-Type
* will be selected from application/json
* based on the value of {@link com.opencloud.slee.rest.common.ApiOptions#preferredBodyType}
* in the {@link com.opencloud.slee.rest.common.ApiConfiguration}
* @param responseBody a Error, may be null
*/
RestResponseBuilder createShowPetByIdDefaultResponse(int statusCode,
String contentTypeStr,
Error responseBody);
Once the new outgoing response is created, it is sent using the API object’s sendResponse method.
/**
* Send a response.
* @param responseBuilder the response to be sent.
* @throws IOException if the response could not be built or sent.
*/
void sendResponse(RestResponseBuilder responseBuilder, ActivityContextInterface aci)
throws IOException;
Create the response from a Request event
The generated request event objects include methods for creating the associated responses.
For example, the ShowPetByIdRequest event class includes these methods.
/**
* Create a {@link RestResponseBuilder} for a 200 Success response.
* @param contentTypeStr the desired Content-Type, as a string. If null, the default Content-Type
* will be selected from application/json
* based on the value of {@link com.opencloud.slee.rest.common.ApiOptions#preferredBodyType}
* in the {@link com.opencloud.slee.rest.common.ApiConfiguration}
* @param responseBody a Pet, may be null
*/
public RestResponseBuilder create_200_SuccessResponse(String contentTypeStr,
Pet responseBody)
{
// method implementation not shown
}
/**
* Create a {@link RestResponseBuilder} for a Default response.
* @param contentTypeStr the desired Content-Type, as a string. If null, the default Content-Type
* will be selected from application/json
* based on the value of {@link com.opencloud.slee.rest.common.ApiOptions#preferredBodyType}
* in the {@link com.opencloud.slee.rest.common.ApiConfiguration}
* @param responseBody a Error, may be null
*/
public RestResponseBuilder createDefaultResponse(int statusCode,
String contentTypeStr,
Error responseBody)
{
// method implementation not shown
}
In the following example, process a ShowPetById by querying the Pets DB.
If there exists a Pet corresponding to PetId then create a 200 success response (create_200_SuccessResponse("application/json", toShow)).
Otherwise create a 501 error response.
private void handleShowPetByIdRequest(ShowPetByIdRequest request,
ActivityContextInterface aci) throws IOException
{
final Pet toShow = getPet(request.getPetId());
if (null == toShow) {
tracer.finest("Show pet with id: {} = {}", request.getPetId(), toShow);
final RestResponseBuilder errorResponse = request.createDefaultResponse(
501,"application/json",
new Error().code(501).message("There is no pet with id: " + request.getPetId()));
sendResponse(errorResponse, aci);
}
else {
sendResponse(request.create_200_SuccessResponse("application/json", toShow), aci);
}
}
Once the new outgoing response is created, it is sent using the API object’s sendResponse method.
private void sendResponse(RestResponseBuilder response, ActivityContextInterface aci) {
try { petsApi.sendResponse(response, aci); }
catch (IOException e) {
tracer.finest("Failed to send response. Api = {} , OperationId = {}",
response.getApi(), response.getOperationId(), e);
}
}
