Homepage of Ingo Klöckl
 Home
 Programmieren
 - Toolbox
 - Java
 - PostScript
 - Perl
 - Assembler
 - Links
 - Download
Ingo Klöckl
i.kloeckl@2k-software.de

Declaring JNDI names in JBoss 3.0

This section deals with the JBoss implementation and usage of JNDI, the J2EE lookup system.

Setting context properties

Within a J2EE environment, it is really easy to get the needed initial context by simple calling the constructor:

import javax.naming.*;

InitialContext ctx = new InitialContext();
This is possible, because the required setup is done by JBoss itself. For an external client program, it is not as easy as this, but still quite simple. You need to supply the needed information like the provider URL and the context factory by one of several means:
  • A map, given in the constructor call
  • Properties set in the system properties
  • A properties file found in the class path. Using the first method, you introduce hard-coded environment values in your code (but keep all together):
    import javax.naming.*;
    
    // hard-coded JNDI settings in the application
    Hashtable env = new Hashtable();
    env.put(Context.PROVIDER_URL, "jnp://adrasteia:1099");
    env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
    InitialContext ctx = new InitialContext(env);
    
    The second method uses the -D<name>=<value> command-line specifier to set some of the JNDI values, which are better collected in a properties file. This is what the third method is:
    # file jndi.properties
    # must be found in the class path of JBoss
    java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
    java.naming.provider.url=jnp://adrasteia:1099
    java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
    
    The third way is normally the best, yielding the most decoupling of code and setup.

    JNDI ENCs

    Each application component of a J2EE application has an individual enterprise naming context or ENC, providing space for setup-constants, distributed objects and whatever-you-need. The ENC is got with code like this:

    import javax.naming.*;
    
    InitialContext ctx = new InitialContext();
    Context env = ctx.lookup("java:comp/env");
    
    The ENC is normaly local for each component, but there are different types of ENCs with different visibilities:
    • java:comp is the component-specific indivual ENC. This ENC is what you normally use in your J2EE application.
    • java: is an ENC which is visible only in the JBoss VM. It holds references to objects which are only senseful in the JBoss environment, like data sources or other ressources.
    • The other ENCs are visible from remote client and can hold references to EJB home interfaces.

    Environment entries kept in an ENC

    One usage of the individual ENC is to store setup constants there which can then be looked up by the application component. You specify these settings in the regular files web.xml:

    <web-app>
      <env-entry>
        <description>...</description>
        <env-entry-name>MaxValue<env-entry-name>
        <env-entry-type>java.lang.Float</env-entry-type>
        <env-entry-value>45.4</env-entry-value>
      </env-entry>
    </web-app>
    
    and, analogously, in the file ejb-jar.xml:
    <ejb-jar>
      <enterprise-beans>
        <session>
          <env-entry>
            <description>...</description>
            <env-entry-name>MaxValue<env-entry-name>
            <env-entry-type>java.lang.Float</env-entry-type>
            <env-entry-value>45.4</env-entry-value>
          </env-entry>
        </session>
      </enterprise-beans>
    </ejb-jar>
    
    The name is relative to java:comp/env, so to get the value, your application use the following code fragment:
    import javax.naming.*;
    
    InitialContext ctx = new InitialContext();
    Float oValue = (Float)ctx.lookup("java:comp/env/MaxValue");
    float value = oValue.floatValue();
    
    This is possible for all simple data types, using their java.lang. object wrapper class.

    EJB references

    EJBs and web components may refer to other EJBs, where symbolic names are used within the code. These symbolic names are declared in the two configuration files (web.xml and ejb-jar.xml) nad have to be mapped to the JNDI names of the deployed EJBs, using vendor-specific tools.

    Let's see this in work in the following scenario, wherein an EJB OrderHandler needs references to two other EJBs. It looking them up with code like this:

    import javax.naming.*;
    
    InitialContext ctx = new InitialContext();
    PayCheckerHome pchome = (PayCheckerHome)ctx.lookup("java:comp/env/ejb/Paycheck");
    CatalogHome chome = (CatalogHome)ctx.lookup("java:comp/env/ejb/Catalog");
    
    It does not know (nor need to know) that the pay checker EJB is outside itw own J2EE application! The following gives you a graphical overview about the scenario:
    Application 1
    
    EJB name: OrderHandler   ----------------------------->
    JNDI name: OrderHandler    java:comp/env/ejb/Paycheck
    
      |
      | java:comp/env/ejb/Catalog
      v
    
    EJB name: Catalog
    JNDI name: general/Products
    
    Application 2
    
    EJB name: PayChecker
    JNDI name: general/money/Checker
    
    In this example, the EJBs Catalog and PayChecker are regarded as general utility beans, useful for many applications, and therefore mapped under the general JNDI context. These EJB references are usable by anyone who needs their functionality, even if the caller is outside the VM (see above). Of course, the OrderHandler is generally reachable via JNDI, too, but may be somehow secured to be used only within the application 1.

    To configure this scenario, we have to write ejb-jar.xml files for each application and - to resolve the dependencies - also the files jboss.xml. The latter specifies the JNDI names of the deployed EJBs and can resolve external EJB references as the one to the paychecker EJB.

    For the second application, things are quite easy, so we start with the configuration for this application. We simply have to specify the JNDI name of the deployed paychecker EJB:
    <ejb-jar>
      <enterprise-beans>
        <session>
          <ejb-name>PayChecker</ejb-name>
        </session>
    
      </enterprise-beans>
    </ejb-jar>
    
    <jboss>
      <enterprise-beans>
        <session>
          <ejb-name>PayChecker</ejb-name>
          <jndi-name>general/money/Checker</jndi-name>
        </session>
      </enterprise-beans>
    </jboss>
    
    This is not always a required step, because JBOSS uses the name given in the <ejb-name> element as the JNDI name, if no JNDI name is specified in a jboss.xml file. So if we omitt this file, we simply get JNDI names equals to the ejb names for all deployed EJBs.

    The first application uses the JNDI name of the deployed paychecker to resolve the external reference to this EJB. The reference to the catalog EJB is done internally by the <ejb-link> element (which can only be used for internal references):
    <ejb-jar>
      <enterprise-beans>
        <session>
          <ejb-name>Catalog</ejb-name>
        </session>
    
    
        <session>
          <ejb-name>OrderHandler</ejb-name>
    
    
          <ejb-ref>
            <ejb-ref-name>ejb/Catalog</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            ...
            <ejb-link>Catalog</ejb-link>
          </ejb-ref>
    
          <ejb-ref>
            <ejb-ref-name>ejb/Paycheck</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            ...
            // no ejb-link here, because target EJB 
            // is outside this application
          </ejb-ref>
        </session>
      </enterprise-beans>
    </ejb-jar>
    
    <jboss>
      <enterprise-beans>
        <session>
          <ejb-name>Catalog</ejb-name>
          <jndi-name>general/Products</jndi-name>
        </session>
    
        <session>
          <ejb-name>Orderhandler</ejb-name>
          <jndi-name>Orderhandler</jndi-name>
    
          // nothing required, because target EJB
          // is in the same application and reachable
          // via the ejb-link element
    
    
    
    
          <ejb-ref>
            <ejb-ref-name>ejb/Paycheck</ejb-ref-name>
            <jndi-name>general/money/Checker</jndi-name>
          </ejb-ref>
    
    
    
        </session>
      </enterprise-beans>
    </jboss>
    
    Not that it is superflous to specifiy the JNDI name OrderHandler for the order handler, because it equals the <ejb-name> for this EJB. Also note that the JNDI names may include hosts to include EJBs, running within another VM and host! These JNDI names take the form jnp://neria:1099/general/BetterPayChecker.

    It is also possible for servlets or JSPs to reference EJBs. As with references from EJBs, these hve to be declared in the web.xml file and resolved in jboss-web.xml. If the order handler would be a servlet calling the payment checker EJB and the catalog EJB, these files would look like this:
    <web-app>
      <ejb-ref>
        <ejb-ref-name>ejb/Catalog</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        ...
      </ejb-ref>
    
      <ejb-ref>
        <ejb-ref-name>ejb/Paycheck</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        ...
      </ejb-ref>
    </web-app>
    
    <jboss-web>
      <ejb-ref>
        <ejb-name>ejb/Catalog</ejb-name>
        <jndi-name>general/Products</jndi-name>
      </ejb-ref>
    
    
      <ejb-ref>
        <ejb-name>ejb/Paycheck</ejb-name>
        <jndi-name>general/money/Checker</jndi-name>
      </ejb-ref>
    </jboss-web>
    
    The reference names are relative to java:comp/env, as they are for references from within an EJB.

    Other JNDI targets

    There are other targets for JNDI lookups besides environment entries and EJBs. These include resource factories and pre-build resources like data sources or JMS queues. Examples how JNDI is set up for these objects can be found here for JMS, here for JDBC data sources and here for mail resources.

    Note that there are two types of resource references: references to resource factories like queue or mail factories, specified in the <resource-ref> elements of the descriptor files, and the actual resource objects themselves, like the queues. These are specified in the <resource-env-ref> elements of the descriptor files.

    back to JBoss page

    back to toolbox page