Thursday, June 26, 2014

SOA Suite 12c: RESTAdapter: Exposing and testing RESTful services

In my previous two blog posts I have described REST (here) and how the new Oracle SOA Suite 12c REST adapter can be used to call RESTful services (here). I recommend those articles to be read first if you're new to REST in order to better understand this article.

The newly introduced Oracle SOA Suite 12c REST adapter provides options for calling RESTful services but it can also be used to expose RESTful services. These exposed services can use XML or JSON as message exchange format. As described in the previous blog post, JSON support is implemented by implementing NXSD (Native Format Builder schema definition files, more information here) to describe the JSON message and make the transformation to and from XML possible. This XML can then be used as usual by the different components in a composite.


Exposing a RESTful service

In order expose a RESTful interface, the REST adapter provides several options. See the image below. A component or external service can be exposed. An interface can also be defined manually. If you just want to expose an existing service in a RESTful way, it might be better to consider an implementation in the Service Bus or for example custom Java code. If however the service hides a complex orchestration, you can consider using a composite with for example a BPEL component.

Options provided by the REST adapter for exposing a RESTful service
Manual configuration

In this example, I am going to configure the REST adapter manually. This also is the only option I have currently seen for providing an interface returning JSON. As already described in my previous post on the REST adapter, the request can be configured to accept template or query style parameters (see http://www.soapui.org/REST-Testing/understanding-rest-parameters.html for more information on REST parameters). I have created a simple synchronous HelloWorldREST BPEL process similar in functionality to the SOA Suite 11g example I've created a while ago. The SOA Suite 12c example, using the REST adapter, has become a lot less complex and more readable (thus I expect less questions on this one). Since the example is that simple, I will not provide the sample code since it will contribute little. The process consists of a receive (creating a new instance), an assign and a reply. The assign puts 'Hello ' in front of the input.

My REST sample process. Receive, Assign ('Hello '+input), Reply.
Going through the wizard is, as we're used from Oracle, easy enough. Because the low level of complexity, I will not get into much detail here providing many screenshots of it and will mostly describe what you will get once you're done with the configuration and provide some implementation tips.

Since a REST service can have a complex URL, the wizard provides an option to obtain a sample URL for a resource or operation. JSON support by the NXSD framework has already been described in my previous blog post.


The REST adapter wizard allows generation of a sample URL for an operation.
After deployment of the service, things get more interesting. A RESTful service should adhere to several architectural constraints. See my blog post on this here. For example, a REST service should be self-descriptive. How is this accomplished with the REST adapters REST implementation? Actually in several ways.

HTTP OPTIONS

The below screenshots are taken from SOAP UI. SOAP UI is useful for testing the service and generating requests. SOAP UI can also read WADL files and generate sample requests based on that. When the service URL is called with the HTTP OPTIONS verb, valid HTTP verbs are returned. See for more explanation of the HTTP OPTIONS verb http://zacstewart.com/2012/04/14/http-options-method.html. The Java JAX-RS framework also uses the HTTP OPTIONS verb in a similar way.

SOAP UI allows using the HTTP OPTIONS verb to obtain information on a service.
If you allow XML to be returned ('Accept: application/xml' HTTP header, I will get back later on this), you even get a complete WADL.

A complete WADL can be obtained from the REST application.

A WADL is to a REST service what a WSDL is to a SOAP service; an XML description/definition of the service/application. This WADL can be used by for example Java frameworks to automatically generate a client for you (see for example https://wadl.java.net/wadl2java.html). Oracle speeds up development of clients against RESTful services by providing this functionality. Some software vendors who provide a RESTful interface neglect to provide a WADL for their services (it would not be very polite of me to mention examples of them here) making client development a more cumbersome process. Luckily, Oracle values developer productivity.

Enterprise Manager support for WADL's

In the Enterprise Manager test console, you can use the WADL to generate the request. This can be used for JAX-RS / Jersey services but also for our newly generated REST HelloWorld service.

In the Enterprise Manager you can load a WADL and generate a sample request for a REST service
For a newly generated REST enabled composite, this works the same;

You can use the EM test console to parse a WADL and call a RESTful composite
Calling the service using an external client

To be honest, this was the hardest part. My first tries ended in this... (the response didn't look very JSON to me even though I had specified it in the wizard)

Doesn't look like it's returning JSON to me...

I usually use the JDeveloper HTTP analyzer (see for example http://docs.oracle.com/cd/E16162_01/user.1112/e17455/aud_prof_test_apps.htm) to analyze a working request. The HTTP analyzer can be used in two ways. Create a request in JDeveloper and use JDeveloper to test the request or use the HTTP analyzer as a proxy. Using the HTTP analyzer to generate sample requests didn't work well for me (I prefer SOAP UI). Using the HTTP analyzer as proxy allows analyzing traffic (HTTP requests) passing through. For XML webservices it is possible to set an HTTP proxy to pass the request through. Since I already had an example of a composite calling another REST service, I thought I could use that. For composites calling REST services however, I have not found the option to set the proxy server so this didn't appear an option.

This would be a nice location to allow setting a proxy server for the REST request
I tried several things related to the Content-Type. I managed to overwrite it with the JCA property rest.binding.http.Content-Type but that didn't help me getting JSON instead of XML as reply. After some struggling with this, Edwin Biemond suggested that the Accept HTTP header might help. I tried it and it did.

The Accept HTTP header with application/json as value made the service respond JSON
Conclusion

The REST adapter

Although this is the first Oracle SOA 12c release, I'm impressed with what Oracle managed to accomplish with (of course among other things) the REST adapter. It introduces a lot more flexibility for integrating services of different kinds. For example, direct integration with usually Javascript based front-ends becomes a lot easier this way. For classic XML developers, REST and JSON might be a bit getting used to at first. It is a good idea to familiarize yourself with them if you not already have since the architecture and the message exchange format are gaining popularity. JSON is benefiting from the popularity of  Javascript and Javascript frameworks which are commonly used to achieve rich client interfaces (AngularJS for example). JSON is usually easier to use in Javascript and less verbose (requiring less bandwidth to transport) then XML. Using less bandwidth is useful for the communication between mobile devices and backend servers. The constraints which are posed by the REST architectural style, allow loose coupling of client/server, scalability and other feats. These are becoming more and more important as IT landscapes grow in complexity. With this REST and JSON support, Oracle SOA Suite has made an important step forward.

When to use which adapter

If you want to accept plain XML, you should use the HTTP adapter. If you want to accept SOAP, you're better of using the SOAP adapter. Currently I have not yet looked at which adapters can use NXSD to translate XML to a 'native' format. I haven't even mentioned the SocketAdapter yet which can be used to provide more low level communication. When using the SocketAdapter however, you will need to do a bit more yourself such as writing Java (see http://javaoraclesoa.blogspot.nl/2013/01/a-json-helloworld-bpel-process.html) or complex NXSD (see http://javaoraclesoa.blogspot.com/2012/12/receiving-json-requests-in-oracle-bpel.html) to provide functionality.

Food for thought. Exposing a CSV file

I've played with the thought of exposing CSV files created by/based on a REST request. NXSD can be used to describe more then JSON. A CSV file can also be described using an NXSD. When I understood the usage of the Accept HTTP header, I became less enthusiastic about this. Most likely it will not be easy (or even possible without using creative methods) to implement with the REST adapter. The client specifies what it accepts as a response. This allows the REST adapter to provide XML and JSON responses with the same adapter configuration while responding with the right format as the client requests. When however I want to return something which the wizard doesn't allow me to select or the REST Adapter doesn't support by default, the request isn't accepted.

The REST adapter does not allow me to specify whatever MIME-type I want