In this entry, I will present the usage of the new REST adapter using OSB 12C. This adapter is a new feature providing support for RESTful web services; it also supports JSON request and response. One important thing to keep in mind is the internal implementation of the message within OSB is SOAP/XML, there are transformations between JSON and XML during the message processing.
I have deployed a JAX-RS service on the server with the following interfaces and we are going to expose this on OSB.
@PUT
@Path("vip")
@Produces(MediaType.APPLICATION_JSON)
@Consumes({MediaType.APPLICATION_JSON})
public Response putUserVIP(CompoundObject element);
@PUT
@Path("putTest/{year}/{month}/{day}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response complexRest(
CompoundObject obj,
@PathParam("year") int year,
@PathParam("month") int month,
@PathParam("day") int day);
@GET
@Path("getTest/{year}/{month}/{day}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUsers(
@PathParam("year") int year,
@PathParam("month") int month,
@PathParam("day") int day,
@QueryParam("from") int from,
@QueryParam("to") int to,
@QueryParam("orderBy") String orderBy);
@POST
@Path("otherwise/{year}/{month}/{day}")
@Produces("application/json")
public Response otherwise(
@FormParam("name") String name,
@FormParam("id") int id,
@PathParam("year") int year,
@PathParam("month") int month,
@PathParam("day") int day);
The inbound CompoundObject is of the format
{ “key” : “keyname” , “value” : “valuetext” }
The response is in the format
{ “value” : “valuetext” }
Right click on the new project-> Import -> Service Bus Resources -> Resources from URL
Drag the REST adapter to the External Services swim lane.
In the operation bindings, select Add operations based on WADL service and use the wadl just imported.
You will get the warning dialogs and take some time to read it. The warnings are reminders that we need to provide the operations bindings details.
Since the operation bindings are not completed, we need to modify each one and provide the operation details:
For getUsers operation request bindings, we need to provide the mappings between the internal SOAP/XML payload to the URI parameters when it is invoking the outbound call. In this case since this is a GET operation and the values are from the payload in the format of:
$msg.request/<parameter name>
In the Response dialog, we need to provide the schema for the result. Since we do not have the xsd schema defined yet, we are going to use the native format builder to create one for us.
Click on the Define Schema for Native Format icon on the right corner.
The native format builder allows us to define different the schema from various format, here we use JSON.
Let’s use a sample payload and the builder will generate the schema for us.
For the complexRest operation. In the Request tab, since this is a PUT with a JSON payload, the URI parameters cannot be mapped to the same payload. In this case we will use the expression in the following format for the mappings, at runtime, the values can be provided in the outbound variable's user-metadata.
$property.<property name>
For the otherwise operation, we have both template parameter and URL-encoded payload, so the request URI parameters mappings look like this:
Once we completed all the details for every operation, the external business is generated.
We can test the service by right click on the external service and select Run
Next we will create a pipeline, connect the business service and expose the pipeline as REST.
Right click in the Pipeline/Split joins swim lane and select create pipeline and connect the pipeline and RestReference service upon completion.
Note: Do not select expose as proxy service yet.
Right click on the RestPipeline and select expose as REST
You will need to complete the REST bindings for the proxy service similar to the business service. In our example, we just reuse the schemas and mappings created earlier, but you are free to define your own interfaces and schemas.
If you open the pipeline design, you will see the pipeline is just a straight pass through to the back end using the inbound operation for outbound request.
If you try to execute the PUT/POST operation that also has URI parameters (putTest, otherwise), you will receive an error complaining missing parameters. This is because the OSB store those URI parameters in the inbound variable and they need to populate to the outbound variable.
<con:endpoint name="ProxyService$RestfulProject$RestService" xmlns:con="http://www.bea.com/wli/sb/context">
…
<con:transport>
<con:uri>/RestfulProject/RestService</con:uri>
<con:mode>request-response</con:mode>
<con:qualityOfService>best-effort</con:qualityOfService>
<con:request xsi:type="http:HttpRequestMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Accept>application/json</http:Accept>
<http:Content-Type>application/x-www-form-urlencoded</http:Content-Type>
</tran:headers>
<tran:user-metadata name="year" value="2014" xmlns:tran="http://www.bea.com/wli/sb/transports"/>
<tran:user-metadata name="month" value="5" xmlns:tran="http://www.bea.com/wli/sb/transports"/>
<tran:user-metadata name="day" value="6" xmlns:tran="http://www.bea.com/wli/sb/transports"/>
<http:query-parameters/>
</con:request>
...
In order to pass the parameters to the backend web services, we need to insert the meta data if it exists. We will add a IF-THEN action in the request pipeline and if there is any user-meta data presents in the inbound request, we populate them in the outbound request:
IF
fn:exists($inbound/ctx:transport/ctx:request/tp:user-metadata)
THEN INSERT
$inbound/ctx:transport/ctx:request//tp:user-metadata
AS LAST CHILD OF VARIABLE
outbound
XPATH
./ctx:transport/ctx:request
Once its is completed, you can test the external REST service.
In this blog, I showed the basic usage of REST adapter:
JDeveloper projects are here: CodeSampleRestAdapter12c
Next Post