Oracle® Containers for J2EE Services Guide 10g (10.1.3.1.0) Part Number B28958-01 |
|
|
View PDF |
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:
Creating JNDI bindings and using JNDI to look up bindings, as described in the following sections:
What's New
The following OC4J JNDI features and behaviors are new for this release:
JNDI Tree Browser - The Application Server Control Console provides a JNDI tree browser as described in Browsing the JNDI Context.
Global JNDI Lookup - In the default OC4J configuration, lookups within an application are bound to the current application's namespace. It is now possible to configure JNDI to perform inter-application lookups. See "Enabling Global JNDI Lookups".
Relative Java Context Lookups - Relative lookups are now attempted when all other lookup attempts fail. For example, if a client looks up its resource using context.lookup("ejb/EJBName")
, rather than ("java:comp/env/ejb/EJBName
"), this lookup will now succeed. This lookup attempt is always relative to the "java:comp/env
" namespace, and has the same effect as calling context.lookup()
with the "java:comp/env
" prefix attached to the binding name. There is no configuration required for this feature, since this feature is enabled by default in OC4J.
Referenceable Interface - This release provides full support for binding objects that implement the javax.naming.Referenceable
interface.
Associating a Principal with a Thread - For work that requires authentication or access control, you can now associate a principal, or user, with the thread that performs the work. This is described in "JNDI Contexts and Threads".
MBean Support for JNDI - The following JNDI-related MBeans are now registered with OC4J and are available for use within the Oracle Enterprise Manager 10g Application Server Control Console:
JNDIResource
- This JSR-77 MBean allows for queries on the JNDI bindings of a given application. A JNDIResource MBean is registered for each deployed application in a given OC4J instance. When an application is undeployed, the associated JNDIResource MBean is deregistered. This MBean offers two ways to access the JNDI bindings for a given application:
getBindingsAsXMLString()
- returns the bindings tree as an XML document.
getBindingsAsString()
- used mainly for debugging.
JNDINamespace
- This MBean allows a client to iterate over all of the JNDIResource MBeans registered on a given OC4J instance. This means that this namespace bean can be used to view all of the JNDI bindings for a given application server instance, separated by application name. The method getAllBindingsAsXMLString()
returns an XML document that represents the entire bindings tree.
Both MBeans return XML documents that can be parsed to determine the current bindings of the applications deployed to an OC4J instance. This XML document uses the oc4j-jndi-bindings-10_0.xsd
schema for validation.
Path to JNDI-Related MBeans from the Application Server Control Page
OC4J:Home > Administration tab > Task Name.System MBean Browser. Go To Task > Drill down: J2EEDomain:oc4j, J2EEServer:standalone > JNDI Namespace and JNDI Resource
Deprecated
The following item is deprecated in this release:
The previous package structure for context factories provided by OC4J is deprecated, and is replaced by a more consistent naming structure. See the note following Table 2-1, "InitialContext Properties".
No Longer Supported
The following items are no longer supported in this release:
The dedicated.connection
environment property
The dedicated.rmicontext
environment property. See Table 2-2, "JNDI-Related Environment Properties".
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 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.
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.
For lookups from within EJBs, the resource references are specified in ejb-jar.xml
. Resource references specified in ejb-jar.xml
are then mapped to actual JNDI locations in orion-ejb-jar.xml
.
When a servlet creates an initial context, the JNDI implementation maps bindings to the resource references specified in web.xml
to the actual JNDI locations specified in orion-web.xml
.
An application client's application-client.xml
descriptor's references are bound when the context is created from a remote application client. These references are bound to the actual JNDI locations specified in orion-application-client.xml
.
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.
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. |
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:
Using a text editor, open J2EE_HOME/config/server.xml
.
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>
Save and close server.xml
.
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.
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 |
---|---|---|
|
This property specifies which initial context factory to use when creating a new initial context object. The eligible settings are:
See the Note following this table for information about deprecated context factories. |
|
|
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. |
|
|
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. |
|
|
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:
For the new context factory names that replace the deprecated ones, see the |
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>
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
).
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
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:
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 useRMIInitialContextFactory or IIOPInitialContextFactory . See "Looking Up Objects in Another Application". |
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 propertyjava.naming.factory.url.pkgs to include com.sun.java.* .
Check this property and remove |
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
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.
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");
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.
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 useIIOPInitialContextFactory only for looking up EJBs. The same holds true for using a "corbaname" URL with the ApplicationClientInitialContextFactory . |
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".
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 anapplication-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.
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 |
---|---|
This property is no longer used by OC4J. This property was used for two reasons:
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. |
|
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 You can supply multiple hosts (for failover) in a comma-delimited list when using the ORMI protocol. |
|
Some versions of the JDK on some platforms automatically set the system property Check this property and remove |
|
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 |
|
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 |
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 |
---|---|
|
If specified, the client interacts with the OC4J process that was initially chosen at the first lookup for the entire conversation. |
|
Used for a Web client (servlet or JSP) that will access EJBs in a clustered OC4J environment. If specified, a new |
|
Used for a standalone client that will access EJBs in a clustered OC4J environment. If specified, a new |
For more information on load balancing see "Configuring ORMI Request Load Balancing".
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.
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.
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:
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.
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.
Consider the following limitations when relying on JNDI state replication:
Bindings to values that are not serializable are not propagated across the cluster.
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.