Distribute Grails with Hazelcast

In this article I will try to integrate two of my favorite technologies: grails and Hazelcast.
(Bias: I am currently working for Hazelcast)
Ruby on Rails gained popularity among people who seeks productivity on web programming.
Java is often criticized on being heavy for rapid development.
But richness of Java community has given birth to flexible and dynamic JVM languages like Groovy.
Grails is somewhat synthesis of power of Java (with the help of Groovy) and productivity of Rails with philosophy “convention over configuration”.
Another technology which amazes me is Hazelcast.
I remember the days which I first meet socket programming, RMI; in university.
And when I first tried the Hazelcast my first reaction is “How can ‘distributing your data over machines’ be so easy?”
Single jar, no dependency, distribute your data over maps, queues, topics…
So I have decided to integrate these two technologies by writing a simple plugin so anyone can easily distribute data over memory by Hazelcast.
I called it hazelgrails and pushed it to GitHub: https://github.com/enesakar/hazelgrails
Here is and introduction to using this plugin.

How to Install Plugin

Run the command:
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>install-plugin hazelgrails

Configuration

You will see hazelcast.xml in conf directory under plugins directory.
You can configure Hazelcast in details.
For available options have a look at:
https://hazelcast.com/docs/2.0/manual/single_html/#Config
To see Hazelcast logs add the following to Config.groovy:
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>info ‘com.hazelcast’
Use Hazelcast as Hibernate 2nd Level Cache
In DataSource.groovy replace the following line in hibernate configuration block.
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>cache.region.factory_class = ‘com.hazelcast.hibernate.HazelcastCacheRegionFactory’
For more details about 2nd level cache configuration have a look at:
https://hazelcast.com/docs/2.0/manual/single_html/#HibernateSecondLevelCache

Test The  Plugin

Create a Grails application and install the plugin. Then create a domain and two controllers.
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>create-domain-class com.hazelgrails.Customer
create-controller com.hazelgrails.Server1
create-controller com.hazelgrails.Server2

As you see, Customer is serializable. Hazelcast requires the objects to be serializable in order to distribute them in cluster.

Now create the war file (command “grails war”) but copy the file with different name (app2.war).
You may deploy the wars into different machines in the same network, or to different servers (Tomcat, Jetty) in same machine or even into the same Tomcat.
For simplicity I have run the current app by “grails run-app” and I have deployed the war to an external Tomcat.
And test them:
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>
http://localhost:9091/TestGrails/server1/index
Output:
Cities:[2:New York, 1:London]
Timestamps:[1333447087796, 1333447112863]
http://localhost:8080/app2/server2/index
Output:
Cities:[2:New York, 1:London]
First customer name:tom, age:20
Timestamps:[1333447087796, 1333447112863]
In practice, if you see the following then you can conclude the nodes formed a cluster succesfully. (you should add “info ‘com.hazelcast’” into Config.groovy)
class=”gmail_quote” style=”border-left-width: 1px; border-left-color: #cccccc; border-left-style: solid; padding-left: 1ex; margin: 0px 0px 0px 0.8ex;”>Members [2] {
Member [127.0.0.1:5701]
Member [127.0.0.1:5702] this
}

Usage Examples

There are two new methods defined for domain classes.
saveHz() method, first persists the domain object (like original save()) then puts it to hazelcast map.
getHz() method tries to find object with given id first in Hazelcast map, if not found then tries to find it in datasource.
Hazelcast create a distributed map for each domain class.
So by using saveHz() and getHz() you can get your objects from distributed memory instead of getting by database operations.
Also by injecting HazelService, you can create Hazelcast instances.
Here the usage examples: