In this post, I will write about how to invoke EJB between 2 distinct GlassFish instances, that is, the 2 GlassFish servers are not in the same cluster. The key to accomplishing this is to correctly specify the physical JNDI name of the target remote EJB, which I will explain in more details with code samples. The following table illustrates the configuration of both the client machine and server machine:
| Client Machine | Server Machine |
OS | Mac OS 10.5.8 | Oracle Enterprise Linux |
GlassFish version | GlassFish 4.0 latest trunk build | GlassFish 3.1 |
Deployed application | client-ejb.jar | service-ejb.jar |
Java SE test program | test.Client | |
This sample app consists of 3 artifacts after it is built:
service-ejb.jar
test/ServiceIF.class
test/ServiceBean.class
client-ejb.jar
test/ClientIF.class
test/ClientBean.class
test/ServiceIF.class
META-INF/glassfish-ejb-jar.xml
Client.classThe following is a simple sequence diagram showing the interaction:
These source code files are as follows:
test/ServiceIF.java
package test;
public interface ServiceIF {
public String hello();
}
test/ServiceBean.java
package test;
import javax.ejb.*;
@Stateless
@Remote(ServiceIF.class)
public class ServiceBean implements ServiceIF {
public String hello() {
return this.toString();
}
}
test/ClientIF.java
package test;
public interface ClientIF {
public String clientHello();
}
test/ClientBean.java
package test;
import javax.ejb.*;
@Stateless
@Remote(ClientIF.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class ClientBean implements ClientIF {
@EJB(name="ejb/ServiceBean")
private ServiceIF serviceBean;
public String clientHello() {
return serviceBean.hello();
}
}META-INF/glassfish-ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd">
<glassfish-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>ClientBean</ejb-name>
<ejb-ref>
<ejb-ref-name>ejb/ServiceBean</ejb-ref-name>
<jndi-name>corbaname:iiop:adc6140215.us.oracle.com:3700#java:global/service-ejb/ServiceBean</jndi-name>
</ejb-ref>
</ejb>
</enterprise-beans>
</glassfish-ejb-jar>
test/Client.java
package test;
import javax.naming.*;
public class Client {
public static void main(String args[]) throws Exception {
InitialContext ic = new InitialContext();
ClientIF clientBean = (ClientIF) ic.lookup(args[0]);
System.out.printf("Result from clientBean.clientHello(): %s%n%n",
clientBean.clientHello());
}
}
To compile all java files:
javac -cp $GLASSFISH_HOME/lib/gf-client.jar test/*java
To package service-ejb.jar, which is to be deployed to the remote server machine:
jar cvf service-ejb.jar test/ServiceIF.class test/ServiceBean.class
To package client-ejb.jar, which is to be deployed to the client machine:
jar cvf client-ejb.jar test/ClientIF.class test/ClientBean.class META-INF/glassfish-ejb-jar.xml test/ServiceIF.class
To deploy service-ejb.jar to the remote GlassFish, you need to first transfer service-ejb.jar file to the remote host with ftp or similar tools, then run the following asadmin command in the remote host:
$ [remote-host] ./asadmin start-domain # if it is not running
$ [remote-host] ./asadmin deploy $HOME/service-ejb.jar
To deploy client-ejb.jar to the local GlassFish:
./asadmin deploy client-ejb.jar
To run the test Client program, passing in the portable global JNDI name of ClientBean as args:
java -cp $GLASSFISH_HOME/lib/gf-client.jar:. test.Client java:global/client-ejb/ClientBean
Apr 18, 2012 9:36:59 AM com.sun.enterprise.v3.server.CommonClassLoaderServiceImpl findDerbyClient
INFO: Cannot find javadb client jar file, derby jdbc driver will not be available by default.
Result from clientBean.clientHello(): test.ServiceBean@335aa
The last line of the above output is the result of invoking ServiceBean EJB deployed to the remote GlassFish server. The INFO message about derby jdbc driver is superfulous and can be ignored for our app.
To undeploy service-ejb from the remote GlassFish, and stop the server:
$[remote-host] ./asadmin undeploy service-ejb
$[remote-host] ./asadmin stop-domainTo undeploy client-ejb from the local GlassFish, and stop the server:
./asadmin undeploy client-ejb./asadmin stop-domain
There are other ways to specifying the JNDI name of the target remote EJB, besides mapping it in glassfish-ejb-jar.xml:
The complete project archive zip can be downloaded here. More resources that may be of help:
omg..
<jndi-name>corbaname:iiop:adc6140215.us.oracle.com:
Corba? Really?