Tuesday, April 27, 2010

Easy RMI services in Grails with JSON controller

My present client uses a middle-tier services layer to provide data to a front end CMS. Many services were developed here that respond to HTTP requests with JSON text. This has worked well for both front-end developers and QA. Developers simply invoked a JSP tag with a service's URL and were returned an object that could be easily traversed via the JSP EL. It has also become common place for QA to test these services directly through their browser, since the data is easily understandable via a JSON parsing plugin such as JSONView.

For reasons beyond my understanding/control the decision has been made declaring HTTP unfit for transferring our data. I believe there are concerns about I/O overhead but there are likely other reasons. At any rate, in it's place we must use Java RMI. There are some promising numbers comparing HTTP to RMI here, so perhaps it's worthwhile.

Another team here has already started using RMI on their new services, and I was very put off by the implementation I have seen. For quite a while the front-end teams were completely unable to use these services since there was no mechanism in place to deal with redistributing changing classes. Someone managed to whip together some scripts that holds it all together by a thread now, but it isn't pretty. What's worse, every new method requires middle-tier developers to write a custom JSP tag to support the new anemic data container classes being transferred. Of course QA is unable to see the data at all directly from the middle-tier anymore, and must rely on front-end developers finishing their implementations before testing can begin.

I was not thrilled at the prospect of jumping into this mess.

My recent work has involved converting a legacy java project to Grails, and after witnessing the productivity benefits of this framework I knew I wanted to see how I could leverage it to provide the RMI functionality required. The first step involved installing the remoting plugin available here. It made it dead simple to add RMI, Burlap, Hessian or Spring Invoker remoting support to any grails service. All that is needed is to add a static property to the service declaring which protocols you want to expose. This made setting up RMI in my project quite simple, but didn't solve the problems of class distribution and testability inherent to RMI. What I really wanted to do was to provide access to my services via RMI OR HTTP/JSON as in the following diagram:



This way developers and QA can test the services in their browser, and the RMI support is there when it comes time to implement the service call in a JSP.

The only requirement of the services is that they always return data that could be represented in JSON, ie. lists, maps, Strings, and primitives. What's really great is that the only class that will ever need to be distributed to clients is the remoteservice interface, and it's as simple as this:



Our implementation of this service, using the remoting plugin, is also quite simple:



We use the Spring application context to grab the requested service, and some groovy meta-magic to call the desired method with a map of parameters.

Now we just write our service which might look something like:



Now if your client wants to hit this up via RMI all they need to do is write a little code like:



Magic! And if you want to be able to test your services over HTTP here's a little controller for you :



Now you can access the exact same service you hit with RMI before now with HTTP like,
http://localhost:1324/Remoting/execute?service=test&method=testMethod&somevar=xyz&somevar2=abc.

I hope someone finds this useful!





1 comment:

  1. Nice Blog,I feel like all your ideas are incredible! Great job!!!
    I have some information about:

    ASBL Spire
    Phoenix Luxury Park1
    Aspire Ameya
    Pbel City

    ReplyDelete