2ObjectivesAfter completing this lesson, you should be able to do the following:Describe Remote Method Invocation (RMI)Define the role of RMI in Java 2, Enterprise Edition (J2EE) applicationsDescribe Java Naming and Directory Interface (JNDI)Define the role of JNDI in J2EE applicationsWrite code to look up a Java object by a JNDI nameObjectivesThis lesson describes the architecture and the APIs that are used for some communication techniques in J2EE environments and examines their usage from client applications.JNDI names are influenced by the configuration of various elements in the environment, such as variables, EJB references, and data sources. In a J2EE environment, these elements are specified in application deployment descriptors or property files.
3Overview of RMIRemote Method Invocation (RMI) is a framework for executing distributed objects in Java. RMI has the following characteristics:It uses RPC-like communication mechanisms.It is designed for client applications to invoke remote object methods, as easily as calling local methods.It comprises the following components:Remote interfaceImplementation classServer application/classClient application/classStub (proxy) and skeleton classesIntroduction to RMIAn RMI client application uses a standard remote procedure call (RPC) mechanism to communicate with remote objects. The mechanism involves the use of stubs and skeletons.RMI applications comprise a client that communicates with a remote server object via a user-defined remote interface. The server object is instantiated from the implementation class in the context of a server application.A stub acts as the client’s representative for the remote object, often called a proxy. The client invokes a method on the local stub that in turn executes the appropriate method call on the remote object. An RMI stub class implements the same remote interface that is used by the remote object. The remote object may have a skeleton class. The skeleton manages the dispatching of a client call (via the client stub) to the actual remote implementation object. In JDK 1.2 and later, an additional stub protocol is introduced that eliminates the need for skeletons, and generic code carries out the tasks that are performed by skeletons in JDK1.1. Stubs and skeletons are generated by running the rmic compiler on the compiled implementation class. For example:rmic RMIClassImplThe rmic command produces two class files: RMIClassImpl_Stub.class for the stub and RMIClassImpl_Skel.class for the skeleton.
4Role of RMI in J2EEDistributed components or objects in J2EE are implemented as Enterprise JavaBeans (EJB).Oracle Application Server 10g Containers for J2EE (OC4J) uses a custom form of the RMI wire protocol known as ORMI. The J2EE 1.3 specification requires support for the RMI-IIOP protocol as the type of communication used between the client and server object.EJBs have a remote interface and implementation classes, which conform to RMI semantics:They implement a remote interface.Methods throw the java.rmi.RemoteException.Object parameters or return values must be serializable.Role of RMI in J2EERemote objects execute in a different Java virtual machine (JVM) from the client application. The J2EE distributed object architecture and protocols are modeled on RMI in such a way that a remote object appears as if it is local to the client. In RMI, the server object is an instance of the remote interface running on a server. In a J2EE container, an EJB instance is the equivalent of the RMI server object. Client interaction with an EJB instance is mediated through the stub and skeleton classes that are generated for the EJB component. The EJB component and its skeleton classes reside on the remote (middle) tier, while the stub class resides with the client software.RMI is a wire-level protocol that supports other protocols, such as HTTP, and defaults to a protocol called Java Remote Messaging Protocol (JRMP). The OC4J stub and skeleton layer uses a modified wire-level protocol called ORMI. OC4J supports the RMI over IIOP (RMI-IIOP) protocol as required by J2EE 1.3 specifications. Common Object Request Broker Architecture (CORBA) and Microsoft Distributed Component Object Model (DCOM) are other distributed technology implementations that use their own wire-level protocols.Much like an RMI server object, an EJB provides a remote interface that describes how to invoke the EJB methods. Methods could throw java.rmi.RemoteException. Objects must conform to Java serialization rules to be passed as parameters to, or returned from, a remote object method.
5Communication in a J2EE Environment J2EE serverNamingCreation13Client425InterfaceMarshaled dataSkeletonStubMarshaled data6Local call7InterfaceCommunicating in a J2EE Distributed Object EnvironmentThe diagram in the slide shows how the distributed object communication occurs from the time the client requests access to a method on the remote object until the client’s request is served.Distributed systems provide transparent communication between objects that reside on different nodes.1. The client requests an appropriate remote server object from the J2EE server.2. A new server object (which implements the required interface) is created, or an existing server object is allocated to the client. Usually an interface object (a skeleton) is generated to intercept and forward the requests that come from the remote client.3. On the client side, a special interface object (stub) is instantiated. This stub exposes the same interface that the server object implements. The stub knows the details of how to access the remote skeleton and the server.4. The client makes local calls to the stub that represents the server object.Network protocol(Java RMI)Serverobject
6Communicating in a J2EE Distributed Object Environment (continued) 5. The stub marshals the methods and parameters that are requested by the client, and transfers the marshaled data over the network to the waiting skeleton.6. The skeleton can intercept the client calls; perform authentication, access control, and transaction handling; and manage the persistent state of the object. The skeleton then invokes the appropriate method in the server implementation.7. The results of the call or run-time exceptions, if any, are passed back by the skeleton to the caller through the stub.The association between a client and the server object remains in effect until the client either directly or indirectly frees the server object. During that period, the client can make several calls.
7How Clients Locate a Distributed Component In J2EE, a distributed component is bound to a name when deployed.The server object run-time environment provides a naming service to help locate an object by a name:In RMI, the RMI registry performs this task.In J2EE, the container typically provides this service.Clients use the Java Naming and Directory Interface (JNDI) API to locate a remote object by a name.How a Client Locates a Distributed ComponentThe RMI clients use an RMI-specific URL string that is prefixed with rmi (using JRMP protocol, by default) to locate a remote RMI server object by a name. The URL string specifies the location of the RMI registry and the name of the remote object. The RMI application server class instantiates the RMI server object and binds the remote implementation object to a name in the RMI registry. In this scenario, the RMI registry provides the service for registering the implementation object with a name, and for the client to look up the remote object by a name in the registry. In this case, the binding of the implementation object to a name is done at run time, and the lookup string is RMI protocol dependent.The J2EE implementation was designed to overcome the run-time binding and to free the developer from a specific naming service and protocol. This was achieved by using the JNDI specification. A J2EE container implements the naming and directory service conforming to JNDI specifications. The binding of a name to the server object or component is done (when the server component is deployed) by using deployment descriptors. The client application uses the JNDI APIs to locate (or look up) a remote object by a JNDI name. The JNDI URL pattern depends on the type of JNDI that the service provider uses to implement the naming and directory service.Subsequent slides in this lesson discuss JNDI in detail.
8Java Naming and Directory Interface (JNDI) What is JNDI?JNDI is a standard API that provides access to the directory and naming functionality.The JNDI Service Provider Interface (SPI) implementation provides the mapping between the naming servers and the JNDI APIs.JNDI APIClientJNDI SPIJava Naming and Directory Interface (JNDI)Java Naming and Directory Interface (JNDI) is a standard interface to a naming and directory service. J2EE applications use the following two parts of JNDI to find other distributed objects:An application-level interface that is used by application programs to access a naming and directory service.A service provider interface to attach a provider of a naming and directory service.By using these parts and portable programming principles, client applications can access any directory service.Applications use JNDI to obtain naming contexts that enable the applications to locate and retrieve objects such as data sources, local and remote EJBs, Java Message Services (JMS), and so on. Objects in a JNDI namespace can be managed by different directory and naming services. For example, a JNDI service provider can be implemented by using a file system, or by using a Lightweight Directory Access Protocol (LDAP) service, such as Oracle Internet Directory (OID), an RMI registry, or the CORBA Object Naming services in the form of COS Naming, and so on. Similar to Java Database Connectivity (JDBC), JNDI provides different drivers for various service providers.OC4J provides a complete JNDI 1.2 implementation, with the JNDI service provider implemented in memory in the container.RMI registryCOS NamingLDAPName and directory services
9J2EE Container and JNDI Interface The container implements the J2EE environment and makes the services and resources available through a JNDI interface.The JNDI service obtains names from the Extensible Markup Language (XML) files and holds them in memory.JNDI allows developers to write application code that is independent of vendor-specific underlying protocols, connections, and other resources.The JNDI interface provides a common naming convention to access J2EE resources.J2EE Container and JNDI InterfaceThe J2EE container provides services, such as transaction services, naming services, and so on, as discussed earlier in this course. These services reside in a framework in the container. This framework exposes the interfaces that are to be used by the client application code and enterprise beans. In the case of EJB, the interfaces enable the developer to write the code for a bean without using vendor-specific references to underlying protocols, connections, and other resources.The container implements the environment and makes the services and resources available through the JNDI interface. For example, data sources represent databases, and JMS service names can be specified as JNDI names.The JNDI interface provides a common naming convention to access the resources that are provided by the container. The names in the naming convention are used in the bean class and the deployment descriptor.
10Naming ServiceA naming service allows clients or objects to locate each other in a network by:Storing objects published against their names, known as binding a name to an objectMaintaining a mapping of logical names to actual names of hierarchical objectsUsing a directory service with a hierarchical structure to maintain logical names for its dataExamples: Java Naming and Directory Interface (JNDI), RMI registry, Lightweight Directory Access Protocol (LDAP), CORBA naming service (COS Naming)Naming ServiceAn Object Naming Service is the principal mechanism for objects or clients to locate other objects on the network. Names are humanly recognizable values that identify an object. The naming service enables the creation and mapping of these names to object references.A name-to-object association is called name binding. In the case of EJBs, the server performs the binding of the bean’s home interface in the JNDI namespace.Naming services can be used for literally mapping any type of object or resource with names such as files, database objects, remote objects, and so on. EJB specifications require that the bean home interfaces be published and made available to the clients through JNDI.It is the responsibility of the server and container provider that the beans deployed in the server are made available to different clients through a JNDI service.A directory service usually has a hierarchical structure of data, and you use the naming service to create logical names and map them to the naming server. For example, the directory service of a file system contains a hierarchical structure of folders, subfolders, and the files in the folders.Examples of naming services are RMI registry, LDAP, and CORBA Naming Service (COS Naming).
11JNDI Terminology JNDI client Initial context ormi://host/AppCtx NamespaceContextenvSub-contextjdbcejbAtomic namesOracleDSoeCoreDSEmployeeCartBindingObjectsJNDI TerminologyNamespace: The set of all names in the naming server. The names in the namespace must be unique. For example, in a directory structure, each file and subdirectory in a particular level have unique names.Initial context: The root directory object in the namespace that refers to the starting point of the name hierarchy from which a client can start navigation. The client obtains this root directory by creating a new InitialContext object. Relative to the initial context, a client can look up another object using its compound name.Compound name: Formed by concatenating the names of each context object along the hierarchical path to the target atomic name for an object published in the JNDI namespace. The slide shows env, jdbc, and ejb as context objects, where jdbc and ejb are subcontexts below env.Atomic name: A unique indivisible part of a name, such as env, jdbc, and OracleDSBinding: The process of associating an object with a name in the naming and directory serviceURL: A composite name spanning more than one context or namespace, which is used to uniquely identify an object in a composite namespacejava:comp/env/jdbc/OracleDSCompound name
12Main JNDI Class and Interface The javax.naming.InitialContext class:Is used to obtain the initial context for JNDI lookup operationsReturns a reference to the object implementing the java.naming.Context interfaceThe javax.naming.Context interface:Provides methods to bind names to objectsProvides methods to create subcontextsProvides methods to navigate the JNDI name hierarchyLooks up an object by a name that is relative to the initial context or a subcontextMain JNDI Class and InterfaceContext: Context is an interface in the javax.naming package. The very first JNDI call to code is the one that gets a Context object. The first context object that you get is called the initial context and is bound to the root naming context of the namespace. A context can contain a subcontext and objects. An object implementing the Context interface contains a number of methods that the EJB application developer can use. The client uses the lookup() method on the context to look up a home object. The names in the namespace are bound to specific objects.URL: URL enables you to use JNDI requests to start up services and sessions and to access components published in the database. Just as a Web document can be located by using a unique URL, an object published in JNDI can be located by using a unique URL.When you use JNDI in your client or server object implementations, be sure to include the following import statements:import javax.naming.Context; // the JNDI Context interfaceimport javax.naming.InitialContext;import java.util.Hashtable; // Hashtable for the initial// context environment
13Accessing an Object in JNDI Namespace A client must perform the following steps to retrieve a local object reference from the JNDI namespace:Get the JNDI InitialContext object. Example: Context ic = new InitialContext();Form the URL for the bean home interface and call the lookup() method to get the reference to the local home interface object. Example: DepartmentLocalHome home = (DepartmentLocalHome) ic.lookup( "java:comp/env/ejb/Dept");lookup() returns an Object type that should be cast to a desired type.Accessing an Object in JNDI NamespaceTo access an object in the JNDI namespace, the client has to perform these steps:1. Get the JNDI InitialContext object.2. Form the URL for the bean home interface and call the lookup() method to get the reference to the home interface object.The code in the slide shows an example of this process. The first statement creates a new initial context object, using the default environment. The second statement looks up an EJB local home interface reference in the application’s JNDI tree. In this case, ejb/Dept might be the name of an entity bean that is declared in the ejb-jar.xml configuration file, in an <ejb-local-ref> tag.For example:<ejb-local-ref><ejb-ref-name>ejb/Dept</ejb-ref-name><ejb-ref-type>Entity</ejb-ref-type><local-home>DepartmentLocalHome</local-home><local>DepartmentLocal</local></ejb-local-ref>
14Getting the JNDI InitialContext When OC4J starts, a JNDI context is constructed for each application deployed in the server.An initial context obtained by the client is used to access the subcontexts and objects.Clients accessing objects in a remote OC4J container typically require a set of environment properties to obtain the InitialContext:INITIAL_CONTEXT_FACTORYPROVIDER_URLSECURITY_PRINCIPALSECURITY_CREDENTIALdedicated.rmicontextGetting the JNDI InitialContextWhen OC4J starts, a JNDI context is constructed for each application that is deployed in the server (in server.xml). 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-written applications inherit properties from the global application. User-written applications can override property values defined in the global application, can define new values for properties, and can define new properties as required. In the default OC4J server, as shipped, the global application is the default application, as defined in the server.xml file. OC4J requires certain properties for obtaining the initial context reference.Each JNDI lookup retrieves a connection to the server. Each subsequent JNDI lookup for this same server uses the connection that is returned by the first JNDI lookup. That is, all requests are forwarded over and share the same connection. The dedicated.rmicontext JNDI property overrides this default behavior. If you set dedicated.rmicontext to true before you retrieve an InitialContext, you will retrieve a separate physical connection for each lookup, each with its own designated username and password. The value of dedicated.rmicontext defaults to false.The list of properties shown in the slide is not an exhaustive list. Refer to the Oracle Application Server 10g Containers for J2EE Services Guide for more information.
15Getting the JNDI InitialContext Set environment properties for initial context in:The system properties, set either by the OC4J server or by the application containerA jndi.properties file contained in the application EAR file, as part of the application-client.jar fileAn environment specified explicitly in a HashtableThe JNDI InitialContext has two constructors:A no-arg constructor used by local clients to execute code in the same J2EE containerA constructor with a Hashtable argument used by remote clients to execute code in a remote J2EE containerGetting the JNDI InitialContext (continued)The environment properties can be in the form of system property values that are set by OC4J as specified in the application.xml file, in the jndi.properties file that is contained in the application EAR file, or as environment properties defined explicitly in the client code and passed as a Hashtable to the JNDI initial context constructor.The JNDI InitialContext constructor has two forms:A default no-arg form of the constructor that creates a Context object by using the default context environment for that application, that is created by the OC4J when the server is started. This is typically used by server-side clients such as JSPs, servlets, or other EJBs. These server-side clients typically use local references to locate an object being looked up as the clients are running in the same J2EE container. You can also specify that the object not be initialized by passing (boolean lazy) to the constructor.The second form of the constructor accepts a Hashtable parameter that consists of the environment properties. These properties can be defined in any one of the three forms, as described above. This form is used by remote client applications. Therefore, it is necessary to specify the JNDI properties. In the JNDI properties, you can specify whether the object that is being looked up is running in a JVM or in a J2EE container remotely from the client application.
16Initial Context Factories There are three JNDI initial context factories:ApplicationClientInitialContextFactoryApplicationInitialContextFactoryRMIInitialContextFactoryAn initial context factory is used to construct an InitialContext object.The initial context factory class name is the string value for the INITIAL_CONTEXT_FACTORY JNDI property.Initial Context FactoriesThe three types of context factories are provided to help a client establish a connection with the naming service in an efficient way. This depends on where the client is, relative to the component that it is locating.Use ApplicationClientInitialContextFactory to construct the initial context for a local or remote resource in a J2EE application. The client is bundled with the J2EE application. For the client to access remote objects, ApplicationClientInitialContextFactory reads the META-INF/application-client.xml and META-INF/orion-application-client.xml files in the <application_name>-client.jar file.The client code runs in a server as part of a J2EE application, and can define a default set of properties for JNDI use. ApplicationInitialContextFactory is set as the default initial context factory for applications that are running in the same container as the client. In this case, the clients can only look up references to local objects (for example, a servlet or JSP calling an EJB in the same container).RMIInitialContextFactory is used by a client to access the JNDI namespace when looking up objects that are part of another remote J2EE application. It is also used for resource references that cannot be specified in the application-client.xml file.
17lookup() MethodThe lookup() method obtains a reference to the required resource.To reference a local resource, pass the URL with the object name as parameter: java:comp/env/subContext/resourceNameExamples:java:comp/env/ejb/Deptjdbc/oeCoreDSRetrieve a reference to target EJB by using:The actual bean name specified in the <ejb-name> element or the <ejb-ref-name> element of ejb-jar.xmlThe logical bean name specified in the <ejb-ref-name> element of application-client.xmllookup() MethodAfter the client obtains the InitialContext, it should obtain a reference to the required resource by using the lookup() method on InitialContext. The client uses the lookup() method by passing the URL with the object name as the parameter. This generally depends on how the resources are mapped in the naming server. Generally, the URL to look up a local resource (in the same container) is of the following format: java:comp/env/subContext/resourceName.For example, the client looks up an EJB called Dept under the subcontext ejb with the URL java:comp/env/ejb/Dept. Here, java:comp/env is the initial context, and ejb/Dept can be the actual name of the EJB as specified in either the <ejb-name> or the <ejb-ref-name> element of the deployment descriptor where the bean is defined. It can also be the logical name of the bean, which is defined in the <ejb-ref-name> element under the <ejb-ref> section in the files ejb-jar.xml, application-client.xml, or web.xml for an EJB, an application, or a servlet or JSP client, respectively.In another example, a client looking up a data source called oeCoreDS may use the URL java:comp/env/jdbc/oeCoreDS. Here, jdbc is the subcontext name and oeCoreDS is the resource name.Note: The initial context for a local object always uses the URL prefix java:comp/env.
18Obtaining a Reference to a Local Resource Using the default InitialContext:1. Obtain InitialContext: Context ic = new InitialContext();2. Obtain reference to a resource using lookup():An EJB client referencing another local EJBObject obj = ic.lookup("java:comp/env/ejb/Dept");An EJB client referencing a data sourceObject obj = ic.lookup("jdbc/oeCoreDS");3. Cast reference obtained from lookup(): DepartmentLocalHome dlh = (DepartmentLocalHome) obj; DataSource ds = (DataSource) obj;Obtaining a Reference to a Local ResourceTo obtain a reference to a local resource, the client first obtains the initial context. The code in the slide shows the example by using the default no-arg constructor. The InitialContext reference returns a Context interface type variable called ic.The client then invokes the lookup() method of the initial context. The parameter for the lookup() method consists of the initial context and the path to the object, as discussed in the previous slide. The lookup() method returns a value of Object type and must be cast to the correct class to be used as intended by the application.
19Obtaining a Reference to a Remote Resource Use initial context with appropriate JNDI properties:1. Set JNDI properties for application: Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, ...);2. Obtain the InitialContext: Context ic = new InitialContext(env);3. Obtain a reference to a resource by using lookup(): Object obj = ic.lookup("Dept");4. Cast the reference to the returned Object type: DepartmentHome dh = (DepartmentHome) PortableRemoteObject.narrow(obj, DepartmentHome.class);Obtaining a Reference to a Remote ResourceIf the client application is external to the container that runs the resource, then you must obtain the initial context by using a set of JNDI properties set in a Hashtable, or a jndi.properties file for the application. The slide shows a snippet of creating the Hashtable. Here is a more complete example of setting environment properties:Hashtable env = new Hashtable();env.put(Context.INITIAL_CONTEXT_FACTORY,"com.evermind.server.rmi.RMIInitialContextFactory");env.put(Context.SECURITY_PRINCIPAL, "admin");env.put(Context.SECURITY_CREDENTIALS, "oracle");env.put(Context.PROVIDER_URL, "ormi://localhost/Dept");After the initial context is obtained by using the appropriate JNDI properties, you can invoke the lookup() method to return a reference to an Object data type, as seen for local resources. You then cast the remote reference to the appropriate type such as a remote home interface or data source by using the PortableRemoteObject.narrow() method, which is required for obtaining a remote reference from a client accessing over the RMI-IIOP protocol.If appropriate, the Object reference returned can be cast to a data source type by using the javax.sql.DataSource class.
20Setting JNDI Environment Properties Do not set JNDI properties if:The client exists in the same application as the targetThe target exists in the parent application of the clientSetting JNDI properties:Supply the properties through the jndi.properties file. The path of the file must be in the CLASSPATH, or JAVA_HOME/lib.Supply properties in the client code by using a Hashtable.Setting JNDI Environment PropertiesThe JNDI environment properties can be either set in the jndi.properties file or explicitly defined in the client code. A client that co-resides with the target EJB does not need to supply the environment properties. The client does not need to supply the environment properties if the parent application of the client coresides with the target EJB. In this case, the container sets the environment properties.The two methods are:Using the jndi.properties file that must be located in the machine’s CLASSPATH, or in the JAVA_HOME/lib directoryExplicitly coding the environment properties in the client code
21Setting JNDI Environment Properties Using the jndi.properties file:Factory: Initial context factory to be usedjava.naming.factory.initial = com.evermind.server.ApplicationClientInitialContextFactoryLocation: URL used to look up the objectsjava.naming.provider.url = ormi://<hostname>:23891/<application-name>Security: Valid credentials of the client to this containerjava.naming.security.principal=<username>java.naming.security.credentials=<password>Setting JNDI Environment Properties (continued)If you are setting the JNDI properties in the jndi.properties file, then set the properties as follows. Make sure that this file is accessible from the CLASSPATH.Factory: Specifies the initial context factory to use when creating a new initial context object. Different context factories are discussed later in this lesson.java.naming.factory.initial= com.evermind.server.ApplicationClientInitialContextFactoryLocation: The URL that the application client code uses to look up objects on the server. The ORMI default port number is 23891, which can be modified in the config/rmi.xml file. Thus, set the URL in the jndi.properties in one of the following three ways:java.naming.provider.url=ormi://<hostname>/<application-name> orjava.naming.provider.url=ormi://<hostname>:23891/<application-name> or when running in the Oracle Application Server 10g server, hardcoding the port is not necessary and you can usejava.naming.provider.url=opmn:ormi://<host>:<port>:<oc4jinstance>/ <application-name>
22Setting JNDI Environment Properties (continued) Security: When you access EJBs in a remote container, you must pass valid credentials to this container. Stand-alone clients define their credentials in the jndi.properties file deployed with the client’s code.java.naming.security.principal=<username>java.naming.security.credentials=<password>
23Setting JNDI Environment Properties Specify the JNDI properties in the client code by:Using jndi.propertiesDeclaring properties in a Hashtable and passing them to the InitialContext constructorHashtable env = new Hashtable();env.put(Context.PROVIDER_URL, "ormi://myhost/J2EECourse");env.put(Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server ApplicationClientInitialContextFactory");env.put(Context.SECURITY_PRINCIPAL, "guest");env.put(Context.SECURITY_CREDENTIALS, "welcome");Context ic = new InitialContext (env);Setting JNDI Environment Properties (continued)If you use the jndi.properties file approach, then the properties names are specified as the textual representation of the first parameter for each env.put() method, shown in the slide. The property values are the same as the second parameter values that are used in each env.put() call listed in the slide. For example:java.naming.security.principal=guest //Context.SECURITY_PRINCIPLEThe slide shows how to use a Hashtable variable env. The property name and value pairs are added to the Hashtable by calling the put() method. Property names are specified by using constants defined in the javax.naming.Context class in the first parameter of the put() method with its corresponding value specified in the second argument.PROVIDER_URL shows a typical example of a URL for a JNDI resource name. The absence of the port number implies that the default ORMI port number of is assumed.INITIAL_CONTEXT_FACTORY, as used by most client applications, is specified as ApplicationClientInitialContextFactory.SECURITY_PRINCIPAL and SECURITY_CREDENTIALS indicate the username and password of the client requesting the initial context. The Hashtable variable env is then passed as a parameter to the InitialContext constructor.
24Using RMI over HTTP Tunneling OC4J supports tunneling of RMI over HTTP or HTTP-S.Allows clients to communicate with remote objects through a firewallMakes the connection appear as if it is statefulClients use RMI over HTTP in JNDI requests by prefixing PROVIDER_URL with http: as in the following example:Port used is the HTTP server port (by default 80)Hashtable env = new Hashtable();env.put(Context.PROVIDER_URL, "http:ormi://<host>:<port>/Application");Using RMI over HTTP TunnelingOC4J supports the ability to tunnel RMI over HTTP and HTTP-S protocols. You can use RMI over HTTP/HTTP-S tunneling for Java-based clients when they must communicate with OC4J over the HTTP protocol.Typically, HTTP tunneling simulates a stateful socket connection between a Java client and OC4J and “tunnels” this socket connection through an HTTP port in a security firewall. HTTP is a stateless protocol, but OC4J provides the tunneling functionality to make the connection appear to be a stateful RMI connection.If you are using RMI over HTTP tunneling, a client can make requests and accept replies from a server, but the server cannot initiate a communication with the client. This means that a continuous two-way connection is not possible.The OC4J HTTP tunneling simulates an RMI connection over the HTTP protocol, overcoming these limitations.An advantage of HTTP tunneling is that different J2EE components can be deployed on a single physical tier to optimize performance, or on separate physical tiers for better accessibility. Deploying components on separate tiers can make use of architectural redundancy designed for managing connection rerouting and high availability, in the event of failure.
25Using Environment References with JNDI An environment reference is:A static element accessible to applications at run timeDefined as:An environment variableA resource manager (JDBC data source, JMS services, or a URL)An EJB reference (logical name for the EJB)Bound in JNDI namespace at deployment timeDefined in the J2EE deployment descriptorsMapped through OC4J-specific descriptorReferenced by using the JNDI lookup() method of an InitialContextConfiguring Environment ReferencesIndependent software vendors (ISVs) typically develop EJBs that are independent of the EJB container. To distance the bean implementation from the container specifics, you can create environment elements that map to one of the following:Environment variables that can be used by more than one applicationEJB referencesResource managersThese environment elements are static and cannot be changed by the bean. The elements are given logical names when defined in the J2EE deployment descriptor. Using a logical name enables the bean developer to refer to existing variables, EJBs, and a JDBC data source without specifying the actual name. The logical names are then associated to the actual names within the OC4J-specific deployment descriptor. When the bean is deployed, these elements are bound in the JNDI registry and are accessible by the client during run time. One advantage of this is that the deployer can set different values to the same element through the container-specific tool and deploy the bean with these different values.The client accesses these environment elements by using the lookup() method of the InitialContext, as discussed in the next slide.
26Configuring Environment Variables Environment variables are defined in the <env-entry> section of the deployment descriptor (DD).One entry for each variable; case-sensitiveTypes can be the following classes: String, Integer, Boolean, Double, Byte, Short, Long, or Float<env-entry> Deployment Descriptor<env-entry-name>minBalance</env-entry-name><env-entry-type>java.lang.Integer</env-entry-type><env-entry-value>500</env-entry-value></env-entry>Configuring Environment VariablesEnvironment variables are defined in an <env-entry> element of the J2EE deployment descriptor (DD) files, that is, web.xml or ejb-jar.xml. There is one environment entry for each variable accessed in the client code. The name of the environment variable is defined in <env-entry-name>, the type is defined in <env-entry-type>, and its initial value is defined in <env-entry-value>. The example in the slide declares one environment variable for minBalance.<env-entry><env-entry-name>minBalance</env-entry-name><env-entry-type>java.lang.Integer</env-entry-type><env-entry-value>500</env-entry-value></env-entry>The data types specified in the <env-entry-type> element can be one of the following Java classes: String, Integer, Boolean, Double, Byte, Short, Long, or Float.The client accesses the environment variables through the InitialContext, as follows:InitialContext ic = new InitialContext();Integer min = (Integer)ic.lookup("java:comp/env/minBalance");To retrieve the environment variable values, prefix each environment element with the base location of java:comp/env/, at which the container stores the environment variable.InitialContext ic = new InitialContext(); ClientInteger minBal = (Integer) ic.lookup("java:comp/env/minBalance");
27Configuring Environment Variables The J2EE name can be mapped to a different value in the OC4J-specific deployment descriptor (DD).The OC4J-specific DD overrides the value in the J2EE deployment descriptor.<env-entry> J2EE DD<env-entry-name>minBalance</env-entry-name><env-entry-type>java.lang.Integer</env-entry-type><env-entry-value>500</env-entry-value></env-entry><env-entry-mapping OC4J DDname="minBalance">300</env-entry-mapping>Configuring Environment Variables (continued)If you want the value of the environment variable to be defined in the OC4J-specific deployment descriptor, you can map <env-entry-name> to the <env-entry-mapping> element in the OC4J-specific deployment descriptor.Note: The value specified in the orion-ejb-jar.xml file overrides any value that may be specified in the ejb-jar.xml file. The type specified in the EJB deployment descriptor stays the same.The minBalance environment variable is defined as 300 in the OC4J-specific deployment descriptor, as shown in the code in the slide.
28Specifying an EJB Reference Specify an EJB reference by using an <ejb-ref> element in a J2EE client application deployment descriptor:<ejb-ref><ejb-ref-name>Employee</ejb-ref-name><ejb-ref-type>Session</ejb-ref-type><home>businesstier.EmployeeHome</home><remote> businesstier.Employee</remote></ejb-ref>A logical name in an <ejb-ref-name> element must be mapped to a JNDI name in an <ejb-name> element of an EJB deployment descriptor.The server side receives the JNDI name and resolves it in its JNDI tree.Specifying an EJB ReferenceYou can specify a reference to a local or remote EJB in the <ejb-ref> element of a J2EE client application’s deployment descriptor (for example, in application-client.xml, ejb-jar.xml, or web.xml). Choose the XML file based on the location of the client with respect to the target EJB.Note: The slide shows an example of a reference to a remote EJB because you defined the <home> and <remote> elements of the bean in the <ejb-ref> element. If the EJB reference is for a local component (that is, in the same container), then you specify the names of the local interfaces in the <local-home> and <local> elements inside the <ejb-ref> section.The value specified for <ejb-ref-name> can be:The actual JNDI name of the target EJB, as found in the <ejb-name> element of the EJB deployment descriptor (ejb-jar.xml)A logical name used by the application client in the JNDI lookup requestIf <ejb-ref-name> used is a logical name, then it must be mapped to an actual JNDI name found in the <ejb-name> element of the target EJB.
29Configuring EJB References The <ejb-ref> element of a client J2EE deployment descriptor can provide:The actual name of the bean in <ejb-ref-name>A logical name of the bean in <ejb-ref-name> and the actual name in <ejb-link>The logical name of the bean in <ejb-ref-name>, to be mapped to the actual name of the bean in the <ejb-ref-mapping> element in the OC4J-specific deployment descriptorOther elements of the EJB reference are:Type: Session or entity beanHome/LocalHome: Qualified home interface nameRemote/Local: Qualified remote/local interface nameConfiguring EJB ReferencesIf an EJB client invokes another EJB, the deployment descriptor for the client uses a reference to locate the other bean. The following examples show how a client specifies an EJB reference by using the actual JNDI name or logical name of the referenced bean.The examples assume that the referenced EJB is a session bean defined in the EJB deployment descriptor (ejb-jar.xml) as follows:<session> ...<ejb-name>Employee</ejb-name><home>businesstiersoln.EmployeeHome</home><remote>businesstiersoln.Employee</remote><ejb-class>businesstiersoln.impl.EmployeeBean</ejb-class> ...</session>Specify the actual JNDI name of the bean in the <ejb-ref-name> element:<ejb-ref><ejb-ref-name>Employee</ejb-ref-name><ejb-ref-type>Session</ejb-ref-type><home>businesstier.EmployeeHome</home><remote>businesstier.Employee/remote></ejb-ref>
30Configuring EJB References (continued) Specify a logical name in the <ejb-ref-name> element, and the actual name in the <ejb-link> element:<ejb-ref><ejb-ref-name>ejb/MyEmployee</ejb-ref-name><ejb-ref-type>Session</ejb-ref-type><home>businesstier.EmployeeHome</home><remote>businesstier.Employee/remote><ejb-link>Employee</ejb-link></ejb-ref>The <ejb-link> element provides the mapping of the logical name used in a JNDI lookup request to the target bean.Provide a logical name in the <ejb-ref-name> element, which is mapped to the actual name with a <ejb-ref-mapping> element:This reference alone is incomplete without mapping the logical name to the actual bean name. The mapping can be achieved by using either the <ejb-link> element in the same deployment descriptor, as shown in the example before this, or by specifying the mapping of the logical name to the actual name in the applications OC4J-specific deployment descriptor as follows:<ejb-ref-mappingname="ejb/MyEmployee"location="Employee"/>In the <ejb-ref-mapping> element of the client application’s OC4J-specific deployment descriptor:The name attribute identifies the logical name used in the client application lookup request and specifies the <ejb-ref-name> element of the J2EE deployment descriptor.The location attribute identifies the actual JNDI name of the target bean specified in the <ejb-name> element of the EJB deployment descriptor (ejb-jar.xml).
31Configuring Data Source References Create an environment reference to each data source that is used by a client through a JNDI reference.These references can be used only by the J2EE application that defines these data sources.The JNDI name is defined in the ejb-location attribute of a <data-source> element in the data-sources.xml file.The J2EE deployment descriptor can use either the JNDI name or a logical name.A logical name must be mapped to the JNDI name in the OC4J-specific deployment descriptor.Configuring Data Source ReferencesYou can access a database through JDBC either by using the traditional method or by creating an environment reference element for a JDBC data source. To create an environment reference element for your JDBC data source, the following steps are necessary:1. Define the JNDI name for each data source in the OC4J or the application-specific data-sources.xml file.2. Write the client code to use the JNDI name specified in the data sources file, or use a logical name that must be specified in the <res-ref-name> element in the J2EE deployment descriptor (either the web.xml file for a servlet or JSP, or the ejb-jar.xml file for an EJB).3. If the client application uses a logical JNDI name, as specified in the <res-ref-name> element of the J2EE applications deployment descriptor, then this logical name should be mapped to the actual JNDI name specified in the ejb-location attribute for the data source found in a data-sources.xml file. The mapping of the logical name to the actual JNDI name is done in the OC4J-specific deployment descriptor (that is, the orion-web.xml file for a servlet or JSP, and the orion-ejb-jar.xml file for an EJB).
32Configuring Data Source References 1. Define in data-sources.xml.<data-sources><data-sourceclass="com.evermind.sql.DriverManagerDataSource"name="OracleDS"location="jdbc/OracleCoreDS" ...ejb-location="jdbc/OracleDS" ... /></data-sources>JNDI Name2. Reference in J2EE Deployment Descriptor.<resource-ref><res-ref-name>jdbc/oeCoreDB</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Application</res-auth>3. Map in OC4J-specific deployment descriptor.Configuring Data Source References (continued)The code examples in the slide indicate how the target JNDI name and the logical names for a data source are defined.1. The data-sources.xml file defines the JNDI name value jdbc/OracleDS in the ejb-location attribute of the <data-source> element.2. In the J2EE deployment descriptor (web.xml/ejb-jar-xml), the reference indicates that the value jdbc/oeCoreDB in the <res-ref-name> element is the logical JNDI name that the client application uses to look up the data source.3. The OC4J-specific deployment descriptor (orion-web.xml/orion-ejb-jar.xml) is used to map the logical name used in J2EE deployment descriptor to the actual JNDI name for the data source defined in the data-sources.xml file.Note: Although JNDI names are specified in the location, xa-location, and ejb-location attributes of the <data-source> element, it is recommended that you use or map to the name specified in the ejb-location attribute. The configuration in the slide supports a client application that uses the logical JNDI name defined in the <res-ref-name> element of the J2EE deployment descriptor. For example:InitialContext ic = new InitialContext();javax.sql.DataSource ds = (javax.sql.DataSource)ic.lookup("java:comp/env/jdbc/oeCoreDB");<resource-ref-mappingname="jdbc/oeCoreDB"location= "jdbc/OracleDS" />Logical Name
33Summary In this lesson, you should have learned how to: Describe Remote Method Invocation (RMI)Recognize the role of RMI in a J2EE environmentExplain the concepts of JNDIAccess an EJB or a data source object by using JNDI techniquesConfigure the JNDI names and environment properties, such as environment variables, EJB references, and data sourcesSummaryThe slide summarizes the key points covered in this lesson. RMI is not specified as a part of the J2EE specification. However, RMI mechanisms and java.rmi interfaces and classes are used by J2EE components. The RMI communications architecture is used as the basis for communication between J2EE client and server components such as Enterprise JavaBeans. The JNDI services provided by J2EE-compliant implementations provide a standard way for clients to locate, look up, and communicate with distributed objects in a J2EE environment.
34Practice 10-1: Overview This practice covers the following topics: Creating a JSP Java client to connect to and invoke a remote Hello World EJB (the EJB is provided) by using the ORMI protocolCreating a stand-alone client to obtain a reference to an EJB and JDBC data source
35d. Save your changes, compile the JSP, and correct any syntax errors. Practice 10-1The aim of this practice is to write the code to perform JNDI lookup of an EJB and data source object. To formulate an appropriate JNDI lookup request, you need to know only the name of the EJB and how to call a method, which is similar to calling a method by using an object reference in any Java application.In JDeveloper, open the workspace practice10ske.jws in the practice10ske directory and expand the usingjndi.jpr project. The project contains a HelloWorld stateless session EJB and its deployment descriptor.1. Enable the HelloWorldLocal.jsp application to invoke the greeting() method of the HelloWorld session bean. The JSP and the session bean execute in the same embedded OC4J container.a. Open the HelloWorldLocal.jsp file and in the first scriptlet create an initial context object and assign it to a Context variable called context.b. Which package name is required in the import statement to compile this line of code?c. Now modify the string parameter value in the context.lookup() method to be the name of the EJB. Hint: Open the ejb-jar.xml file for the EJB and find the <ejb-name> element.d. Save your changes, compile the JSP, and correct any syntax errors.e. Expand the usingjndi.impl package, and right-click the HelloWorld node to run the HelloWorld EJB component in the embedded OC4J container.f. Run HelloWorldLocal.jsp and observe the results in the generated HTML page. The HTML page should contain the following text: “Result from the HelloWorld greeting() method is: Hello World (from Stateless Session EJB)”.2. Create a stand-alone Java class, with a main() method to invoke the HelloWorldEJB in the embedded OC4J container.a. Right-click the usingjndi project, select New, and then click Simple Files and create a new Java class called HelloWorldClient, making sure that the Generate Main Method check box is selected.b. In the default constructor, copy the code from the scriptlet of the HelloWorldLocal.jsp into the body of a try block, with Exception class being caught in the catch block. Hint: Make sure that you import the javax.naming package and any others that may be required in your class, and call the exception object printStackTrace() method in the catch block.c. In the last line of the try block, enter the following code to print the return value of the greetings() method of the EJB:System.out.println(helloWorld.greetings());d. Right-click HelloWorldClient.java, and select Run from the menu.e. You are expected to get an error. Can you explain the error? Hint: Check the first line of the error message displayed.
36Practice 10-1 (continued) f. Modify the HelloWorldClient application to create a java.util.Hashtable with JNDI properties set to the following values:Context.INITIAL_CONTEXT_FACTORY set to the string "com.evermind.server.rmi.RMIInitialContextFactory"Context.SECURITY_PRINCIPAL set to "admin"Context.SECURITY_CREDENTIALS set to "welcome"Context.PROVIDER_URL set to "ormi://localhost:23891/current-workspace-app"Hint: Remember to add an import statement for the java.util.Hashtable. Make sure that the port number in PROVIDER_URL is the same as the RMI port number printed in the Embedded OC4J Container tab window in the Log Message window.g. Modify the HelloWorldClient application to provide the Hashtable object as a parameter to the constructor when creating the InitialContext.h. Right-click HelloWorldClient.java and select Run. The Log window should show the bean message.3. Open the UseDataSource.java file and write the JNDI code to obtain a data source object from an OC4J server. You must run the HelloWorld EJB application to start the embedded OC4J container.a. In the try block of the UseDataSource() constructor, create a new InitialContext with the same JNDI properties used in the HelloWorldLocal.jsp application. Hint: Use a Hashtable parameter with the InitialContext constructor, or copy the jndi.properties file located in your E:\JDeveloper\jdev\mywork\practice10ske directory to your E:\JDeveloper\jdev\mywork\practice10ske\usingjdni\classes directory, and use the no-arg constructor of the InitialContext. You may need to edit the port number in the java.naming.provider.url property of the jndi.property file.b. Use the context object to create a javax.sql.DataSource object by looking up the JNDI name of jdbc/oeDS.c. Create a java.sql.Connection using the data source object by calling the getConnection(), or the getConnection(user, pass) with your database username and password.d. Call the listDepartments() method using the JDBC connection object that you opened from the data source to verify that your JNDI lookup works.e. Compile the code and eliminate any syntax errors.f. Run the HelloWorld EJB to launch the OC4J container.g. Run the UseDataSource application. The application should display a list of department ID and names in the JDeveloper Log window.
37Practice 10-1 (continued) Optionally, if you have time, then you can perform the following:Alter the client applications to work with the HelloWorld EJB deployed to Oracle Application Server 10g.a. Right-click HelloWorldEJB.deploy and select Deploy to OracleAS10g, or select Deploy to EAR file and deploy the resulting EAR file by using the Oracle Enterprise Manager Web interface.b. Modify HelloWorldClient.java and UseDataSource.java to work with Oracle Application Server 10g.c. Run HelloWorldClient.java. You should see the EJB message Hello World (from Stateless Session EJB) displayed in the Log Message window.d. In HelloWorldClient.java, alter the code that executes the lookup() method by passing the return value of the context.lookup() method to the first parameter of the javax.rmi.PortableRemoteObject.narrow() method. Hint: PortableRemoteObject.narrow() requires HelloWorldHome.class as a second parameter and an import javax.rmi.PortableRemoteObject statement.e. Run the HelloWorldClient.java application again, and it should yield the same result as before. In the client code, you use PortableRemoteObject.narrow()to resolve the remote object reference obtained from the a JNDI lookup request into its target object type.5. Modify HelloWorldClient.java or UseDataSource.java to use RMI over HTTP tunneling. Hint: Prefix PROVIDER_URL with