EJB FAQ


Here are answers to some frequently asked questions about how to use Enterprise Java Beans within GlassFish.   Additional resources can be found here.  Please send any follow-up questions/comments to ejb@glassfish.java.net or the GlassFish forum.





EJB Clients


Local EJB Access

       


JNDI names



Testing / Embeddable API




How do I access a Remote EJB component from a stand-alone java client?

Step 1.  Use the no-arg InitialContext() constructor in your code.

The most common problem developers run into is passing specific JNDI bootstrapping properties to InitialContext(args).  Some other vendors require this step but GlassFish does not.   Instead, use the no-arg InitialContext() constructor. 

Step 2.  Pass the global JNDI name of the Remote EJB to InitialContext.lookup()

Stand-alone java clients do not have access to a component naming environment (java:comp/env) or to the @EJB annotation, so they must explicitly use the global JNDI name to lookup the Remote EJB.   (See here for more information on how global JNDI names are assigned to EJB components) Assuming the global JNDI name of the Remote EJB is "FooEJB" :

For Beans with a 3.x Remote Business interface  :

  Foo foo = (Foo) new InitialContext().lookup("FooEJB");

Note that in the EJB 3.x case the result of the lookup can be directly cast to the remote business interface type without using PortableRemoteObject.narrow().  

For EJB 2.1 and earlier session/entity beans :
 
    Object homeObj = new InitialContext().lookup("FooEJB");

  FooHome fooHome = (FooHome)
    PortableRemoteObject.narrow(homeObj,FooHome.class);  

  Foo foo = fooHome.create(...)

Step 3.  Include the appropriate GlassFish .jars in the java client's classpath.

For GlassFish 3.

Include $GLASSFISH_HOME/glassfish/lib/gf-client.jar in the client's classpath. 

E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :

  java -classpath $GLASSFISH_HOME/glassfish/lib/gf-client.jar:/home/user1/myclasses acme.MyClient

Note that the Java EE 6 API classes are automatically included by gf-client.jar so there is no need to explicitly add javaee.jar to the classpath.  gf-client.jar refers to many other .jars from the GlassFish installation directory so it is best to refer to it from within the installation directory itself rather than copying it(and all the other .jars) to another location. 

Note: gf-client.jar is located in $GLASSFISH_HOME/modules/gf-client.jar in GlassFish v3.

For GlassFish v2 and earlier

Include both $GLASSFISH_HOME/lib/appserv-rt.jar and $APS_HOME/lib/javaee.jar in the client's classpath.

E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :

  java -classpath $GLASSFISH_HOME/lib/appserv-rt.jar:$GLASSFISH_HOME/lib/javaee.jar:/home/user1/myclasses acme.MyClient

Note : appserv-rt.jar uses the JAR MANIFEST-CLASSPATH attribute to include other dependent .jars within the lib directory.  When setting your client classpath, it is best to directly refer to the appserv-rt.jar within the app server lib directory rather  than copying it to another location.  If you do copy appserv-rt.jar, you'll need to copy additional .jars such as  appserv-deployment-client.jar and appserv-ext.jar.  The full set of .jars that might be needed by appserv-rt.jar is located in its META-INF/MANIFEST.MF file.  

If your stand-alone client makes use of JMS, you'll also need to add $GLASSFISH_HOME/lib/install/applications/jmsra/imqjmsra.jar, $GLASSFISH_HOME/lib/appserv-admin.jar and $GLASSFISH_HOME/lib/appserv-ws.jar.

If your stand-alone client makes use of the Java Persistence API (e.g. it calls a Remote EJB component that returns a Java Persistence API entity ), you'll also need to add $APS_HOME/lib/toplink-essentials.jar.

Step 4.  Set the server host property, if necessary.

If the stand-alone java client is running on a different host than the server, set the -Dorg.omg.CORBA.ORBInitialHost property when starting the client JVM.  E.g.
java -Dorg.omg.CORBA.ORBInitialHost=com.acme.Host1.  This property defaults to localhost, so it is not necessary to set it if the java client is running on the same machine as the server.

Step 5.  Set the naming service port property, if necessary.

The default naming service port in the app server is 3700.   If the naming service is running on a different port, you'll need to set it via the -Dorg.omg.CORBA.ORBInitialPort property when starting the client JVM.   You can double-check the actual naming service port for a given server instance by looking in the server instace's domain.xml for "orb-listener-1". Alternatively, check the Applications..Configuration..ORB..IIOP Listeners section of the admin GUI for orb-listener-1.  



Is a stand-alone Java client portable?  What's the difference between a stand-alone Java client and an Application Client component?


The Java EE platform defines a component that is specially designed to portably access Java EE services from a JVM running outside of the Application Server.   It is called a Java EE Application Client and has been part of the platform since the first release (J2EE 1.2).   Like all Java EE components it runs within a container provided by the vendor's implementation.  The main advantages of the Application Client are that it's portable and that it allows the developer to use the same programming model for defining and accessing resources as is used within web components and EJB components.  It follows the overall philosophy of the Java EE platform that as much of the "plumbing" or system-level work as possible should be performed by a container instead of being part of the Application code.   That means a guarantee that the no-arg InitialContext constructor will work, that a private component naming context (java:comp/env) is available, and in Java EE 5 that platform annotations and injection are available.  

One of the most common issues faced by developers is how to initialize the naming context within a client that accesses EJB components.   When such a client is *not* written as an Application Client it is referred to as a "stand-alone" java client.  By definition, such stand-alone java clients are not portable, so each vendor defines its own way to bootstrap the naming service. This not only makes it more difficult to code the client but causes problems when moving between Java EE implementations.

Like all Java EE components, there are some additional steps required to achieve the portability offerered by the Application Client.   E.g.,  definining a deployment descriptor, packaging the application client .jar and learning how to run the Application Client container. 

See the following for more details on using Application Clients :

Chapter 22 (Getting Started with EJBs) of the Java EE 5 tutorial

Simple EJB 3.0 session / message-driven bean code examples

Client chapter of our Developer's Guide



How do I access a Remote EJB (3.0 or 2.x) component from a non-Java EE web container like Tomcat or Resin?

Accessing a Remote EJB component from a non-Java EE web container is similar to the stand-alone java client case.    However, the complication is that most Java web servers set the default JNDI name provider for the JVM, which prevents our appserver naming provider from being instantiated when the application uses the no-arg InitialContext() constructor.   The solution is to explicitly instantiate an InitialContext(Hashtable) with the properties for our naming provider, as contained in GlassFish's jndi.properties file.  

Step 1.  Instantiate the InitialContext 

     Properties props = new Properties();

  props.setProperty("java.naming.factory.initial",
                    "com.sun.enterprise.naming.SerialInitContextFactory");

  props.setProperty("java.naming.factory.url.pkgs",
                    "com.sun.enterprise.naming");

  props.setProperty("java.naming.factory.state",
                    "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");


  // optional.  Defaults to localhost.  Only needed if web server is running
  // on a different host than the appserver   
  props.setProperty("
org.omg.CORBA.ORBInitialHost", "localhost");

  // optional.  Defaults to 3700.  Only needed if target orb port is not 3700.
  props.setProperty("
org.omg.CORBA.ORBInitialPort", "3700");

  InitialContext ic = new InitialContext(props);

Step 2.  Use the global JNDI name of the target Remote EJB in the lookup.


EJB 3.x, assuming a global JNDI name of "com.acme.FooRemoteBusiness"

     FooRemoteBusiness foo = (FooRemoteBusiness) ic.lookup("com.acme.FooRemoteBusiness");


EJB 2.x, assuming a global JNDI name of "com.acme.FooHome"

  Object obj = ic.lookup("com.acme.FooHome");

  FooHome fooHome = (FooHome) PortableRemoteObject.narrow(obj, FooHome.class);

Step 3.  Add the necessary appserver code to the web server's classpath.

See step 3 of stand-alone client access for the list of required .jars.  

Step 4.  For EJB 3.0 Remote access, use at least Glassfish V2 or Java EE 5 SDK(SJS AS 9) Update 1. 

Builds from this point on will contain a required bug fix.  
See http://java.net/jira/browse/GLASSFISH-920  for more details.



What if I have multiple instances of the Appserver running and I want to access a Remote EJB component between them?


If the two server instances are part of the same cluster, there is no special mapping needed.   By definition, a cluster is homogeneous, meaning the exact same set of applications is deployed to all instances.   Each server instance has the same entries in its global JNDI namespace, so the target Remote EJB component can always be resolved intra-server.  Therefore, it would never be a good idea to explicitly refer to a Remote EJB component in one server instance in the cluster from a different server instance in the same cluster.

However, if the server instances are either both stand-alone instances or this a cross-cluster access, the only difference is the syntax of the global JNDI name used to resolve the ejb-ref or @EJB.   Since the calling code is running within a Java EE component (web or ejb), it should use the standard Java EE programming model for accessing remote EJB components -- @EJB or ejb-ref + java:comp/env lookup.   The application code and any ejb-ref .xml should remain location transparent so that the mapping to physical EJB component can be changed without affecting any portable code or descriptors.

Follow the steps outlined here , but instead of using an unqualified global JNDI name, use the CORBA interoperable naming syntax :

  corbaname:iiop:<host>:<port>#<global_jndi_name>

E.g., assume we have a web application running in a non-clustered app server instance on host1 that wants to access a Remote Stateless Session bean in an app server instance on host2.  The target Remote EJB component has a global JNDI name of "Foo".

Within the servlet :

  @EJB(name="fooejbref")
  private FooRemote fooRemote;


Within sun-web.xml :

  <ejb-ref>
    <ejb-ref-name>fooejbref</ejb-ref-name>
    <jndi-name>corbaname:iiop:host2:3700#Foo</jndi-name>
  </ejb-ref>




Do I need RMI stubs to access EJBs from my java client?


No. Our implementation uses a feature called "Dynamic RMI-IIOP" that creates any necessary RMI-IIOP stubs at runtime in a way that is completely hidden from the application.   This makes deployment much faster and avoids many of the configuration problems that result from having to add static stubs to your client.   However, Dynamic RMI-IIOP is only enabled when the client is using the naming provider from our server implementation.  If the client is a stand-alone java client, that means following the instructions here or here , or using an Application Client component.   Any explicit use of the CosNaming provider in the client will not be able to use the dynamic RMI-IIOP feature, which is why we don't recommend that approach.  If you must use CosNaming, see here.  



What if I have an existing stand-alone java client that accesses EJB components through the CosNaming JNDI provider ?  How do I get static RMI-IIOP stubs for it?


First, read about Portable Java EE clients and "How To Write a Stand-alone Client".  The best option would be to change the client to an Application Client or to follow our stand-alone java client recommendations.  If that's not possible, you can request that static RMI-IIOP stubs be generated during deployment by using the  --generatermistubs option on the asadmin deploy command.    In this case, the static RMI-IIOP stubs will be placed within the client.jar file.   E.g.

  asadmin deploy --generatermistubs --retrieve /home/user1/clientstubdir  fooapp.ear

After the command executes, the client.jar containing the static RMI-IIOP stubs will be in /home/user1/clientstubdir/fooappClient.jar.

The reason static RMI-IIOP stubs are still needed in this case is that if the CosNaming provider is instantiated, it is not using the client naming provider from our appserver implementation.  It instead uses an ORB from Java SE which does not support dynamic RMI-IIOP.



What is the relationship between @EJB and ejb-ref/ejb-local-ref?


The @EJB annotation and the ejb-ref/ejb-local-ref .xml elements are used to specify the same semantic information.  Specifically, that a Java EE component has a dependency on a local or remote EJB component.  Every @EJB can be translated into an equivalent ejb-ref/ejb-local-ref@EJB is easier to use but it serves the same purpose as ejb-ref/ejb-local-ref.   Here's a table with more details :

@EJB attribute
Description
Default value
ejb-ref equivalent
ejb-local-ref equivalent
name
Unique location within the private component namespace(java:comp/env).  
field-level : <fully-qualified name of declaring class>/<field-name>

method-level : <fully-qualified name of declaring class>/<property name>

class level : name is required.  
ejb-ref-name


ejb-ref-name


beanInterface
For EJB 3.x business interfaces, the Local or Remote business interface of the session bean.

For EJB 2.x, the Home/LocalHome interface of the session/entity bean.
field-level : the type of the declared field.

method-level : the type of the single setter parameter

class level : beanInterface is required.


For EJB 3.x : <remote>

For EJB 2.x :
<home>
For EJB 3.x :
<local>

For EJB 2.x :
<local-home>
beanName
ejb-name (not global JNDI name) of the target ejb component within the application.   This can be used whenever the target ejb component is defined within the same application as the referencing component, regardless of local vs. remote.   The only time it can't be used is if the @EJB refers to a Remote interface (3.x or 2.x) that is defined outside the application.  
Automatically resolved if there is only one EJB component within the application that exposes  the value of beanInterface
ejb-link
ejb-link
lookup

*(Added in EJB 3.1)
Specifies the portable JNDI name of the target EJB component to which this @EJB dependency refers.   This should be used instead of mappedName in cases where an @EJB dependency needs to be resolved to a Remote EJB component defined in a different application.  It can also be used to chain one @EJB dependency to another @EJB dependency.
n/a
lookup-name
lookup-name
mappedName
Specifies the product-specific name of the target Remote EJB component.  For GlassFish, this refers to the global JNDI name of the target Remote EJB component.  

Not applicable for local interfaces because beanName can always be used instead.

*(Should not be used in EJB 3.1.  See lookup instead)
If the target EJB component is defined within the same application and the beanName default applies, no additional mapping is required.

Otherwise, the target global JNDI name will be set to the value of beanInterface
mapped-name
n/a




I have a Remote EJB dependency (@EJB or <ejb-ref>) in my Java EE component.  How do I control which actual target EJB component it refers to?


If the target EJB component is defined within the same application as your referencing component and there is only one target EJB component within the application that exposes the remote interface associated with your EJB dependency, then the mapping will happen automatically.   In this case, there is no need to specify any additional mapping information.

Otherwise, there are 3 ways to map the remote EJB dependency to the target Remote EJB component.  From highest to lowest precedence, they are :

1. Use the sun-specific deployment descriptor


Map the remote EJB dependency to the global JNDI name of the target EJB component within the sun-*.xml {sun-web.xml, sun-application-client.xml, sun-ejb-jar.xml} file corresponding to the module in which the EJB dependency is defined.  

E.g. given a remote EJB dependency defined within a servlet (com.acme.MyServlet) :

  @EJB(name="fooejbref")
  private FooRemote fooRemote;


To map this remote EJB dependency to an EJB comopnent with global JNDI name "Foo" :

Within sun-web.xml :

  <ejb-ref>
    <ejb-ref-name>fooejbref</ejb-ref-name>
    <jndi-name>Foo</jndi-name>
  </ejb-ref>


If the @EJB did not use the name attribute, you would need to refer to the default name of the EJB dependency when specifying the sun-*.xml mapping. E.g. :

  @EJB
  private FooRemote fooRemote;


To map this remote EJB dependency to an EJB component with global JNDI name "Foo" :

Within sun-web.xml :

  <ejb-ref>
    <ejb-ref-name>com.acme.MyServlet/fooRemote</ejb-ref-name>
    <jndi-name>Foo</jndi-name>
  </ejb-ref>

  

2. Use @EJB mappedName or the <ejb-ref>..<mapped-name> element.


For @EJB, specify the global JNDI name of the target EJB component using the mappedName attribute.  E.g.

  @EJB(name="fooejbref", mappedName="Foo")
  private FooRemote fooRemote;


Note that mappedName is completely different than name.  name refers to a location within the private component environment namespace (java:comp/env) that represents this EJB dependency.   mappedName refers to a location within a product-specific global namespace that holds the EJB reference object.

For <ejb-ref>, specify the global JNDI name of the target EJB component using the <mapped-name> element.  E.g.

  <ejb-ref>
    <ejb-ref-name>fooejbref</ejb-ref-name>
    <remote>com.acme.FooRemote</remote>
    <mapped-name>Foo</mapped-name>
  </ejb-ref>


If an @EJB and an <ejb-ref> are defined for the same EJB dependency(meaning @EJB.name equals <ejb-ref>..<ejb-ref-name>) in the same component environment, the values in <ejb-ref> take precedence. 

3. Use @EJB beanName or <ejb-ref>..<ejb-link> element.

beanName and <ejb-link> only apply if the target remote EJB component is defined within the same application as the referencing component.    In this case, the value is the ejb-name of the target bean, not the global JNDI name.  If the target EJB component is defined using ejb-jar.xml, the ejb-name is the value of the <session> or <entity> ejb-name element.  If the target EJB component is defined using annotations, the ejb-name is either the value the @Stateless/@Stateful/@Singleton name attribute or if name was not specified, the unqualified bean class name.  

E.g. , assuming our target EJB component com.acme.FooBean is defined as follows :

  @Stateless
  public class FooBean implements FooRemote { ... }


To map the servlet's EJB dependency using beanName :

  @EJB(name="fooejbref", beanName="FooBean")
  private FooRemote fooRemote;


To map the servlet's EJB dependency using ejb-link :

  <ejb-ref>
    <ejb-ref-name>fooejbref</ejb-ref-name>
    <remote>com.acme.FooRemote</remote>
    <ejb-link>FooBean</ejb-link>
  </ejb-ref>



Note that ejb-name is only guaranteed to be unique within an ejb-jar or .war module.   If there are multiple modules within the .ear that define an EJB component with the same ejb-name, the following beanName/<ejb-link> syntax can be used to explicitly refer to the target EJB component : 

 <relative ejb-jar module uri>#<ejb-name>

E.g., given an application containing ejb1.jar, ejb2.jar, and web1.war, where ejb1.jar and ejb2.jar both define an EJB component with ejb-name FooBean :

To map the servlet's EJB dependency to the EJB component in ejb1.jar using beanName :

  @EJB(name="fooejbref", beanName="ejb1.jar#FooBean")
  private FooRemote fooRemote;


To map the servlet's EJB dependency to the EJB component in ejb1.jar using ejb-link :

  <ejb-ref>
    <ejb-ref-name>fooejbref</ejb-ref-name>
    <remote>com.acme.FooRemote</remote>
    <ejb-link>ejb1.jar#FooBean</ejb-link>
  </ejb-ref>


If an @EJB and an <ejb-ref> are defined for the same EJB dependency(meaning @EJB.name equals <ejb-ref>..<ejb-ref-name>) in the same component environment, the values in <ejb-ref> take precedence. 



I have an EJB component with a Local interface. Can I access it from an Application Client or a stand-alone java client ?


If the EJB component is running within the server, no.  The EJB Local view is an optimized invocation path that uses call-by-reference semantics.   It is only available to web components and EJB components that are part of the same application as the target EJB component.    To access EJB components that are running in the server from an Application Client or stand-alone java client,  you'll need to use either a Remote 3.x Business interface, a 2.x Home interface, or web services.

One alternative, if using GlassFish v3, is to use the EJB 3.1 Embeddable API.  This allows a Java SE program to directly execute EJB components within the same JVM, without using a server process. 



I have an EJB component with a Local interface.  Can I access it from a web component in a different application?


No.  The EJB specification only requires access to an EJB component's local EJB interface from within the same application in the same JVM.    One option is to package the ejb-jar in the same .ear as the .war.   A second option, if using GlassFish v3, is to package the EJB component directly within the .war



How do I access a Local EJB component from a POJO?


Local EJB component access is only portable from within the same application, so the POJO class must be called from a component running within the same application as the target Local EJB component.  Injection is not supported for POJO classes, so the POJO needs to look up the local reference. 

If the application is running within GlassFish v3, it can use the portable global JNDI names defined by the EJB 3.1 specification.   In addition to portable java:global names, there are default portable JNDI names for two other scopes : java:module, and java:app.   An EJB component's java:module JNDI name is visible to any code running within the same module.   An EJB component's java:app JNDI name is visible to any code running within the same application.  

The syntax for each is :

java:module/<bean-name>

java:app/<module-name>/<bean-name>

<module-name> defaults to the unqualified name of the ejb-jar file or .war file in which the EJB component is defined, minus the file extension.   The <module-name> can be explicitly specified using the <module-name> element of the ejb-jar.xml (for ejb-jars) or web.xml(for EJB components defined in .wars). 

<bean-name> corresponds to the session bean's ejb-name.  It defaults to the unqualified name of the session bean class.  It can be explicitly specified using the name attribute of the @Stateless/@Stateful/@Singleton annotation.  Alternatively, if the ejb-jar.xml is being used to define the component, <bean-name> corresponds to the <ejb-name> element of ejb-jar.xml.

So, given :

  @Stateless
  public class FooBean { ... }


A POJO running within the same module as FooBean can lookup an EJB reference to FooBean using :

  FooBean foo = (FooBean) new InitialContext().lookup("java:module/FooBean");

An advantage of the java:module syntax vs. java:global is that the code doing the lookup does not have to know the <app-name> or <module-name> in which it is executing. 

If the application is running in GlassFish v2 or earlier, there are no portable JNDI names for the local EJB view.  In that case the only way for the POJO to acquire an EJB reference is to define a local EJB dependency using @EJB or ejb-local-ref, and then look up that dependency within the private namespace (java:comp/env) of the component within whose scope it is executing.    That can be done using the following steps :

Step 1.  Define the local EJB dependency for the component within whose scope the POJO will execute.


Assume the POJO wants to access a local EJB 3.0 business interface FooLocal from the following EJB component defined within the same application :

  @Stateless
  public class FooBean implements FooLocal { ... }


If the POJO is called from a web application, the java:comp/env namespace is shared by the entire .war.  So, the local EJB dependency can be defined by using an @EJB annotation on any managed class within the .war :

  @EJB(name="fooejbref", beanInterface=FooLocal.class)
  public class MyServlet extends HttpServlet { ... }


Likewise, if the POJO is itself called from an EJB component, the local EJB dependency must be defined within that EJB component.  Unlike the .war case, the component environment (java:comp/env) is private for each EJB component.

  @EJB(name="fooejbref", beanInterface=FooLocal.class)
  @Stateless
  public class BarBean implements BarLocal { ... }



Alternatively, the local EJB dependency can be declared within the standard deployment descriptor corresponding to the component within whose scope the POJO is executing (web.xml / ejb-jar.xml)

    <ejb>
      <ejb-name>BarBean</ejb-name>
      <ejb-class>com.acme.BarBean</ejb-class>
 
       ...

        <ejb-local-ref>
          <ejb-ref-name>fooejbref</ejb-ref-name>
          <local>com.acme.FooLocal</local>
          <ejb-link>FooBean</ejb-link>
        </ejb-local-ref>

   </ejb>

Step 2.  In the POJO code, lookup the local EJB dependency within java:comp/env


   InitialContext ic = new InitialContext();

   FooLocal foo = (FooLocal) ic.lookup("java:comp/env/fooejbref");



Note that if the POJO is called from multiple components, e.g. from both the web application and BarBean, you'll need to define the same local EJB dependency for both calling components so that it is always defined in the currently active component environment when the POJO does its lookup.



Are Global JNDI names portable?  How do I know if my EJB component has a portable JNDI name? 

If the EJB component is a kind of session bean and it is deployed to any implementation supporting EJB 3.1(E.g. GlassFish v3), it will automatically have one or more portable JNDI names defined based on the syntax in the EJB 3.1 specification.  Note that this is true of existing EJB 3.0 and 2.x applications that are deployed to an implementation supporting EJB 3.1.  No code changes are required on the bean class itself in order to have the portable global JNDI name automatically assigned when deployed to an EJB 3.1 container.  See here for EJB 3.1 portable global JNDI name syntax.

Prior to EJB 3.1 (GlassFish v2 and earlier), there were no portable global JNDI names defined by the specification.    See  GlassFish-specific global JNDI name syntax.   

What is the syntax for portable global JNDI names in EJB 3.1?

Per the EJB 3.1 Specification, each session bean is assigned a unique JNDI name within the java:global namespace.  Note that prior to EJB 3.1 / GlassFish v3,  there were no portable JNDI names defined for session beans, so each vendor defined its own syntax.   See here for GlassFish vendor-specific global JNDI name syntax .   

The syntax for portable global session bean JNDI names in EJB 3.1 is :

  java:global[/<app-name>]/<module-name>/<bean-name>

The <app-name> portion is only present if the application is deployed as an .ear file.   In that case, <app-name> defaults to the unqualified name of the .ear file, minus the file extension.   The <app-name> can be explicitly specified using the <app-name> element in application.xml

<module-name> defaults to the unqualified name of the ejb-jar file or .war file in which the EJB component is defined, minus the file extension.   The <module-name> can be explicitly specified using the <module-name> element of the ejb-jar.xml (for ejb-jars) or web.xml(for EJB components defined in .wars). 

<bean-name> corresponds to the session bean's EJB name.  It defaults to the unqualified name of the session bean class.  It can be explicitly specified using the name attribute of the @Stateless/@Stateful/@Singleton annotation.  Alternatively, if the ejb-jar.xml is being used to define the component, <bean-name> corresponds to the <ejb-name> element of ejb-jar.xml.

Given the session bean :

  @Stateless
  public class FooBean implements Foo { ... }


If FooBean is packaged in fooejb.jar and deployed as a stand-alone module, its resulting JNDI name entry is :

    java:global/fooejb/FooBean

If FooBean is packaged in fooejb.jar within fooapp.ear, its resulting global JNDI name entry is :

    java:global/fooapp/fooejb/FooBean

If FooBean is packaged in a stand-alone web module fooweb.war, its resulting global JNDI name is :
 
   java:global/fooweb/FooBean

If FooBean is packaged in fooweb.war within fooapp.ear, its resulting global JNDI name entry is :

   java:global/fooapp/fooweb/FooBean


Also note that the portable java:global syntax is defined for a session bean with a local interface or no-interface view, not just for beans exposing a remote interface.  However, only the names corresponding to remote session beans can be portably looked up from code running outside the application in which the target bean is defined. 

Each portable global JNDI name is printed out to the server.log during deployment. 

Finally, in the advanced case that a session bean exposes more than one client view, e.g. two local business interfaces, the above syntax is extended to include the fully-qualified name of the interface, with a "!" separator character.  The syntax then becomes :

 java:global[/<app-name>]/<module-name>/<bean-name>!<fully-qualified-interface-name>

If one of the multiple client views is a no-interface view, the last portion is the fully-qualified bean class name.

How do I define my own portable global JNDI name?

The EJB 3.1 portable global JNDI names defined by the specification are always registered by the container during deployment.  However, it is possible to define one or more additional user-specified portable JNDI names for the bean using an EJB dependency( @EJB or <ejb-ref>/<ejb-local-ref>).   EJB dependencies in Java EE 6 have been extended to allow the name attribute (or <ejb-ref-name> element)  to specify a name outside of the component-specific(java:comp/env) scope.  That allows a wider selection of code than the component itself to lookup the EJB dependency at a given name.   The prefix of the string assigned to name can be ay one of the following :

For example, to define a Singleton with a user-specified global JNDI name of "java:global/MySingleton" the corresponding code would be :

  @Singleton
  @EJB(name="java:global/MySingleton", beanInterface=SharedRemote.class)
  public class SharedBean implements SharedRemote { ... }


If this Singleton were deployed in a stand-alone ejb-jar called foo.jar, its default portable global JNDI name would be "java:global/foo/SharedBean".  However, it would also be available for lookup at "java:global/MySingleton".  

Also note that there is no requirement that the @EJB dependency be defined on the same bean class as the bean to which it refers.  It could just as easily appear on some other component in the same or different application.

How are GlassFish-specific (non-portable) Global JNDI names assigned to Session beans?  


If using GlassFish v3 (and therefore EJB 3.1) it is best to use the portable Global JNDI names defined by the EJB 3.1 specification, so see here instead.   If you must use GlassFish-specific JNDI names, the syntax is as follows :

First, global JNDI names only apply to Session/Entity beans that have some kind of Remote interface.   If the Session/Entity bean only has some combination of Local interfaces and Web Service interfaces, global JNDI names do not apply.  In that case, any specified global JNDI name will be ignored.

In our J2EE 1.4 implementation (Application Server 8.x) , there is only one way to assign a global JNDI name to a session/entity bean's Remote view :

Map the bean's <ejb-name> to a <jndi-name> within the <ejb> element in sun-ejb-jar.xml.  E.g.

  <sun-ejb-jar>
    <enterprise-beans>
      <ejb>
        <ejb-name>FooBean</ejb-name>
        <jndi-name>FooEJB</jndi-name>
      </ejb>
    </enterprise-beans>
   </sun-ejb-jar>


In our Java EE 5 implementation (GlassFish V2 and earlier, Application Server 9.x) , there are four ways to specify JNDI name for a session/entity bean.  In decreasing order of precedence, they are :

1. Use sun-ejb-jar.xml (Same as above)

2. Specify the bean's global JNDI name using the <mapped-name> element in ejb-jar.xml


  <enterprise-beans>
    <session>
      <ejb-name>FooBean</ejb-name>
      <mapped-name>FooEJB</mapped-name>
      ...
    </session>
  </enterprise-beans>

3. Specify the bean's global JNDI name within the @Stateless/@Stateful mappedName attribute.  E.g.,

  @Stateless(mappedName="FooEJB")
  public class FooBean implements Foo { ... }


4. If no global JNDI name has been specified, a default global JNDI name will be generated according to the following table :

Bean has 2.x Home/Remote interfaces
Total # of 3.0 Remote Business interfaces
default JNDI name
example
No
0
n/a
n/a
Yes
0
fully-qualified name of Home interface
com.acme.FooHome
No
1
fully-qualified name Remote Business interface
com.acme.FooBusiness
No
2 or more
No default -- JNDI name must be specified
n/a
Yes
1 or more
No default -- JNDI name must be specified
n/a




How do I specify the Queue or Topic that a Message Driven Bean should consume from?

In our J2EE 1.4 implementation (Application Server 8.x) :

Map the bean's <ejb-name> to the global JNDI name of the Queue/Topic JMS resource in sun-ejb-jar.xml :

  <sun-ejb-jar>
    <enterprise-beans>
      <ejb>
        <ejb-name>FooMessageBean</ejb-name>
        <jndi-name>jms/NotificationQueue</jndi-name>
      </ejb>
    </enterprise-beans>
  </sun-ejb-jar>


In our Java EE 5 / 6 implementation (Application Server 9.x, GlassFish v2/v3) , there are three ways to do it.  In decreasing order of precedence, they are :

1. Use sun-ejb-jar.xml (Same as above)

2. Specify the global JNDI of the Queue/Topic JMS Resource using the <mapped-name> element in ejb-jar.xml  

  <enterprise-beans>
    <message-driven>
      <ejb-name>FooMessageBean</ejb-name>
      <mapped-name>jms/NotificationQueue</mapped-name>
      ...
    </message-driven>
  </enterprise-beans>

3. Specify the global JNDI name of the Queue/Topic JMS Resource using the @MessageDriven mappedName attribute. 

  @MessageDriven(mappedName="jms/NotificationQueue")
  public class FooMessageBean implements javax.jms.MessageListener { ... }




How do I "unit test" my EJB components?

The EJB 3.1 specification defines a new API called the EJB Embeddable API that allows a Java SE program to execute EJB components within the same JVM.  This provides an easy way to invoke EJB components without needing a separate server process or an independent deployment step.    To use it, you'll need GlassFish v3.  

The Java SE main method is responsible for instantiating the EJB container via the javax.ejb.embeddable.EJBContainer.createEJBContainer() method.   Once this method returns, all EJB components have been initialized.   To lookup EJB references, use a special JNDI context returned from EJBContainer.getContext(), combined with the portable global JNDI names of the target EJB component.    When the program is finished with all use of the EJB components, it should call EJBContainer.close() to shutdown and cleanup the embeddable EJB container instance.   Here's an example :


  EJBContainer ejbC = EJBContainer.createEJBContainer();
 
  FooBean fooRef = (FooBean)
      ejbC.getNamingContext();.lookup("java:global/foo/FooBean");
   
  fooRef.foo();

  ejbC.close();   



Executing the Java SE program that uses the EJB Embeddable API is simple.   The java classpath needs to contain the following :


For example, assume that FooBean.class is packaged in foo.jar and that the main class acme.FooTest is under $HOME/test.   The corresponding java command is  :

  java -classpath  foo.jar:$HOME/test:$GLASSFISH_HOME/lib/embedded/glassfish-embedded-static-shell.jar
acme.FooTest