GlassFish-to-GlassFish Remote EJB Invocation

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:

  1. service-ejb.jar: the components that are to be deployed to the remote GlassFish server
  2. client-ejb.jar: the components that are to be deployed to the local GlassFish server
  3. Client.class: the test application main class that interacts directly with the local GlassFish server
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.class

The 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-domain

 

To 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:

  • Specify it with lookup or mappedName attribute of @EJB annotation, without the need for any XML descriptor files.  But the drawback is you will need to recompile the code when changing to a different remote host, or different target JNDI name.
  • Specify it in ejb-jar.xml with <lookup-name> or <mapped-name> element.  This is handy especially when you already use ejb-jar.xml for other configurations.  The minor downside is you are mixing runtime environment information along with portable application configuration.

The complete project archive zip can be downloaded here.  More resources that may be of help:

Comments:

omg..

<jndi-name>corbaname:iiop:adc6140215.us.oracle.com:

Corba? Really?

Posted by guest on April 20, 2012 at 02:48 AM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Cheng Fang

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today