Grails Remoting with Hessian, Burlap and HttpInvoker

Erik Pragt

A short while ago, a collegue and I decided to write an application with Grails and Eclipse RCP. We choose Grails for the ease of development, and Eclipse RCP (in favor of Flex and Plain Old HTML) because we wanted to give our users a solid and native look and feel, for which Eclipse RCP works really well.

Since the Eclipse RCP front-end would actually be a remote front-end, we needed some kind of kind of communication between the client and the server. One of our first idea's was to use XML-RPC, which is pretty well supported in Grails, but it would force us to to do some mapping between our domain and the XML. Since we wanted to use the same domain classes is Eclipse as in Grails (by exporting the Grails domain to external domain jars), we opted for a different approach: Burlap/Hessian.

Burlap / Hessian

Burlap and Hessian are two protocols developed by Caucho. They serve the same purpose, but Burlap is XML, while Hessian is binary. While there is actually no reason the use Burlap, since Hessian is much smaller and thus faster, we choose Burlap, since it's easier to debug (it's plain XML after all). Okay, so there is a reason to pick Burlap after all..

In our Eclipse RCP application, we could use Spring, which has out of the box support for Hessian and Burlap. In Grails, we could use the Grails Remoting plugin, which also has support for Burlap and Hessian (and HttpInvoker and RMI, but more about that later). So, we just needed a little bit of configuration, connect them to each other, and it would work without any problems. Right? Right! In theory, it should work out of the box. In practice, there was Hibernate. And Proxies. And also some bugs....

Hibernate

Grails uses Hibernate. That's not a problem: in fact, it's great! Why re-invent the wheel when there's a powerful framework available? However, there are some issues when using Hibernate in combination with remoting. This is not Grails specific, but it did occur in our application, and since our application was a Grails application, it troubled us! The problem when using Grails, however, is that you might not suspect that all the collections you use are actually Hibernate collections. Normally, in a web application, it doesn't matter: Hibernate collections work like any other collection. When doing remoting, however, things change a little...

ClassNotFoundException for Hibernate Lists

Because you're using Hibernate, and you use remoting, you'll need Hibernate on the client side, because of the Hibernate Collections. Either that, or make copies of the objects yourself. While you're at it, you can make DTO's for it, which provide additional benefits. However, this does impose a lot of extra work (manually copying, extra classes to maintain, etc), so we'd rather not do this.

Lazy initialization exception / Proxies

A simple solution for the above is ofcourse to add to libraries on the client. Maybe not the best solution, but it's a solution anyway. However, when you do have the libraries at the client, you might run into Lazy Initialization Exceptions, because of Hibernate proxies. The easiest way to solve this is to agree on what to fetch, eagerly fetch all entities, and access only those relationships you agreed upon. There is (ofcourse!) a small problem with this approach: by default, Hibernate outer joins fetches 'only' 3 levels deep, but I needed 4. The recommended values are in between 0 and 3, but there isn't a lot of data to transfer, so I've set the hibernate.max_fetch_depth property in Grails to 4. This solved a lot! But, unfortunately, not everything...

Grails Bugs

As it seems, there are a lot of people using Grails to create web applications, but few of them use Grails for anything else, like remoting. There wasn't a lot of information to be found, except for the Wiki, and there was a slight problem: it didn't work. After 2 days of programming, I created more than 5 Jira issues on the remoting subject (see for example here, , or here. Most of the issues were blockers for Hessian and Burlap, or created a lot of noice hiding the real problem. So, after a couple of days without much progress, we had to talk..

Alternatives

After 2 days of remoting issues, we were at a T-junction, were we could either go left or right. Left would mean: look for completely alternative ways to do remoting, like XML-RPC or SOAP, and right would mean: investigate into our 2 alternative remoting options: RMI and HttpInvoker. After some discussion, we decided to give HttpInvoker a last chance: RMI is not firewall friendly, and XML-RPC/SOAP would mean a lot of extra work. And finally, we got some succes!

HttpInvoker

HttpInvoker allowed us to pass our tests! This meant it would be possible to retrieve a single object, a list of objects, and send information to the server! This worked great, all our tested passed! And we lived happily ever after.... or didn't we? I forgot to implement 1 more test: storing a complex object (like a Project class containing two Strings). Something with a ClassNotFoundException, even though we knew our classes were there...*sigh*. As a workaround, we didn't send any complex data, but only Strings, int, etc. I also created this issue here. While our application pretty much worked, it still had the complex object issue, which just didn't feel right. And after a week, our hero arrived: Peter Ledbrook made a patch for the issue, which worked immediately, which was really great!!

Conclusion

Despite all of our problems with Grails, the bugs, the remoting, with everything, it was a great learning experience. When all the bugs are fixed, Grails will make it's promise to be a high-productivity framework really come true. There's really no configuration needed, and when it works, it's great. I would certainly use something like HttpInvoker to do future remoting. It (at the moment) worked the best, can easily pass firewalls and is well supported (in Spring as well as in Grails). And above all, even though there was some frustration with the remoting plugin, it was really fun to develop the application!

Update

While writing this blog, I got some status updates on the rest of the issues, which seems all to be fixed right now! A new version of the plugin is even released! This part of the power of the Grails Community: no framework is 100% correct or bugfree, but it's great that there are people like Peter Ledbrook who care to make Grails even better. Thanks again Peter, your support is great!

Comments (8)

  1. Jawher - Reply

    September 26, 2008 at 12:34 am

    Hi,
    Thanks for sharing this.
    Could you please elaborate on the HttpInvoker section ? What problems exactly did it solve (in comparison with Hessian) ?

    Cheers,
    Jawher

  2. Erik Pragt - Reply

    September 26, 2008 at 9:56 am

    Hi Jawher,

    Thanks for the reaction. One of the problems we encountered problems with Hessian/Burlap when encountering Hibernate Collections. It seems Hessian/Burlap doesn't know how to handle customized serialization for Hibernate Collections. One solution to this would be to copy all collections to new collections (for example you could copy your domain to DTO's for example, and you solve two problems at the same time), but this costs some extra work, so we didn't want to take that path.

    HttpInvoker didn't have these problems, it just worked, probably because HttpInvoker uses Java's own serialization, instead of a custom serialization.

    Also, because of Grails Remoting plugin issues at that time, it was quite hard to see what was working and what wasn't: even when things worked, we got a lot of exceptions.

    So, in short, I would advise to check the new 1.0 version of the remoting plugin, and see what works for you. In the end, if you have only Java (compatible) clients, I would go for HttpInvoker: it's fast, firewall friendly and can serialize all Java objects without problems.

  3. Jawher - Reply

    September 27, 2008 at 2:46 am

    Hi again,
    Thanks Erik for taking the time to answer my request ;)
    This will prove very useful as I'm planning to use Spring Remoting (via Hessian for now) for transferring Hibernate entities.

    Cheers,
    Jawher.

  4. [...] Grails Remoting wiht Hessian, Burlap and HttpInvoker [...]

  5. Jawher - Reply

    October 20, 2008 at 11:15 am

    Hi,
    Erik, I owe you one ! It indeed turned out that Hessian + Hibernate entities are not good friends ... you end up getting very confusing exceptions (especially on the server side).
    Whereas when using Spring Remoting instead, it works like a charm.

    Cheers,
    Jawher

  6. Erik Pragt - Reply

    October 20, 2008 at 11:36 am

    Hi Jawher,

    I'm glad I could help! I already forgot which exceptions I got, but there were indeed many. Normally, when using Grails + Hibernate, this isn't a problem since no remoting is involved, and you won't notice all the proxies and Hibernate specific collections.

    So, when using remoting, I guess the easiest way out is indeed HttpInvoker!

    Cheers,

    Erik Pragt

  7. Peter - Reply

    April 18, 2009 at 11:11 am

    Thanks for this information!
    Especially the suggestion to HttpInvoker.
    And because of your blog I know the difference of all the remoting libraries in one sentence:
    RMI is not firewall friendly, and XML-RPC/SOAP would mean a lot of extra work.

    Great!

  8. Kallin Nagelberg - Reply

    April 27, 2010 at 9:31 pm

    I was recently required to start writing services with RMI instead of RESTful JSON and wrote a tutorial on how to easily support both in Grails: http://techscursions.blogspot.com/2010/04/easy-rmi-services-in-grails-with-json.html . Enjoy!

Add a Comment