Clustering Stateful Session Beans with GlassFish 3.1
Join the DZone community and get the full member experience.
Join For FreeClustering will be the next big topic for the GlassFish 3.1 version. It's right ahead and you can already pick your RC4
build to experiment a bit. There are some screencasts for clustering
the HTTPSession available. Arun Gupta did a great intro for GlassFish 3.1 Clustering, High Availability and Centralized Administration.
So you can get a basic introduction into clustering, nodes, instances
and domains. Up to today the documentation for all those features is
still very limited. But this will change in the next few weeks. Here is,
what I did to get a Stateful Session Bean failover scenario working
with two instances on one node.
Preparation
As always: Get you GlassFish 3.1 RC4 up an running. Create a cluster
(e.g. demoCluster) and add two instances (instance1 and instance2). Now
start your domain and cluster. Write a simple EJB (e.g. MySessionBean)
and make it implement a RemoteInterface (e.g. MySessionBeanRemote). My
example has a simple String showInstance() business method which prints
out the actual running instance:
Logger.getLogger(MySessionBean.class.getName())
.log(Level.INFO, "Running on: {0}",
System.getProperty("com.sun.aas.instanceName"));
Wrap your ejb-jar into an ear and deploy it. Make sure to check the
"Availability" during deployment. This enables in-memory replication
from one instance to the other.
Go and check if the EJB is registered with your instances:
%AS_INSTALL%/bin/asadmin list-jndi-entries demoCluster
You should see something like this:
node2:
java:global: com.sun.enterprise.naming.impl.TransientContext
[...]net.eisele.cluster.MySessionBeanRemote#
net.eisele.cluster.MySessionBeanRemote: javax.naming.Reference
[...]
node1:
java:global: com.sun.enterprise.naming.impl.TransientContext
[...]
net.eisele.cluster.MySessionBeanRemote#
net.eisele.cluster.MySessionBeanRemote: javax.naming.Reference
[...]
Up to now, this hardly was any problem. It's a simple EJB without anything else to tweak. Now let's go and write some clients.
Standalone Client
Coming from the old-school I am starting with a standalone client
without any "magic". Create a Java project (e.g. StandaloneClient), add a
Main class (StandaloneClient) and add the
%AS_INSTALL%/glassfish/lib/gf-client.jar as a dependency. Make sure to
reference the RemoteInterface (MySessionBeanRemote) somehow (Classpath
or copying it to your projects source).
// get a simple no argument constructor InitialContext
InitialContext ic = new InitialContext();
// use the global jndi name as lookup string
String lookup = "java:global/ClusterTestEar/ClusterTestEar-ejb/MySessionBean!net.eisele.cluster.MySessionBeanRemote";
//lookup the jndi name
MySessionBeanRemote myEjb = (MySessionBeanRemote) ic.lookup(lookup);
//call showInstance
myEjb .showInstance();
Everything straight forward. No magic here. Compared with most of the
other application servers it's unusual that you don't either have to
specify any InitialContext properties or even add any cluster magic to
the lookup string. But how does the client know about my instances and
ports? That's simple. you have to specify them as VM Options:
-Dcom.sun.appserv.iiop.endpoints=
127.0.0.1:23701,127.0.0.1:23700
Application Client Container
The youth is probably unhappy about the standalone client. They are used
to some kind of injection and those fancy annotation stuff. Ok. Here we
go. You are calling for the ACC. The easiest way of creating one is to
let your IDE do this. NetBeans generates a great acc project for you. It
also has a main class and you can simply:
// inject you ejb ...
@EJB
private static MySessionBeanRemote myEjb;
[...]
// and use it
myEjb .showInstance();
Great. But here it goes. NetBeans itself does not have any kind of
cluster deployment support, but the ACC project was designed to be
deployed. So, even if you are not in need doing so, the "Run File"
NetBeans command fails. So you have to do this manually. First part is
to Tell the ACC where to find the remote EJB.
If you are not going to write a webstart based scenario (which is
exactly what we are NOT going to do :)), you can simply pick a copy of
the %AS_INSTALL%\domains\clusterdomain\config\sun-acc.xml and put it to
your projects folder. You need to edit it and make it reflect your
instances:
<target-server name="MYNODE" address="localhost" port="23701"/>
<target-server name="MYNODE" address="localhost" port="23700"/>
The %AS_INSTALL%\bin\appclient.bat/sh script is there to help you executing the ACC. Build a jar from your appclient project and run it:
appclient -client %YOUR_DIST_FOLDER%\ClusterAppClient.jar -xml %YOUR_DIST_FOLDER%\sun-acc.xml
Done. Now you have everything working. The new-school and the old-school way of accessing remote EJBs.
Clustering / Failover
Now let's test the failover capabilities. Add a second business method
call to your clients and do anything to make the client pause between
them. Either to automatically continue after a few seconds or on
key-press.
Now let's start the client. It prints out to which instance this client is connected. Assume it tells you something like this:
Running on: instance1
Now switch over to your asadmin console and enter the needed
stop-instance command to shutdown the instance the client is connected
to. In this case:
asadmin> stop-instance instance1
If it is stopped, press a key or wait for the client script to continue.
and see, that the second call is redirected to the second node:
Running on: instance2
Failover works. Perfect :) Thanks to Oracle's Cheng and Tim for answering my questions during research!
Further Reading
Oracle GlassFish Server 3.0.1 Application Development Guide Chapter 11 Developing Java Clients
GlassFish Community EJB FAQ
From http://blog.eisele.net/2011/02/clustering-stateful-session-beans-with.html
Opinions expressed by DZone contributors are their own.
Comments