Oracle® Application Server Containers for J2EE Services Guide
10g Release 2 (10.1.2) for Windows or UNIX B14012-02 |
|
Previous |
Next |
This chapter describes Oracle Application Server Containers for J2EE (OC4J) support for allowing EJBs to invoke one another across OC4J containers using the proprietary Remote Method Invocation (RMI)/Oracle RMI (ORMI) protocol.
This chapter covers the following topics:
Java Remote Method Invocation (RMI) enables you to create distributed Java-based to Java-based applications, in which the methods of remote Java objects can be invoked from other Java virtual machines (JVMs), possibly on different hosts.
By default, OC4J EJBs exchange RMI calls over the Oracle Remote Method Invocation (ORMI) protocol, an Oracle proprietary protocol optimized for use with OC4J.
Alternatively, you can convert an EJB to use RMI/IIOP, making it possible for EJBs to invoke one another across different EJB containers as described in Chapter 6, "J2EE Interoperability".
Note: For the OC4J 10g Release 2 (10.1.2) implementation, load balancing and failover are supported only for ORMI, not IIOP. |
ORMI is enhanced for OC4J and provides the following features:
Using ORMI, OC4J can process at a very high transaction rate. This is reflected in Oracle's SpecJ Application Server benchmarks at:
http://www.spec.org/
One way ORMI achieves this performance is by using messages that are much smaller than IIOP messages. Smaller messages take less bandwidth to send and receive, and less processing time to encode and decode. ORMI message size is further reduced by optimizing how much state information is exchanged between client and server. Using ORMI, some state is cached on the server so that it does not need to be transmitted in every RMI call. This does not violate the RMI requirement to be stateless because in the event of a failover, the client code resends all the state information required by the new server.
ORMI is tightly coupled with the OC4J threading model to take full advantage of its queuing, pooling, and staging capabilities.
ORMI uses one thread per client. For multi-threaded clients, OC4J multiplexes each call through one connection. However, OC4J does not serialize them, so multiple threads do not block each other.
This feature ensures that each client (single-threaded or multi-threaded) has one connection to the remote server.
To access EJBs, do the following on the client-side:
Download the oc4j_client.zip
file from
http://www.oracle.com/technology/software/products/ias/devuse.html
Unzip it into a client-side directory (for example, d:\oc4jclient
)
Add d:\oc4jclient\oc4jclient.jar
to your CLASSPATH
The oc4j_client.zip
file contains all the JAR files required by the client (including oc4jclient.jar
and optic.jar
). These JAR files contain the classes necessary for client interaction. You must add only oc4jclient.jar
to your CLASSPATH, because all other JAR files required by the client are referenced in the oc4jclient.jar
manifest classpath.
If you download this file into a browser, then you must grant certain permissions as described in the "Granting Permissions" section of the Security chapter in the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide.
You can configure OC4J for RMI in one of two ways:
Oracle recommends that you configure OC4J using the Oracle Enterprise Manager 10g.
After OC4J is configured for RMI, you must specify RMI properties as described in "RMI Configuration Files".
Oracle recommends that you configure OC4J to use RMI by using Oracle Enterprise Manager 10g as follows:
Navigate to an OC4J instance in which you want to allow access to applications through RMI.
Figure 5-1 shows an OC4J instance called home
.
Figure 5-1 Oracle Enterprise Manager 10g System Components
Click the OC4J instance name.
Click the Administration tab.
Click Server Properties.
By default, RMI is disabled in an Oracle Application Server environment. To enable RMI, set a unique RMI port (or port range) for each OC4J instance by entering the value in the RMI Ports field, as shown in Figure 5-2.
Figure 5-2 Oracle Enterprise Manager 10g Server Properties Port Configuration
Click Apply.
Click the Back button on your browser.
Click Replication Properties.
Check the Replicate State field as shown in Figure 5-3.
The remaining attributes on the EJB Applications screen are ignored if Replicate State is not checked.
Figure 5-3 Oracle Enterprise Manager 10g Replication Properties
Configure the RMI Server Host field as shown in Figure 5-3.
Enter a particular host name or IP address from which your server will accept RMI requests. The OC4J server accepts only RMI requests from this particular host.
Note: The other attributes on the Replication Properties window apply only to EJB clustering. For details, see the section "Configure the Multicast Address for EJB Clustering" in the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide. |
Click Apply.
Oracle recommends that you configure OC4J using the Oracle Enterprise Manager 10g as described in "Configuring RMI Using Oracle Enterprise Manager 10g". If you choose to manually configure RMI, you must:
Edit the property file server.xml
. See "Editing server.xml".
Choose the configuration files appropriate for your environment:
In an OC4J standalone environment, edit the rmi.xml
file (see "Editing rmi.xml") only.
In an Oracle Application Server environment, edit both the rmi.xml
file (see "Editing rmi.xml") and the opmn.xml
file (see "Editing opmn.xml").
Note: In an Oracle Application Server environment,opmn selects an RMI port for each OC4J instance from the range of RMI ports defined in the opmn.xml file (see "Editing opmn.xml"); the rmi.xml file rmi-server element port attribute is ignored.
Manual changes to configuration files in an Oracle Application Server environment are not applied until you synchronize the configuration repository by running the following on the Oracle Application Server command line: |
Your server.xml
file must specify the path name of the RMI configuration file in the <rmi-config>
element. Here is the syntax:
<rmi-config path="RMI_PATH" />
The usual RMI_PATH
is ./rmi.xml
; you can name the file whatever you like.
In an Oracle Application Server environment only, apply changes by running the following on the Oracle Application Server command line:
dcmctl updateConfig
Edit the rmi.xml
file to specify which host, port, and user name and password to use to connect to (and accept connections from) remote RMI servers by configuring an rmi-server
element.
To configure the rmi.xml
file:
Add an rmi-server
element for this local RMI server.
For example:
<rmi-server host="hostname" port="port"> </rmi-server>
Here are the user-replaceable attributes of the <rmi-server>
element:
hostname
: the host name or IP address from which the RMI server accepts RMI requests. If you omit this attribute, the RMI server accepts RMI requests from any host.
port
: the port number on which the RMI server listens for RMI requests.
Note: In an OC4J standalone environment, if you omit this attribute, it defaults to 23791.In an Oracle Application Server environment, |
Configure the rmi-server
element with zero or more server
elements that each specify a remote (point-to-point) RMI server that your application can contact over RMI.
For example:
<rmi-server host="hostname" port="port"> <server host="serverhostname" username="username" port="serverport" password="password"/> </rmi-server>
The host
attribute is required; the remaining attributes are optional. Here are the user-replaceable attributes of the server
element:
serverhostname
: the host name or IP address on which the remote RMI server listens for RMI requests
username
: the user name of a valid principal on the remote RMI server
serverport
: the port number on which the remote RMI server listens for RMI requests
password
: the password used by the principal username
Configure the rmi-server
element with zero or more log
elements that each specify a file to which RMI-specific notifications are written.
For example, using the file
element:
<rmi-server host="hostname" port="port"> <log> <file path="logfilepathname" /> </log> </rmi-server>
Or using the odl
element:
<rmi-server host="hostname" port="port"> <log> <odl path="odlpathname" max-file-size="size" max-num-files="num"/> </log> </rmi-server>
You can use either the file
element or the odl
element (but not both).
Here are the user-replaceable attributes of the log
element:
odlpathname
: the path and folder name of the log folder for this area. You can use an absolute path or a path relative to the J2EE_HOME
/config
directory. This denotes where the RMI log files will reside.
size
: the maximum size in bytes of each individual log file.
num
: the maximum number of log files.
logfilepathname
: the path name of a log file (logfilepathname
) to which the server writes all RMI requests.
The <odl>
element is new in the OC4J 10g Release 2 (10.1.2) implementation. The ODL log entries are each written out in XML format in its respective log file. The log files have a maximum limit. When the limit is reached, the log files are overwritten.
When you enable ODL logging, each message goes into its respective log file, named logN.xml
, where N
is a number starting at 1. The first log message starts the log file log1.xml
. When the log file size maximum is reached, the second log file, named log2.xml
, is opened to continue the logging. When the last log file is full, the first log file, log1.xml
, is erased and a new one is opened for the new messages. Thus, your log files are constantly rolling over and do not encroach on your disk space.
For more information about ODL logging, see the Oracle Application Server Containers for J2EE User's Guide.
In an Oracle Application Server environment only, apply changes by running the following on the Oracle Application Server command line:
dcmctl updateConfig
In an Oracle Application Server environment, edit the opmn.xml
file to specify the port range on which this local RMI server listens for RMI requests.
To configure the opmn.xml
file:
Configure the rmi
port range using the port id="rmi"
element as shown in the following example opmn.xml
file excerpt:
<ias-component id="OC4J"> <process-type id="home" module-id="OC4J"> <port id="ajp" range="3301-3400" /> <port id="rmi" range="3101-3200" /> <port id="jms" range="3201-3300" /> <process-set id="default-island" numprocs="1"/> </process-type> </ias-component>
For more information on configuring the opmn.xml
file, see the Oracle Application Server Administrator's Guide.
Apply changes by running the following on the Oracle Application Server command line:
dcmctl updateConfig
Before EJBs can communicate, you must configure the parameters in the configuration files listed in Table 5-1.
Table 5-1 RMI Configuration Files
Context | File | Description |
---|---|---|
Server | server.xml
|
The <sep-config> element in this file specifies the path name, normally internal-settings.xml , for the server extension provider properties. Example:
|
Application | jndi.properties
|
This file specifies the URL of the initial naming context used by the client. See "JNDI Properties for RMI". |
This section summarizes JNDI properties specific to RMI/ORMI. For details, see "Accessing the EJB" in the EJB Primer chapter in Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide.
The following RMI/ORMI properties are controlled by the jndi.properties
file:
java.naming.provider.url
(see "Naming Provider URL")
java.naming.factory.initial
(see "Context Factory Usage")
Use the following syntax to set thejava.naming.provider.url
:
<prefix>://<host>:<port>:<oc4j_instance>/<application-name>
Table 5-2 describes arguments used in this syntax.
Table 5-2 Naming Provider URL
Variable | Description |
---|---|
prefix
|
Use opmn:ormi for Oracle Application Server applications.
Use Use Use |
host
|
For Oracle Application Server applications, the name of the OPMN host as defined in the opmn.xml file. Although OPMN is often located on the same node as the OC4J instance, specify the host name in case it is located on another machine.
For standalone OC4J applications, the port number defined by the |
port
|
In Oracle Application Server 10g Release 2 (10.1.2), when the opmn:ormi prefix is used, specify the request port on which the opmn process is listening, and the opmn process will forward RMI requests to the RMI port that it selected for the appropriate OC4J instance (see "Using the opmn Request Port"). If omitted, the default request port value 6003 is used.
In Oracle Application Server implementations before 10g Release 2 (10.1.2), when the For standalone OC4J applications, when the For applications that use HTTP tunneling and use the For applications that must interoperate with non-OC4J containers and use the |
oc4j_instance
|
For Oracle Application Server applications, the name of the OC4J instance as defined in the Enterprise Manager.
For standalone OC4J applications, this is not applicable. |
application-name
|
The name of your application. |
For example:
java.naming.provider.url=opmn:ormi://localhost:oc4j_inst1/ejbsamples
In Oracle Application Server 10g Release 2 (10.1.2), you can specify the port defined for the request
attribute of the notification-server
element's port
element configured in the opmn.xml
file (default: 6003). When opmn
receives an RMI request on its request
port, it forwards the RMI request to the RMI port that it selected for the appropriate OC4J instance.
For example, consider the following opmn.xml
file excerpt:
<notification-server> <port local="6100" remote="6200" request="6004"/> <log-file path="$ORACLE_HOME/opmn/logs/ons.log" level="4" rotation-size="1500000"/> <ssl enabled="true" wallet-file="$ORACLE_HOME/opmn/conf/ssl.wlt/default"/> </notification-server>
In this example, the port defined for the request
attribute of the notification-server
element's port
element is 6004, so you would use 6004 as the port in your JNDI naming provider URL.
For an example of how this URL is used, see "OC4J in Oracle Application Server Since 9.0 4".
To determine what RMI port has been selected by opmn
for each OC4J instance, use the following command on the host on which opmn
is running:
opmnctl status -l
This outputs a table of data with one row per OC4J instance.
For example (some columns are omitted for clarity):
Processes in Instance: core817.dsunrdb22.us.oracle.com -------------------+--------------------+-------+ ... +------ ias-component | process-type | pid | ... | ports -------------------+--------------------+-------+ ... +------ WebCache | WebCacheAdmin | 28821 | ... | administration:4000 WebCache | WebCache | 28820 | ... | statistics:4002,invalidation:4001,http:7777 OC4J | home | 2012 | ... | iiop:3401,jms:3701,rmi:3201,ajp:3000 HTTP_Server | HTTP_Server | 28818 | ... | http2:7200,http1:7778,http:7200 dcm-daemon | dcm-daemon | 28811 | ... | N/A LogLoader | logloaderd | N/A | ... | N/A
The ports
column of this table lists the ports selected by opmn
. For example:
iiop:3401,jms:3701,rmi:3201,ajp:3000
In this example, opmn
has selected port 3201 for RMI on the OC4J instance, with process id 2012, so you would use 3201 as the port in your JNDI naming provider URL for this OC4J instance.
The initial context factory creates the initial context class for the client.
Set thejava.naming.factory.initial
property to one of the following:
The ApplicationClientInitialContextFactory
is used when looking up remote objects from standalone application clients. It uses the refs
and ref-mappings
found in application-client.xml
and orion-application-client.xml
. It is the default initial context factory when the initial context is instantiated in a Java application.
Note: If you access an EJB in an application from an EJB in a different application, then you cannot use the RMIInitialContextFactory object. In this scenario, you must use a parent-child relationship between these applications, and you must use the default initial context factory object. bug 2812150 |
The RMIInitialContextFactory
is used when looking up remote objects between different containers using the ORMI protocol.
The type of initial context factory that you use depends on who the client is:
If the client is a pure Java client outside the OC4J container, then use the ApplicationClientInitialContextFactory
class.
If the client is an EJB or servlet client within the OC4J container, then use the ApplicationInitialContextFactory
class. This is the default class; thus, each time you create a new InitialContext
without specifying an initial context factory class, your client uses the ApplicationInitialContextFactory
class.
If the client is an administrative class that is going to manipulate or traverse the JNDI tree, then use the RMIInitialContextFactory
class.
If the client is going to use DNS load balancing, then use the RMIInitialContextFactory
class.
This section provides examples of how to look up an EJB in:
The following example shows how to look up an EJB called MyCart
in the J2EE application ejbsamples
deployed in a standalone OC4J instance. The application is located on a node named localhost,
configured to listen on RMI port 23792:
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, "welcome"); env.put(Context.PROVIDER_URL, "ormi://localhost:23792/ejbsamples"); Context context = new InitialContext(env); Object homeObject = context.lookup("MyCart"); CartHome home = (CartHome)PortableRemoteObject.narrow(homeObject,CartHome.class);
In an OC4J instance in an Oracle Application Server environment, RMI ports are assigned dynamically, and JAZNUserManager
is the default user manager.
In Oracle Application Server releases before 10g Release 2 (10.1.2), if you are accessing an EJB in Oracle Application Server, you have to know the RMI ports assigned by opmn
. If you have only one JVM for your OC4J instance, then you have to limit the port ranges for RMIs to a specific number, for example: 3101-3101.
The following example shows how to look up an EJB called MyCart
in the J2EE application ejbsamples
in an Oracle Application Server environment in releases before 10g Release 2 (10.1.2). The application is located on a node named localhost
configured to listen on RMI port 3101:
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.evermind.server.rmi.RMIInitialContextFactory"); env.put(Context.SECURITY_PRINCIPAL, "jazn.com/admin"); env.put(Context.SECURITY_CREDENTIALS, "welcome"); env.put(Context.PROVIDER_URL, "ormi://localhost:3101/ejbsamples"); Context context = new InitialContext(env); Object homeObject = context.lookup("MyCart"); CartHome home = (CartHome)PortableRemoteObject.narrow(homeObject,CartHome.class);
You can use the following type of lookup in the URL to look up an EJB in an Oracle Application Server environment without needing to know the RMI port assigned to your OC4J instance.
The following example shows how to look up the EJB named MyCart
in the J2EE application ejbsamples
in an Oracle Application Server 10g Release 2 (10.1.2) environment. The EJB application is located on a node named localhost
. The differences between this invocation and the standalone invocation are: the opmn
prefix to ormi
, the specification of the OC4J instance name oc4j_inst1
to which the EJB application is deployed, and no requirement to specify the RMI port:
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.evermind.server.rmi.RMIInitialContextFactory"); env.put(Context.SECURITY_PRINCIPAL, "jazn.com/admin"); env.put(Context.SECURITY_CREDENTIALS, "welcome"); env.put(Context.PROVIDER_URL,"opmn:ormi://localhost:oc4j_inst1/ejbsamples"); Context context = new InitialContext(env); Object homeObject = context.lookup("MyCart"); CartHome home = (CartHome)PortableRemoteObject.narrow(homeObject,CartHome.class);
When EJBs communicate across firewalls, they can use tunneling to transmit RMI across HTTP. This tunneling is supported only with RMI/ORMI; you cannot perform HTTP tunneling with RMI/IIOP.
To configure OC4J to support RMI tunneling, do the following:
Verify that the following entries are in global-web-application.xml
(the default installation has these entries preconfigured):
<servlet> <servlet-name>rmi</servlet-name> <servlet-class>com.evermind.server.rmi.RMIHttpTunnelServlet </servlet-class> </servlet> <servlet> <servlet-name>rmip</servlet-name> <servlet-class>com.evermind.server.rmi.RMIHttpTunnelProxyServlet </servlet-class> </servlet>
Modify the JNDI provider URL (see "JNDI Properties for RMI"). The JNDI provider URL for accessing the OC4J EJB server takes the form:
ormi://hostname:ormi_port/appName
To direct tunneling requests to the home instance of OC4J in an Oracle Application Server or standalone environment, set the URL to:
http:ormi://hostname:http_port/appName
To direct tunneling requests to an instance mapped in an OC4J mount point in an Oracle Application Server environment only, configure oc4j_mount
(see "Configuring an OC4J Mount Point") and set the URL to:
http:ormi://hostname:http_port/appName@oc4j_mount
Note: http_port is the HTTP port, not the ORMI port (if omitted, it defaults to 80), and appName is the name of the application, not the application context defined in web-site.xml .
|
If your HTTP traffic goes through a proxy server, specify the proxyHost
and (optionally) proxyPort
in the command line that starts the EJB client:
-Dhttp.proxyHost=proxy_host -Dhttp.proxyPort=proxy_port
Note: If omitted,proxy_port defaults to 80.
|
An OC4J mount point is used to direct tunneling requests to an OC4J instance other than the home instance of OC4J. To route incoming requests, Oracle HTTP Server (OHS) utilizes a list of application-specific mount points that map the URL supplied in a request with the OC4J instance that will service the request. The list of application mount points is defined in the mod_oc4j configuration file, mod_oc4j.conf
. Mount points are typically defined at the time an application is deployed.
Note: For this to work, you must have a web module deployed or you must use a valid context root in the context instance. Using a placeholder web module has the advantage of removing any dependency on an existing web module that might be removed or modified, thereby affecting the client connection. |
Here is an example of such a mapping:
Oc4jMount /xyz inst1 Oc4jMount /xyz/* inst1
In this example, the OC4J instance inst1
receives all requests with URLs that start with /xyz
.
The first part of "Configuring ORMI Tunneling through HTTP" shows the following URL:
http:ormi://hostname:http_port/appName@oc4j_mount
In this URL:
http_port
is the HTTP port, not the ORMI port.
appName
is the name of the application (defined by default-web-site.xml
attribute name
). It is not the application context (defined by default-web-site.xml
attribute application
).
Make sure that the context root for appName
in the default-web-site.xml
file is the same as that in the mod-oc4j.conf
file. In this example, the application name is demoApp
and its context root is /xyz
. The actual line in the default-web-site.xml
file for this application would be:
<default-web-app application="default" name="demoApp" root="/xyz" />
oc4j_mount
is the OC4J instance to which requests are to be routed.
Therefore, in this example, to direct tunneling requests from defaultWebApp
to OC4J instance inst1
, the URL would be:
http:ormi://hostname:http_port/defaultWebApp@xyz
The mod-oc4j.conf
file is a component of the Oracle HTTP server. For more information, see the Oracle HTTP Server Administrator's Guide.
The default-web-site.xml
file is an OC4J configuration file. For more information, see the Oracle Application Server Containers for J2EE Servlet Developer's Guide.
Caution.: When you change these configuration files manually, the changes do not take effect until you restart the OC4J instance. If you make the changes in the Application Server Control Console, then the changes take effect immediately. In this case, it is not necessary to restart the OC4J instance. |
Here are the steps used to configure ORMI over HTTP in a clustered application in conjunction with the information already provided in this chapter.
Create a placeholder web application. This only needs to be a WAR file that contains a WEB-INF
directory with a basic web.xml file. No actual JSP, servlet, or other files are needed.
Add the empty distributable
tag to the web.xml
file. For example,
<description> A placeholder web.xml file to be used to implement HTTP tunnel ORMI connection for the EJB application.</description> <distributable /> ...
Include the web module in the application.xml
file.
<module> <web> <web-uri>placeholder.war</web-uri> <context-root>/tunnel</context-root> </web.> </module>
This assumes that the WAR file is placeholder.war
and the context root is /tunnel
.
Configure the OC4J instances for replication as documented in the Oracle Application Server High Availability Guide.
Configure both the Web Application and the EJB Application section.
Package and deploy your new EAR file with the place holder WAR file.
If using a manually-configured cluster, then you must deploy to each OC4J instance.
Make sure the client uses the following URL:
http:ormi://host.domain:http_port/<appname>@<contextroot>
where <contextroot>
is the tunnel for this example and <appname>
is the name provide when you deploy the EAR file for this application.
Failover will now work as expected.
Note: If the application already contains a web module, then you can configure this module to be distributable and use its context root using these same steps. However, this method will prevent any changes to the web module from affecting the client configuration. For example, if the developer decides to change the context root you must also implement the change in the client connection information. |