Monday, September 15, 2008

RESTfull Mashup with WSDL 2.0 - WSO2 Mashup Server

I was looking around for REST stuff related to Axis2 and stumbled upon one of Stefan Tilkov’s blog post (An old one at that). In that post Stefan had asked somebody to show a WSDL 2.0 document that describes this RESTfull scenario.

Too bad I didn't come across this back then, but as the saying goes better late than never. WSDL 2.0 can describe this scenario easily and I thought of writing a WSDL 2.0 document for this scenario (I've made one change to the URLS used in the scenario, instead of customer/{id}/orders I've used customerorders/{id}. This is not due to a limitation in WSDL 2.0 but rather the implementation of Axis2).

I put all these details together and built a little Mashup (which I named RESTDemo) that runs on the WSO2 Mashup Server. Of course the WSO2 Mashup Server has the ability to build RESTfull Mashups. In order to make it accessible to others I've uploaded it to Mooshup.com our community site.

Note : I have made some assumptions on how an Order and a Customer will be described. My assumptions is that an Order is described by an id (String), customerID (String), details (String), amount (Double), items (String array). A customer will be described as id (String), name (String), address (String), email (String).

The main objective of putting this Mashup together was to demonstrate that this RESTfull scenario can be described using WSDL 2.0. The WSDL 2.0 for this mashup can be accessed from the Mashup page, you could choose either the annotated view or the raw view.

The all important section in the WSDL is the HTTPBinding , cause this is where all the information for accessing this service via REST lies. Ideally I would have loved to make the content-type (whttp:inputSerialization in WSDL 2.0 terms) of a few of the operations application/x-www-form-urlencoded (WSDL 2.0 defaults it to application/xml) . But unfortunately as of now the Mashup Server does not offer a mechanism to do this. I've already opened a JIRA so that this could be added.

You might also want to try out our RESTfull mashup. Simply goto its tryit page in order to try it out (The tryit page allows you to test your mashup and a drop down at the top allows users to select the endpoint they want to access, in our case we may prefer to choose the HTTPEndpoint cause this is all about REST). Now this is where the benefit of a standard description (WSDL 2.0) for our RESTfull mashup kicks in. The tryit page is auto generated off the WSDL 2.0 doc (It has all the information as to how this mashup can be accessed, let it be SOAP 1.1, SOAP 1.2 or REST). The tryit page invokes the service using a auto generated JavaScript Stub.

Let me now explain as to why I had to change the URL mapping for get all customer orders. Axis2 (Which is what the WSO2 Mashup Server is built on) dispatches to the correct operation (when REST is used) using the http method and the URL of the request (The service is always found using the request URL). Now when we try to figure out the operation the request is headed to we basically do some pattern matching, and thats done against the first constant part we get off the httpLocation. In the scenario given it allows a GET on customer/{id}/orders as well as customer/{id}. Now if I used these two templates as it is, there would have been dispatching issues, hence I decided to change the second template.

This has become quite a long blog post. If you are interested in knowing how WSDL 2.0 can be used to describe RESTfull services stay tuned to my blog. I plan to write more on this topic in the time to come. Also there is a RESTfull services on Axis2 tutorial which is just around the corner.

Note : Mooshup is running the 1.5.1 version of the WSO2 Mashup Server (released before Axis2 1.4.1). There fore its REST URLs are of the format http://mooshup.com/services/keith/RESTDemo.HTTPEndpoint/customer/123, in the next version which will be based on Axis2 1.4.1 the URLs of the form http://mooshup.com/services/keith/RESTDemo/customer/123 would also work.

12 comments:

Jonathan Marsh said...

Very nice! It wasn't totally clear from reading it whether you had written the WSDL 2.0 first and then the mashup or the other way around. The WSO2 Mashup Server generates the WSDL 2.0 from simple annotations in the Javascript, and I see you've used the httpLocation, httpMethod, and safe annotations to generate the appropriate parts of the WSDL - without complicated conceptual mappings. The Mashup Server turns out to be a really easy way to generate WSDL 2.0.

Also, when you choose the HTTPEndpoint, and the operations has an httpMethod of GET I think it's cool that as you fill in the form the try-it also constructs the URI for that particular REST interaction for you. Just clicking on it shows that you can invoke the service from the browser without any intermediate processing done by the try-it.

And a hearty +1 to the value of REST description as demonstrated by the Javascript stub, the try-it, the documentation summary, etc., etc. These are all artifacts that are generally needed with a REST service, and by having WSDL 2.0 available we can build a them automatically.

Keith Chapman said...

I was initially thinking of writing the WSDL 2.0 first, but then realized that writing a mashup will be more useful cause it can demonstrate the practical use of the WSDL 2.0 document. As you have mentioned the JavaScript stub, tryit and documentation can auto generated all because we have a standard description for our service.

Sanjiva Weerawarana said...

Keith, I'd totally turn off the SOAP bindings from this mashup - avoids any feeling that there's SOAP involved this scenario.

If we don't allow that in the mashup server yet then that's another JIRA .. allow the author to turn on/off specific bindings or go with whatever the server does.

Keith Chapman said...

Support for turning off the SOAP Binding completely needs to come from Axis2. I agree that its a nice to have feature. I'll fire up a discussion on this on the Axis2 mailing list.

Once thats in we can make it available to mashup authors.

Keith Chapman said...

Hi,

Nice to see that plenty of people are finding this example useful. And on your question,

Yes the spec does support it. Quoting from what whttp:method can be: "{http method} OPTIONAL. A xs:string, to the Binding Operation component, indicating the value for the HTTP Request Method for this specific Binding Operation."

So it basically can support any standard HTTP request method.

The Primer makes this even clearer by stating: "Which HTTP operation will be used. (GET, PUT, POST, DELETE, and other HTTP operations are supported.)" under the features of the HTTP binding.

And yes WSDL 2.0 because a W3C Recommendation on 26 June 2007.

Subbu Allamaraju said...

Keith - just looking at the demo you put together.

I am a bit confused about the intent of the demo. Is the intent to demonstrate that it is possible to use WSDL 2 for describing a RESTful HTTP web service, or is to demonstrate that it is possible to build a RESTful application using SOAP-based technologies?

In any case, I expected to see the use of uniform interface in your demo, but all I see are POSTs even for idempotent and safe requests such as getting all orders or customers. When I type in an order number that does not exist, and hit cancelOrder, I get a 500 instead of a 404.

Could you clarify?

Keith Chapman said...

Subbu,

The main intent for this demo was to show how the RESTfull service described by Stefan can be described using WSDL 2.0.

If you look at the HTTPBinding section of this wsdl you will notice that getting all orders and customers are exposed over GET. You can get all customers at http://mooshup.com/services/keith/RESTDemo.HTTPEndpoint/customers and all orders at http://mooshup.com/services/keith/RESTDemo.HTTPEndpoint/orders.

Currently the Mashup Server which I used to do this demo does not support throwing custom exceptions. If it was to support that I could have thrown 404 rather than throwing the default 500. If I was do write this service in Java and deploy it on Axis2 I could have done that.

Subbu Allamaraju said...

But looking at the demo (http://mooshup.com/services/keith/RESTDemo?tryit) via Firebug, all I see are POSTs.

Keith Chapman said...

By default the try-it uses the first binding in the WSDL (cause the try-it is generated off the WSDL). In the case of the demo it defaults to SOAP 1.1 hence you would see POST all the time. You could change the binding in use by clicking on the expand to change section at the top left of the page. Change the selected endpoint to HTTPEndpoint (That will use all the REST properties We've exposed).

The try-it does something clever as well. If an operation is exposed over GET and is explicitly marked as safe it will show you the URL that the operation is exposed under.

Subbu Allamaraju said...

Thanks for clarifying, but I find that confusing, particularly for a demo.

Keith Chapman said...

We would provide the facility to turn off the SOAP Bindings completely in a future release of the Mashup Server. This should make things more clear.

BTW the Mashup server runs on top of Apache Axis2. So this goes to show the REST support in Axis2 as well.

Skaldrom Y. Sarg said...

I know, this is maybe a bit necro, but unfortunately the Link to the mooshup-Server is dead.