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!





Monday, April 5, 2010

Managing Intellij dependencies with Gradle

Here I am once again facing a legacy project in need of some dependency management love, and a general simplification/cleanup of its build process. I have been following the Gradle project for some time and decided to see how it performs. The short answer is very well. I don't want to focus on all the details of building a project with Gradle, but instead look at one very important piece that I've found is often neglected with these build tools: IDE integration.

I am a big fan of Intellij (currently using the latest 9.x), so I was hoping I could easily synchronize my project files with the Gradle build file. This is sort of a make or break feature for me, as having to hand-tune the XML project files every time I want to change a dependency is not practical; doubly so when other developers in the office are making changes to those dependencies and have zero inclination to understand how their project files work. Unfortunately I could find nothing in Intellij or Gradle that would perform this synchronization for me. Fortunately I was able to very easily roll my own!

The XML processing capabilities of Groovy, Intellij's XML based project files, and Gradle's groovy-based dsl form a powerful build trifecta. If you're not already familiar with Gradle then you might want to browse the Build Script Basics. If you're already up to speed let's jump right in:

You can create many different types of libraries in Intellij, but for this we are going to look exclusively at module libraries. They are sets of JARs that are associated to a specific module in your project, and are declared in that module's .iml file. A simplified view of your .iml with a couple of JARs might look something like:




So you can see that in order to setup our Intellij module's dependencies we need to update that orderEntry element. Here is a gradle script that does that. A few dependencies are declared including some maven-style artifacts along with a couple of local directories. These are available in gradle via configurations.compile.asPath. The rest should be pretty straightforward if you are familiar with Gradle and XMLParser.Just execute the intellijSync task and you're good to go!