Skip Headers
Oracle® Containers for J2EE Services Guide
10g (10.1.3.5.0)

Part Number E13975-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

2 Using JNDI

This chapter describes the Java Naming and Directory Interface (JNDI) service as implemented by Oracle Containers for J2EE (OC4J). The chapter focuses on setting up JNDI initial contexts and performing JNDI lookups.

This chapter covers the following topics:

To use the information in this chapter, you should be familiar with the basics of JNDI and the JNDI API. For basic information about JNDI, including tutorials and the API documentation, visit the Sun Microsystems Web site at:

http://java.sun.com/products/jndi/index.html

For more information about the other JNDI classes and methods, see the Javadoc at:

http://java.sun.com/products/jndi/1.2/javadoc/index.html

JNDI Tasks

This chapter discusses the following common JNDI tasks:

What's New

The following OC4J JNDI features and behaviors are new for this release:

Additional Documentation

The How-To documents at the following site provide information about OC4J features, including feature overviews and code excerpts relevant to the feature.

http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html

JNDI Primer

JNDI is a core part of the J2EE specification. JNDI provides naming and directory functionality for J2EE applications and components. JNDI is defined independently of any specific naming or directory service implementation. This enables J2EE applications and components to access different naming and directory services using a single API. Different naming and directory service provider interfaces (SPIs) can be plugged in behind this common API to handle different naming services.

J2EE application developers use JNDI to obtain naming contexts. A naming context enables the application to use J2EE resources, such as data sources, local and remote Enterprise Java Beans (EJBs), and JMS topics and queues.

Creating and Using the Initial Context

The two most frequently used JNDI operations are:

When OC4J starts up, it constructs a JNDI initial context for each application by reading the resource references in each application's deployment descriptor.

Persistence

After the initial configuration, the JNDI namespace for each application is purely memory-based. Additions made to the context at run time are not persisted.

When OC4J is shut down, any bindings made programmatically (by making a call to Context.bind, for example) are no longer available.

Bindings that are specified declaratively through J2EE deployment descriptors are persisted beyond a shutdown of the application server.

Constructing a JNDI Context

OC4J constructs a JNDI context for each application that is deployed in the server. There is always at least one application for an OC4J server, the global application, which is the default parent for each application in a server instance. User applications inherit properties and bindings from the global application and can override property values defined in the global application, specify new values for properties, and define new properties as required. Lookups in a user application's context are made in the following order:

  • First, look in the local application's namespace.

  • If the binding is not found locally, then look for the binding in the parent application.

  • If the binding is not found locally or in the parent application, then one of the following occurs:

    • If global lookup is enabled, then OC4J will attempt to resolve the lookup over all known application contexts currently deployed in the OC4J instance.

    • If global lookup is not enabled (which is the default behavior), then a NameNotFoundException is thrown.

Note:

For information about securing access to JNDI namespaces, see the Oracle Application Server Security Guide.

Enabling Global JNDI Lookups

The Global JNDI feature causes a lookup to be attempted across all known applications in the OC4J instance. If the lookup fails within the current application, the lookup is attempted on each deployed application's context. The first successful lookup of the given name is returned. This feature is disabled by default.

To enable the global JNDI feature:

  1. Using a text editor, open J2EE_HOME/config/server.xml.

  2. Within the <application-server> element, add the global-jndi-lookup-enabled attribute and set it to true:

    <application-server
       global-jndi-lookup-enabled="true">
       ...
    </application-server>
    
  3. Save and close server.xml.

  4. Restart the application server.

Note:

Each resource binding name must be unique across all applications deployed in an OC4J instance. In addition, when a lookup across all applications is performed, the order of applications is not guaranteed. If two applications in the same instance have a binding of the same name pointing to different objects, then a lookup might return an unexpected object.

Classpath Configuration

A target application's classes must be located in the classpath of the application attempting the JNDI lookup. The following options are supported when configuring the classpath:

  • Include the target library as part of an OC4J shared library. This causes OC4J to load the JAR as a system library that is imported by all deployed applications. If finer-grained control of system libraries is desired, you can also deploy the target classes as a named system library, and then explicitly import these into each application.

    Java objects that are non Serializable or non Remote-able (that is Local objects) require the use of shared libraries and must be imported by both the caller and target applications.

    Note:

    For more information on creating Shared Libraries, see the Oracle Containers for J2EE Developer's Guide.
  • Include the target JAR file in the caller's EAR file. Once the target JAR is copied into the caller's EAR file, it can be loaded into the proper classpath in either of the following ways:

    • If the global lookup occurs from within a servlet, then place the target JAR into the WEB-INF/lib directory of the web application file (WAR) that is deployed within this EAR.

    • If the global lookup occurs from within an EJB's business method, then place the target JAR into the calling application's EAR file at the top level. Add the target JAR into the classpath by adding a Class-Path tag in the manifest of the caller's JAR.

      An example of the required manifest file (found in the META-INF directory of the caller's JAR file) follows:

      "Manifest-Version: 1.0
      Class-Path: jndi_globalLookup-ejb2.jar"
      

      The Class-Path line in this example causes the target JAR (jndi_globalLookup-ejb2.jar in this example) to be loaded in the classpath of a calling EJB.

Environment and Constructors

The environment that OC4J uses to construct a JNDI initial context can be found in three places:

  • An environment specified explicitly in a java.util.Hashtable instance passed to the JNDI initial context constructor. ("Example: Application Client Looking Up an EJB" includes an example of this constructor.)

  • System property values, as set either by the OC4J server or by the application container.

  • A jndi.properties file contained in the application EAR file (as part of and application client's JAR file.

The JNDI InitialContext has two constructors. You can use either of the following constructors to create the initial context:

InitialContext()
InitialContext(Hashtable env)

InitialContext()

The InitialContext() constructor creates a Context object using the default context environment. If you use this constructor in an OC4J server-side application, then the application context built by OC4J upon startup is returned. This constructor is typically used in code that runs on the server side, such as JSPs, EJBs, and servlets.

InitialContext(Hashtable env)

The InitialContext(Hashtable env) constructor takes an environment parameter. You normally use this form of the InitialContext constructor in remote client applications, where it is necessary to specify the JNDI environment. The env parameter in this constructor is a java.util.Hashtable that contains properties required by JNDI. Table 2-1 lists these properties, which are defined in the javax.naming.Context interface.

Table 2-1 InitialContext Properties

Property Value Meaning

java.naming.factory.initial

INITIAL_CONTEXT_FACTORY

This property specifies which initial context factory to use when creating a new initial context object. The eligible settings are:

  • oracle.j2ee.rmi.RMIInitialContextFactory

  • oracle.j2ee.naming.ApplicationClientInitialContextFactory

  • oracle.j2ee.iiop.IIOPInitialContextFactory

See the Note following this table for information about deprecated context factories.

java.naming.provider.url

PROVIDER_URL

This property specifies the URL that the client-side JNDI code uses to look up objects on the server. See Table 2-2, "JNDI-Related Environment Properties" for details.

java.naming.security.principal

SECURITY_PRINCIPAL

This property specifies the user name for the current security credentials. Required in application client code to authenticate the client. Not required for server-side code, because the authentication has already been performed.

java.naming.security.credential

SECURITY_CREDENTIALS

This property specifies the password for the current security principal. Required in application client code to authenticate the client. Not required for server-side code, because the authentication has already been performed.


See "Example: Application Client Looking Up an EJB" for a code example that sets these properties and gets a new JNDI initial context.

Note:

The following context factories are deprecated:
  • com.evermind.server.rmi.RMIInitialContextFactory

  • com.evermind.server.ApplicationClientInitialContextFactory

  • com.oracle.iiop.server.IIOPInitialContextFactory

For the new context factory names that replace the deprecated ones, see the java.naming.factory.initial item in Table 2-1, "InitialContext Properties".

Example: Looking Up An EJB

This example shows code to use on the server side in a typical Web or EJB application:

Context ctx = new InitialContext();
HelloHome myhome = (HelloHome) ctx.lookup("java:comp/env/ejb/myEJB");

The first statement creates a new initial context object, using the default environment. The second statement looks up an EJB home interface reference in the application's JNDI tree.

In this case, myEJB is the name of a reference to a session bean that is declared in web.xml (if this code executes in a servlet), or in ejb-jar.xml (if this code executes in an EJB business method). This reference is defined in an <ejb-ref> tag. The EJB reference would then be mapped to an actual JNDI location in either orion-web.xml or orion-ejb-jar.xml, depending on the caller that is executing this code.

For example:

<ejb-ref>
  <ejb-ref-name>ejb/myEJB</ejb-ref-name>
  <ejb-ref-type>Session</ejb-ref-type>
  <home>myEjb.HelloHome</home>
  <remote>myEjb.HelloRemote</remote>
</ejb-ref>

JNDI Contexts and Threads

By default, when you create a JNDI Context with a username and password, a principal or user is bound to a context instance when establishing an initial context with OC4J. Thus, the specified principal or user is used during authentication and access control when looking up a named object in the OC4J namespace, obtaining a reference to a remote object, and invoking operations on the remote object. In this scenario, multiple threads within an application client may share the context.

You can also associate a principal or user with the thread that will perform the work. To do so, create a context with the appropriate principal and credential property values. To disassociate a principal from the thread, close the context.

When a thread is associated with a principal, that principal becomes the default for the thread. If any contexts are subsequently created without principal or credential properties, the principal associated with the thread will remain unchanged.

While it is technically possible to share a single context among multiple threads, passing a context to another thread does not associate the principal used in creating the context with the new thread. The only way to associate a principal with a new thread is to create a new context within that thread. In addition, a context can only be closed within the thread with which it was created. For these reasons, Oracle recommends that all work performed with a given context be handled in the same thread.

A thread may be associated with only one principal at any given time. If multiple contexts are created within a single thread without closing any contexts, the thread will be associated with the principal used in the last context created. Principal information is stored with the thread in a stack. If the last context is closed, the thread becomes associated with the principal used in creating the previous context, and so on.

To enable this feature, set the system property -DAssociateUserToThread=true on the command line. By default, this feature is not enabled (set to false).

Creating Other Vendor Contexts

A client may want to access remote resources that are on a different vendor's server (such as WebLogic server). An initial context can be created using the InitialContext(Hashtable env) constructor and setting the JNDI environment properties to the vendor's required values. However, it is likely that some environment properties will remain set as system-level JNDI properties with the vendor's specific values. If this is the case, subsequent OC4J contexts may fail when creating a context using an InitialContext() no-argument constructor; since, the incorrect system-level properties will be used.

To support this scenario, OC4J provides a URL context factory that ensures an OC4J context never uses a vendor's JNDI environment settings that may still be set as system-level properties. A URL context factory is available for both server-side clients and remote clients.

Enabling the Server-Side URL Context Factory

Server-side clients can enable the URL context factory by setting a server environment property. The URL context factory should be enabled whenever a different vendor's context is used in an application.

To enable the server-side URL context factory:

  1. Stop OC4J.

  2. Using a text editor, open the J2EE_HOME/config/server.xml file.

  3. Add the environment-naming-url-factory-enabled property set to true. For example:

    <application-server ...
       ...
       <environment-naming-url-factory-enabled="true" />
       ...
    </application-server>
    
  4. Restart OC4J.

Enabling the Remote Client URL Context Factory

Remote clients can enable the remote client URL context factory using a JNDI environment property that is specified when creating an initial context. This property should be set if errors occur performing OC4J lookups after a remote client uses another vendor's context.

The following example demonstrates an initial context that specifies the remote URL context factory property:

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"factory_class");
env.put(Context.PROVIDER_URL,"protocol://remote_host:port/app");
env.put(Context.SECURITY_PRINCIPAL,"user");
env.put(Context.SECURITY_CREDENTIALS,"password");
env.put(Context.URL_PKG_PREFIXES, "oracle.j2ee.jndi.client");

Context ctx = new InitialContext(env);

Accessing WebLogic Server Resources

This section demonstrates how OC4J components (server or remote clients) use JNDI to connect to a WebLogic server in order to access resources such as EJBs.

Note:

Interoperability between OC4J and WebLogic servers does not include the following:
  • Transaction propagation – Propagating transaction context objects between servers in a cluster is a proprietary feature. Transactions started in OC4J, for example, will not be propagated to WebLogic during a remote call. The same holds true for transactions started on the WebLogic side.

  • Security Context propagation – Propagating security/identity information between servers in a cluster is also a proprietary feature. This means that security subjects/identities cannot be shared across OC4J and WebLogic.

To access WebLogic resources from OC4J clients:

  1. In your client code, create a WebLogic initial context; then, use the context to lookup and use a resource. For example:

    Hashtable env = new Hashtable();
    env.put("java.naming.factory.initial",
    "weblogic.jndi.WLInitialContextFactory");
    env.put("java.naming.provider.url","t3://host:7001");
    env.put("java.naming.security.principal","user");
    env.put("java.naming.security.credentials","password");
    
    Try {
       Context ctx = new InitialContext(env);
       Object homeObject =
       context.lookup("EmployeeBean");
       //use the EmployeeBean
    }
    catch (NamingException e) {
    // a failure occurred
    }
    finally {
       try {ctx.close();}
       catch (Exception e) {
       // a failure occurred
       }
    
  2. Set the OC4J URL context factory property as described in the preceding sections: "Enabling the Server-Side URL Context Factory" or "Enabling the Remote Client URL Context Factory".

  3. Download oc4j-wls-interop.jar from https://metalink.oracle.com (My Oracle Support) and include it on the classpath of your client. For OC4J server-side clients, this is typically accomplished by adding the JAR file as an OC4J shared library. See "Creating and Managing Shared Libraries" in the Oracle Containers for J2EE Deployment Guide.

  4. Start or deploy the client.

Browsing the JNDI Context

Using the JNDI Browser, you can view the entire JNDI namespace to verify that a given set of objects is actually bound in an application.

The JNDI Browser is available within the Oracle Enterprise Manager 10g Application Server Control Console as follows:

Path to JNDI Browser

OC4J: Home > Administration tab > Task Name: Services > JNDI Browser > Click Go To Task icon > Expand All

To Get JNDI Bindings as a String

You can also get a string representation of the bindings in a JNDI context. This can be useful in debugging.

OC4J: Home > Administration tab > Task Name: System MBean Browser. Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone, JNDIResource > Select application > Operations tab > getBindingsAsString or getBindingsAsXMLString > Invoke

Looking Up Objects from J2EE Application Components

This section describes how to use the JNDI to look up bound objects from J2EE application components, such as servlets, JSP pages, and EJBs.

You can use initial context factories in OC4J to access objects from J2EE application components:

Looking Up Objects In the Same Application

When code is running in a server, it is by definition part of an application. Because the code is part of an application, OC4J establishes defaults for properties that JNDI uses. Application code, such as a servlet or an EJB business method, does not need to provide any property values when constructing a JNDI InitialContext object.

Note:

If your application must look up a remote reference, such as a resource in another J2EE application in the same JVM or a resource external to any J2EE application, then you must use RMIInitialContextFactory or IIOPInitialContextFactory. See "Looking Up Objects in Another Application".

Example: Servlet Looking Up a Data Source

In this example, a servlet retrieves a data source to perform a JDBC operation on a database.

Use the Application Server Control Console to specify data source location. Specify the location in the JNDI Location field of the Create Data Source page. See Chapter 5, "Data Sources".

The servlet's web.xml file defines the following resource:

<resource-ref>
   <description>
      A data source for the database in which
      the EmployeeService enterprise bean will
      record a log of all transactions.
   </description>
   <res-ref-name>jdbc/EmployeeAppDB</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
   <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

The corresponding orion-web.xml mapping is:

<resource-ref-mapping name="jdbc/EmployeeAppDB" location="jdbc/pool/OracleCache" />

The name value is the same as that specified in the <res-ref-name> element in web.xml.

The location value corresponds to the "jndi-name" attribute in the <data-source> element of data-sources.xml.

In this case, the following code in the servlet returns the correct reference to the data source object:

...
try {
  InitialContext ic = new InitialContext();
  ds = (DataSource) ic.lookup("java:comp/env/jdbc/EmployeeAppDB");
  ...
}
catch (NamingException ne) {
  throw new ServletException(ne);
}
...

When looking up objects within the same application, no initial context factory specification is necessary, because OC4J sets appropriate defaults when the application starts. For most lookups within the same application, only the no-args constructor for javax.naming.InitialContext to create an InitialContext is required.

Also, it is not necessary to supply a provider URL in this case, because no URL is required to look up an object contained within the same application or under java:comp/.

Note:

Some versions of the JDK on some platforms automatically set the system property java.naming.factory.url.pkgs to include com.sun.java.*.

Check this property and remove com.sun.java.* if it is present.

Looking Up Objects in Another Application

Use one of the following context factories to access objects in another application, or to access J2EE resources from a standalone java client:

  • oracle.j2ee.rmi.RMIInitialContextFactory

  • oracle.j2ee.iiop.IIOPInitialContextFactory

  • oracle.j2ee.naming.ApplicationClientInitialContextFactory

RMIInitialContextFactory

The RMIInitialContexFactory provides a JNDI context implementation that uses the Oracle Remote Method Invocation (RMI) protocol for distributed lookups. This context factory is used by remote clients, as well as applications that attempt lookups for bindings deployed in other OC4J instances. The JNDI environment properties used by the RMIInitialContextFactory are described in Table 2-2, "JNDI-Related Environment Properties". For information on RMI, see the "Using Remote Method Invocation" chapter.

Example: Servlet Looking Up an EJB Remotely Using RMI

In this example, a servlet accesses an EJB running on another OC4J instance on a different machine. The EJB in this example is the EmployeeBean that is used in the "Example: Application Client Looking Up an EJB".

Here is an excerpt of the servlet code:

Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"oracle.j2ee.rmi.RMIInitialContextFactory");
env.put("java.naming.provider.url","ormi://remotehost/bmpapp");
env.put("java.naming.security.principal","SCOTT");
env.put("java.naming.security.credentials","TIGER");
Context context = new InitialContext(env);
Object homeObject =
context.lookup("EmployeeBean");
Example: Servlet Looking Up an EJB Remotely in a Multiple Instance Environment

When running OC4J within IAS, a remote JNDI service can specify that the request should use the "opmn:ormi" protocol, which allows a client to attempt a lookup without hard-coding the ORMI port information. The OC4J JNDI code contacts the opmn process to determine the proper ORMI port for this IAS install. The lookup is similar to the preceding ORMI example, except that the "java.naming.provider.url" property is set to a URL that begins with "opmn:ormi". Here is an excerpt of the same lookup code, using "opmn:ormi":

Here is an excerpt of the servlet code:

Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"oracle.j2ee.rmi.RMIInitialContextFactory");
env.put("java.naming.provider.url","opmn:ormi://remotehost/bmpapp");
env.put("java.naming.security.principal","SCOTT");
env.put("java.naming.security.credentials","TIGER");
Context context = new InitialContext(env);
Object homeObject =
context.lookup("EmployeeBean");

There are also ways to specify which home instance the "opmn" URL should refer to. For more information on using "opmn", see Using Remote Method Invocation.

IIOPInitial ContextFactory

The IIOPInitialContexFactory provides a JNDI Context implementation that uses the Internet Inter-ORB Protocol (IIOP) for distributed lookups. For information on RMI, see the "Using Remote Method Invocation" chapter.

The conditions under which to use IIOPInitialContextFactory are the same as those for RMIInitialContextFactory except that the remote protocol is IIOP instead of ORMI.

Note:

You can use IIOPInitialContextFactory only for looking up EJBs. The same holds true for using a "corbaname" URL with the ApplicationClientInitialContextFactory.
Example: Servlet Looking Up an EJB Remotely Using IIOP

Here is an example.

Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"oracle.j2ee.iiop.IIOPInitialContextFactory");
env.put("java.naming.provider.url","corbaname::remotehost:PORT_NUMBER#APPLICATION_NAME");
env.put("java.naming.security.principal","SCOTT");
env.put("java.naming.security.credentials","TIGER");
Context context = new InitialContext(env);
Object homeObject =
context.lookup("EmployeeBean");

In this example, a corbaname URL is used to specify the location of the EJB. In the corbaname string, PORT_NUMBER is the IIOP port number that OC4J is configured to use, remotehost is the name of the server that OC4J is running on, and APPLICATION_NAME is the name of the application that contains the EJB.

The application used in this example must be deployed with IIOP enabled for this lookup to succeed. The remote client must also include the IIOP client jar generated by OC4J. For more information on this, see the OC4J IIOP documentation at "Switching from ORMI to IIOP Transport".

Looking Up Objects from J2EE Application Clients

This section discusses how to configure an application client to access objects running inside an OC4J instance. For complete instructions on using the OC4J application client container, see Chapter 9, "Using The Application Client Container".

When an application client looks up a resource that is available in a remote J2EE server application, the client uses the ApplicationClientInitialContextFactory in the oracle.j2ee.naming package to construct the initial context.

Note:

If your application is a J2EE application client (that is, it has an application-client.xml file), then you must always use ApplicationClientInitialContextFactory regardless of the protocol (ORMI or IIOP) that the client application is using. The protocol itself is specified by the JNDI property java.naming.provider.url. See Table 2-2, "JNDI-Related Environment Properties" for details.

Remote and local access of components is essentially the same from the point of view of the remote client. Clients can use ORMI or IIOP, depending on the provider URL.

Consider an application client that consists of Java code that connects to an OC4J server. For example, the client code is running on a workstation and might connect to a server object, such as an EJB, to perform some application task. In this case, the remote client must specify the value of the property java.naming.factory.initial as "oracle.j2ee.naming.ApplicationClientInitialContextFactory". This can be specified in client code, or it can be specified in the jndi.properties file that is part of the application client's JAR file.

To get access to remote objects, ApplicationClientInitialContextFactory may utilize resource injection using annotations or may read the META-INF/application-client.xml file and the META-INF/orion-application-client.xml file. Both files are located in the application client's JAR file.

Environment Properties

If the ORMI protocol is being used, then ApplicationClientInitialContextFactory reads the properties listed in Table 2-2 from the environment.

Table 2-2 JNDI-Related Environment Properties

Property Meaning

dedicated.rmicontext

This property is no longer used by OC4J. This property was used for two reasons:

  • To enable load balancing.

  • As a workaround for known ORMI/JNDI bugs.

To enable client-side ORMI load-balancing, please use the properties described in the "Load Balancing" section.

The properties described in the "Load Balancing" section can be used in the few cases that would still require this flag.

java.naming.provider.url

This property specifies the URL to use when looking for local or remote objects. The format is either

[opmn:|http:|https:]ormi://hostname/appname

or

corbaname:hostname:port

For details on the corbaname URL, see "Specifying the corbaname URL" .

You can supply multiple hosts (for failover) in a comma-delimited list when using the ORMI protocol.

java.naming.factory.url.pkgs

Some versions of the JDK on some platforms automatically set the system property java.naming.factory.url.pkgs to include com.sun.java.*.

Check this property and remove com.sun.java.* if it is present.

Context.SECURITY_PRINCIPAL

This property specifies the user name and is required in client-side code to authenticate the client. It is not required for server-side code because authentication has already been performed. This property name is also defined as java.naming.security.principal.

Context.SECURITY_CREDENTIAL

This property specifies the password and is required in client-side code to authenticate the client. It is not required for server-side code because authentication has already been performed. This property name is also defined as java.naming.security.credentials.


Load Balancing

In situations where heavy request volume is expected, load balancing of requests across OC4J instances may be desired. Load balancing is configurable using the oracle.j2ee.rmi.loadBalance property, which can be set in the client's jndi.properties file or in a Hashtable in the client code. The values for this the oracle.j2ee.rmi.loadBalance property are outlined in the following table.

Table 2-3 oracle.j2ee.rmi.loadBalance Property Values

Value Description

client

If specified, the client interacts with the OC4J process that was initially chosen at the first lookup for the entire conversation.

context

Used for a Web client (servlet or JSP) that will access EJBs in a clustered OC4J environment.

If specified, a new Context object for a randomly-selected OC4J instance will be returned each time InitialContext() is invoked.

lookup

Used for a standalone client that will access EJBs in a clustered OC4J environment.

If specified, a new Context object for a randomly-selected OC4J instance will be created each time the client calls Context.lookup().


For more information on load balancing see "Configuring ORMI Request Load Balancing".

Example: Application Client Looking Up an EJB

This section shows how to configure an application client to access an EJB running inside an OC4J instance.

First, the EJB is deployed into OC4J. with the name EmployeeBean. The name is defined as follows in ejb-jar.xml:

<ejb-jar>
  <display-name>bmpapp</display-name>
  <description>
     An EJB app containing only one Bean Managed Persistence Entity Bean
  </description>
  <enterprise-beans>
     <entity>
        <description>no description</description>
        <display-name>EmployeeBean</display-name>
        <ejb-name>EmployeeBean</ejb-name>
        <home>bmpapp.EmployeeHome</home>
        <remote>bmpapp.Employee</remote>
        <ejb-class>bmpapp.EmployeeBean</ejb-class>
        <persistence-type>Bean</persistence-type>
        ...
     </entity>
  </enterprise-beans>
..
</ejb-jar>

The EJB EmployeeBean is bound to the JNDI location bmpapp/EmployeeBean in orion-ejb-jar.xml as follows:

<orion-ejb-jar>
   <enterprise-beans>
       <entity-deployment name="EmployeeBean"
           location="bmpapp/EmployeeBean" table="EMP">
                        ...
       </entity-deployment>
                        ...
   </enterprise-beans>
           ...
</orion-ejb-jar>

The application client program uses the EmployeeBean EJB, and refers to it as EmployeeBean.

An excerpt from the application client program demonstrates the use of an annotation in an application client's main class to request resource injection as well as the use of the JNDI API:

Using Annotations

public class Client {
   @EJB
      private static EmployeeHome home;
      public  static void main(String[] args) {


       // Create a new record.
       Employee rec = home.create(empNo, empName, salary);

       // call method on the EJB
       rec.doSomething();
       ...
   }

Using the JNDI API

public static void main (String args[])
{
 ...
 Context context = new InitialContext();
 /**
  * Look up the EmployeeHome object. The reference is retrieved from the
  * application environment naming context (java:comp/env). The ejb reference is
  * specified in the assembly descriptor (META-INF/application-client.xml).
  */
 Object homeObject =
     context.lookup("java:comp/env/EmployeeBean");
 // Narrow the reference to an EmployeeHome.
 EmployeeHome home =
     (EmployeeHome) PortableRemoteObject.narrow(homeObject,
                                                EmployeeHome.class);
 // Create a new record.
 Employee rec = home.create(empNo, empName, salary);
 // call method on the EJB
 rec.doSomething();
 ...
}

Note that we are not passing a hash table when creating a context in the line:

Context context = new InitialContext();

This is because the context is created with values read from the jndi.properties file, which in this example contains:

java.naming.factory.initial=    oracle.j2ee.naming.ApplicationClientInitialContextFactory
java.naming.provider.url=ormi://localhost/bmpapp
java.naming.security.principal=SCOTT
java.naming.security.credentials=TIGER

Alternatively, you can pass a hash table to the constructor of InitialContext instead of supplying a jndi.properties file. The code looks like this:

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,    "oracle.j2ee.naming.ApplicationClientInitialContextFactory");
env.put("java.naming.provider.url","ormi://localhost/bmpapp");
env.put("java.naming.security.principal","SCOTT");
env.put("java.naming.security.credentials","TIGER");
Context initial = new InitialContext(env);

Because the application client code refers to the EmployeeBean EJB, you must declare this in the <ejb-ref> element in the application-client.xml file:

<application-client>
   <display-name>EmployeeBean</display-name>
   <ejb-ref>
       <ejb-ref-name>EmployeeBean</ejb-ref-name>
       <ejb-ref-type>Entity</ejb-ref-type>
       <home>bmpapp.EmployeeHome</home>
       <remote>bmpapp.Employee</remote>
   </ejb-ref>
</application-client>

Recall that the EmployeeBean EJB is bound to the JNDI location bmpapp/EmployeeBean as configured in the orion-ejb-jar.xml file. You must map the EJB reference name used in the application client program to the JNDI location where the EJB is actually bound to in orion-ejb-jar.xml. Do this in the orion-application-client.xml file:

orion-application-client.xml file:
<orion-application-client>
   <ejb-ref-mapping name="EmployeeBean" location="bmpapp/EmployeeBean" />
</orion-application-client>

For details on the application-client.xml file and the orion-application-client.xml file, see Oracle Containers for J2EE Developer's Guide, Appendix A, OC4J-Specific Deployment Descriptors.

Example: Application Client Looking Up an EJB Using IIOP

In the previous example, the application client used ORMI as the underlying protocol for remote lookups of resources. Alternatively, you can configure the application client to use IIOP as the remote protocol. The code for looking up the EmployeeBean is the same as the previous example, with the following differences:

The jndi.properties file must be changed to reflect the fact that IIOP is being used as the remote protocol. This is configured in the java.naming.provider.url system property in jndi.properties. The following is the jndi.properties file for the same example, configured to use IIOP:

java.naming.factory.initial=    oracle.j2ee.naming.ApplicationClientInitialContextFactory
java.naming.provider.url=corbaname::REMOTE_HOST:IIOP_PORT#bmpapp
java.naming.security.principal=SCOTT
java.naming.security.credentials=TIGER

Alternatively, you can pass a hash table to the constructor of InitialContext instead of supplying a jndi.properties file to use IIOP as the underlying protocol. The code looks like this:

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "oracle.j2ee.naming.ApplicationClientInitialContextFactory");
env.put("java.naming.provider.url","corbaname::REMOTE_HOST:IIOP_PORT#bmpapp");
env.put("java.naming.security.principal","SCOTT");
env.put("java.naming.security.credentials","TIGER");
Context initial = new InitialContext(env);

If an application client sets the JNDI properties through a hash table, as shown in this example, the security credentials must be set as system properties. The IIOP interceptors require access to the client's credentials through system properties. This is achieved automatically when using the jndi.properties file, since the JNDI framework automatically sets these properties as system properties.

If the properties are set in the code itself, the following lines must be added to the client code:

System.setProperty("java.naming.security.principal","SCOTT");
System.setProperty("java.naming.security.credentials ","TIGER");

In both the jndi.properties file and the programmatic example,

  • REMOTE_HOST must be set to the name of the server running the OC4J server.

  • IIOP_PORT must be set to the port number used by OC4Jfor serving IIOP requests.

When using IIOP with the application client, no changes need to be made to the application client code or the deployment descriptors. The client must be configured to use IIOP properly, including the use of the jndi.properties file.

The remote application client must also include the deployed application's IIOP client jar in its classpath, in order to have access to the IIOP stubs for each EJB deployed.

See "Switching from ORMI to IIOP Transport" for more information on this.

JNDI State Replication

This section discusses JNDI state replication.

Note:

JNDI State Replication supports clustering in a multiple-OC4J environment.

If you are using Oracle Application Server in standalone mode as an environment for developing applications to be used in a multiple-OC4j environment, the information in this section is provided to support your planning and coding process.

The section covers the following topics:

What Is JNDI State Replication

JNDI state replication causes changes made to the context on one OC4J instance of an OC4J cluster to be replicated to the name space of every other OC4J instance in the cluster.

When JNDI state replication is enabled, you can bind a serializable value into an application context (using a remote client, EJB, or servlet) on one server and read it on another server.

Enabling JNDI State Replication

JNDI state replication must be enabled for each application. When an application is deployed, a <cluster> tag can be added to orion-application.xml, which is found in the application's META-INF directory. This type of configuration allows for control over the clustering status of each application. Adding this <cluster> tag enables HTTP/EJB session replication as well as JNDI State replication.

The <cluster> element serves as the single mechanism for clustering configuration. You can add the <cluster> element to either of the following files:

  • The ORACLE_HOME/j2ee/home/config/application.xml file to configure clustering at the global level.

  • An application-specific orion-application.xml file to configure clustering for each application.

Configuring the <cluster> element mainly involves specifying the following subelements:

  • The <replication-policy> subelement controls when replication occurs and what data is replicated.

  • The <protocol> subelement defines what mechanism to use for replication - multicast (default), peer-to-peer, or database.

Here are two example OC4J clustering and JNDI state replication configuration.

Example 1:

This example configures an application to communicate over a multicast network. It is important to make sure that all nodes in this cluster use the same multicast port.

<cluster>
    <protocol>
        <multicast ip="230.230.0.30" port="45678" />
    </protocol>
</cluster>

Example 2:

This example uses a peer-to-peer protocol for JNDI state replication. This example requires that all nodes running in the cluster be part of a managed IAS instance. This Oracle Application Server instance is controlled by OPMN.

<cluster>
    <replication-policy trigger="onRequestEnd" scope="modifiedAttributes" />
    <protocol>
        <peer>
            <opmn-discovery/>
        </peer>
    </protocol>
</cluster>

For detailed information on OC4J clustering, see the Oracle Containers for J2EE Configuration and Administration Guide.

Limitations of JNDI State Replication

Consider the following limitations when relying on JNDI state replication:

Propagating Changes Across the Cluster

Bindings to values that are not serializable are not propagated across the cluster.

Binding a Remote Object

If you bind a remote object (typically a home or EJB object) in an application context, then that JNDI object is shared across the cluster but there is a single point of failure in the first server to which it is bound.