Skip Headers

Oracle9iAS Containers for J2EE Enterprise JavaBeans Developer's Guide
Release 2 (9.0.3)

Part Number A97677-01
Go To Core Documentation
Core
Go To Platform Documentation
Platform
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

8
Advanced EJB Subjects

This chapter discusses how to extend beyond the basics mentioned in each of the previous chapters. This chapter covers the following subjects:

Accessing EJBs

To access an EJB from a client, you must do the following:

  1. Download the oc4j.jar file. This JAR contains only the classes necessary for client interaction.

  2. Set up JNDI properties for the connection. If the client is a standalone EJB client, you must determine the RMI or JMS port to which the client sends the request. This is denoted in the JNDI properties as well as the opmn.xml file.

  3. Determine which InitialContext you will use for the connection.

  4. Retrieve an EJB using an EJB reference, which is configured in the deployment descriptor.

These subjects are discussed in the following sections:

Within your client code, you retrieve an EJB reference to the target bean in order to execute methods on that bean. In OC4J, you use JNDI to retrieve this reference. Most of the time, you must specify the target bean in an <ejb-ref> element in the originator's XML configuration file that is used in the java:comp/env logical name to designate the target bean to JNDI.

The method for accessing EJBs depends on where your client is located relative to the bean it wants to invoke. Consider the following when implementing the JNDI retrieval of the EJB reference of the bean:

  1. Do you want to set up a logical name for the target bean?

    • Yes: Modify the XML configuration file to set up the <ejb-ref> element with the target bean information. The logical name specified in the <ejb-ref-name> element is used in the JNDI lookup.

    • No: The actual name of the bean is used in the JNDI lookup. This name has been specified in the target bean's XML deployment descriptors in the <ejb-name> element.

  2. Where does the client exist relative to the target bean?

    • Collocated with the target bean? Deployed in the same application? Or is the target bean part of an application that is this client's parent? You do not need to set up any JNDI properties.

    • Otherwise, you must set up JNDI properties. There are two methods for setting up JNDI properties. See "Setting JNDI Properties" for more information

Client Installation of OC4J.JAR

In order to access EJBs, the client-side must download the oc4j.jar file. This JAR contains only the classes necessary for client interaction. If you download this JAR into a browser, you must grant certain permissions. See <<<>>> for a list of these permissions.

EJB Reference Information

Specify the EJB reference information for the remote EJB in the <ejb-ref> element in the application-client.xml, ejb-jar.xml, or web.xml files. A full description or how to set up the <ejb-ref> element is given in "Configuring Environment References".

For example, the following specifies the reference information for the employee example:

<application-client>
        <display-name>EmployeeBean</display-name>
        <ejb-ref>
                <ejb-ref-name>EmployeeBean</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <home>employee.EmployeeHome</home>
                <remote>employee.Employee</remote>
                <local-home>employee.EmployeeLocalHome</local-home>
                <local>employee.EmployeeLocal</local>
        </ejb-ref>
</application-client>

OC4J maps the logical name to the actual JNDI name on the client-side. The server-side receives the JNDI name and resolves it within its JNDI tree.

For more information and examples of the <ejb-ref> element, see "Configuring Environment References".

Setting JNDI Properties

If the client is collocated with the target, exists within the same application as the target, or the target exists within its parent, then you do not need a JNDI properties file. If not, you must initialize your JNDI properties either within a jndi.properties file, in the system properties, or within your implementation, before the JNDI call. The following sections discuss these three options:

To specify credentials within the JNDI properties, see "Specifying Credentials in EJB Clients".

No JNDI Properties

A servlet that is collocated with the target bean automatically accesses the JNDI properties for the node. Thus, accessing the EJB is simple: no JNDI properties are required.

//Get the Initial Context for the JNDI lookup for a local EJB
InitialContext ic = new InitialContext();
//Retrieve the Home interface using JNDI lookup
Object empObject = ic.lookup("java:comp/env/employeeBean");

This is also true if the target bean is in the same application or an application that has been deployed as this application's parent. The default parent is the global application. The children see the namespace of its parent application. This is used in order to share services such as EJBs among multiple applications. See the Oracle9iAS Containers for J2EE User's Guide for directions on how to specify a parent application.

JNDI Properties File

If setting the JNDI properties within the jndi.properties file, set the properties as follows. Make sure that this file is accessible from the CLASSPATH.

Factory
java.naming.factory.initial=
com.evermind.server.ApplicationClientInitialContextFactory
Location

The ORMI default port number is 23791, which can be modified in rmi.xml. Thus, set the URL in the jndi.properties, in one of the two ways:

java.naming.provider.url=ormi://<hostname>/<application-name>

or

java.naming.provider.url=ormi://<hostname>:23791/<application-name>
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>

JNDI Properties Within Implementation

Set the properties with the same values, only with different syntax. For example, JavaBeans running within the container pass their credentials within the InitialContext, which is created to look up the remote EJBs.

To pass JNDI properties within the Hashtable environment, set these as shown below:

Hashtable env = new Hashtable(); 
env.put("java.naming.provider.url", "ormi://myhost/ejbsamples"); 
env.put("java.naming.factory.initial", 
      "com.evermind.server.ApplicationClientInitialContextFactory"); 
env.put(Context.SECURITY_PRINCIPAL, "guest"); 
env.put(Context.SECURITY_CREDENTIALS, "welcome"); 
Context ic = new InitialContext (env); 
Object homeObject = ic.lookup("java:comp/env/employeeBean");

// Narrow the reference to a TemplateHome.
EmployeeHome empHome =
	 (EmployeeHome) PortableRemoteObject.narrow(homeObject,
                                                   EmployeeHome.class);

Configuring RMI or JMS Port for Standalone EJB Clients

OC4J is configured to assign an RMI or JMS port dynamically within set ranges. However, if you have a standalone EJB client, you must know an exact port number to direct your request.

  1. Pick a port number that is not being used by the OC4J process.

  2. Modify the opmn.xml file within the Enterprise Manager Advanced Properties within the OPMN configuration. Change the RMI or JMS range to the specified port number. The following demonstrates setting the RMI port to 3202 in the opmn.xml file:

    <port ajp="..." jms="..." rmi="3202"/>
    
    
  3. Restart the OC4J process to initialize the new port numbers.

  4. Configure the same port number within the JNDI properties within the standalone client. The following demonstrates setting the same RMI port number in the JNDI properties for the EJB client:

    java.naming.provider.url=ormi://myhost:3202/myapp
    

Using the Initial Context Factory Classes

For most clients, set the initial context factory class to ApplicationClientInitialContextFactory. If you are not using a logical name defined in the <ejb-ref> in your XML configuration file, then you must provide the actual JNDI name of the target bean. In this instance, you must use a different initial context factory class, the com.evermind.server.RMIInitialContextFactory class.

Example 8-1 Servlet Accessing EJB in Remote OC4J Instance

The following servlet uses the JNDI name for the target bean: /cmpapp/employeeBean. Thus, this servlet may provide the JNDI properties in an RMIInitialContext object, instead of the ApplicationClientInitialContext object. The environment is initialized as follows:

An Initial Context Factory Specific to DNS Load Balancing

To use round-robin DNS for your incoming load balancing, you must do the following:

  1. Within DNS, map a single host name to several IP addresses. Each of the port numbers must be the same for each IP address. Then, the incoming calls are randomly routed to one of the back-end machines.

  2. Within each client, use the RMILBInitialContextFactory as your initial context. Each client must use this initial context for DNS round-robin load balancing to work properly.

When you perform a successful host name lookup from the name server, the value is cached. DNS load balancing does not occur if every lookup returns the same value from the cache. When you use the RMILBInitialContextFactory in the client, then a new context class is returned on each lookup.

Example 8-2 RMILBInitialContextFactory Example

java.naming.factory.initial=
           com.evermind.server.rmi.RMILBInitialContextFactory
java.naming.provider.url=ormi://DNSserver:23792/applname
java.naming.security.principal=admin
java.naming.security.credentials=welcome
dedicated.rmicontext=true

Accessing an EJB in a Remote Server

If an application is installed in the OC4J server with a JSP or servlet that wants to invoke an EJB in a remote server, do the following:

  1. Deploy the intended EJB with the JSP/servlet in the same application.

  2. Set "remote=true" attribute in the <ejb-module> element in orion-application.xml for the EJB module deployed in the local application. The local EJB will be ignored.

  3. Configure the remote server where the remote EJB has been deployed in the <server> element in rmi.xml. You provide the hostname, port number, username, and password, as follows:

    <server host=<remote_host> port=<remote_port> user=<username> 
    password=<password>
    
    

If multiple servers are configured, the OC4J container will search all remote servers for the intended EJB application. Thus, the JSP or servlet in one OC4J container will invoke an EJB deployed in another OC4J container.

Packaging and Sharing Classes

When you have an EJB or Web application that references other shared EJB classes, you should place the referenced classes in a shared JAR. In certain situations, if you copy the shared EJB classes into WAR file or another application that references them, you may receive a ClassCastException because of a class loader issue. To be completely safe, never copy referenced EJB classes into the WAR file of its application or into another application.

Web application: The Web application copies referenced EJB classes in its WAR file in the same application. As described in the Oracle9iAS Containers for J2EE Servlet Developer's Guide, you can specify where to load the classes from in the <web-app-class-loader> element. However, when executing, the Web application retrieves the EJB bean reference using JNDI, the following may occur:

Separate application: A separate application copies referenced EJB classes into its EAR file. If both applications are executing within the same process and the bean reference is retrieved using JNDI lookup, one of the following occurs:

To avoid this problem, do one of the following:

Entity Bean Concurrency and Database Isolation Modes

In order to avoid resource contention and overwriting each others changes to database tables while allowing concurrent execution, entity bean concurrency and database isolation modes are provided.

Database Isolation Modes

The java.sql.Connection object represents a connection to a specific database. Database isolation modes are provided to define protection against resource contention. When two or more users try to update the same resource, a lost update can occur. That is, one user can overwrite the other user's data without realizing it. The java.sql.Connection standard provides four isolation modes, of which Oracle only supports two of these modes. These are as follows:

You can configure one of these database isolation modes for a specific bean. That is, you can specify that when the bean starts a transaction, the database isolation mode for this bean be what is specified in the OC4J-specific deployment descriptor. Specify the isolation mode on what is important for the bean: parallel execution or data consistency. The isolation mode for this bean is set for the entire transaction.

The isolation mode can be set for each entity bean in the <entity-deployment> element in the isolation attribute. The values can be committed or serializable. The default is committed. To change it to serializable, configure the following in the orion-ejb-jar.xml for the intended bean:

<entity-deployment ...  isolation="serializable"
 ...
</entity-deployment>

There is always a trade-off between performance and data consistency. The serializable isolation mode provides data consistency; the committed isolation mode provides for parallel execution.


Note:

There is a danger of lost updates with the serializable mode if the max-tx-retries element in the OC4J-specific deployment descriptor is greater than zero. The default for this value is three. If this element is set to greater than zero, then the container retries the update if a second blocked client receives a ORA-8177 exception. The retry would find the row unlocked and the update would occur. Thus, the second client's update succeeds and overwrites the first client's update. If you use serializable, you should consider setting the max-tx-retries element to zero for data consistency.


If you do not set an isolation mode, you receive the mode that is configured in the database. Setting the isolation mode within the OC4J-specific deployment descriptor temporarily overrides the database configured isolation mode for the life of the global transaction for this bean. That is, if you define the bean to use the serializable mode, then the OC4J container will force the database to be serializable for this bean only until the end of the transaction.

Entity Bean Concurrency Modes

OC4J also provides concurrency modes for handling resource contention and parallel execution within container-managed persistence (CMP) entity beans. Bean-managed persistence entity beans manage the resource locking within the bean implementation themselves. The concurrency modes configure when to block to manage resource contention or when to execute in parallel.

The concurrency modes are as follows:

To enable the CMP entity bean concurrency mode, add the appropriate concurrency value of "pessimistic", "optimistic", or "read-only" to the locking-mode attribute of the <entity-deployment> element in the OC4J-specific deployment descriptor (orion-ejb-jar.xml). The default is "optimistic". To modify the concurrency mode to pessimistic, do the following:

<entity-deployment ...  locking-mode="pessimistic"
 ...
</entity-deployment>

These concurrency modes are defined per bean and the effects of locking apply on the transaction boundaries.

Parallel execution requires that the pool size for wrapper and bean instances are set correctly. For more information on how to configure the pool sizes, see "Configuring Pool Sizes For Entity Beans".

Exclusive Write Access to the Database

The exclusive-write-access attribute of the <entity-deployment> element states that this is the only bean that accesses its table in the database and that no external methods are used to update the resource. It informs the OC4J instance that any cache maintained for this bean will only be dirtied by this bean. Essentially, if you set this attribute to true, you are assuring the container that this is the only bean that will update the tables used within this bean. Thus, any cache maintained for the bean does not need to constantly update from the back-end database.

This flag does not prevent you from updating the table; that is, it does not actually lock the table. However, if you update the table from another bean or manually, the results are not automatically updated within this bean.

The default for this attribute is false. Because of the effects of the entity bean concurrency modes, this element is only allowed to be set to true for a read-only entity bean. OC4J will always reset this attribute to false for pessimistic and optimistic concurrency modes.

<entity-deployment ...  exclusive-write-access="true"
 ...
</entity-deployment>

Effects of the Combination of Isolation and Concurrency Modes

For the pessimistic and read-only concurrency modes, the setting of the database isolation mode does not matter. These isolation modes only matter if an external source is modifying the database.

If you choose optimistic with committed, you have the potential to lose an update. If you choose optimistic with serializable, you will never lose an update. Thus, your data will always be consistent. However, you can receive an ORA-8177 exception as a resource contention error.

Differences Between Pessimistic and Optimistic/Serializable

An entity bean with the pessimistic concurrency mode does not allow multiple clients to execute the bean instance. Only one client is allowed to execute the instance at any one moment. An entity bean with the optimistic concurrency mode allows multiple instances of the bean implementation to execute in parallel. Setting the database isolation mode to serializable does not allow these multiple bean implementation instances to update the same row at the same time. Thus, the only difference between a pessimistic concurrency bean and an optimistic/serializable bean is where the blocking occurs. A pessimistic bean blocks at the bean instance; the other blocks at the database row.

Affects of Concurrency Modes on Clustering

All concurrency modes behave in a similar manner whether they are used within a standalone or a clustered environment. This is because the concurrency modes are locked at the database level. Thus, even if a pessimistic bean instance is clustered across nodes, the instant one instance tries to execute, the database locks out all other instances.

Configuring Pool Sizes For Entity Beans

You can set the minimum and maximum number of both the following instance pools:

You can set the pool number of each instance type with the following attributes of the <entity-deployment> element.

Techniques for Updating Persistence

By default, the container persists only the modified fields in the bean. At the end of each call, a SQL command is created to update these fields. However, if you want to have all of your persistence fields updated, set the following attribute to false:

<entity-deployment ...  update-changed-fields-only="false"
 ...
</entity-deployment>

If you choose to have all fields updated, the SQL parsing cache is used. The same SQL command is used for each update.

Configuring Environment References

You can create three types of environment elements that are accessible to your bean during runtime: environment variables, EJB references, and resource managers. These environment elements are static and can not be changed by the bean.

ISVs typically develop EJBs that are independent from the EJB container. In order to distance the bean implementation from the container specifics, you can create environment elements that map to one of the following: defined variables, entity beans, or resource managers. This indirection enables the bean developer to refer to existing variables, EJBs, and a JDBC DataSource without specifying the actual name. These names are defined in the deployment descriptor and are linked to the actual names within the OC4J-specific deployment descriptor.

Environment variables

You can create environment variables that your bean accesses through a lookup on the InitialContext. These variables are defined within an <env-entry> element and can be of the following types: String, Integer, Boolean, Double, Byte, Short, Long, and Float. The name of the environment variable is defined within <env-entry-name>, the type is defined in <env-entry-type>, and its initialized value is defined in <env-entry-value>. The <env-entry-name> is relative to the "java:comp/env" context.

For example, the following two environment variables are declared within the XML deployment descriptor for java:comp/env/minBalance and java:comp/env/maxCreditBalance.

<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>
<env-entry>
     <env-entry-name>maxCreditBalance</env-entry-name>
     <env-entry-type>java.lang.Integer</env-entry-type>
     <env-entry-value>10000</env-entry-value>
</env-entry>

Within the bean's code, you would access these environment variables through the InitialContext, as follows:

InitialContext ic = new InitialContext();
Integer min = (Integer) ic.lookup("java:comp/env/minBalance");
Integer max = (Integer) ic.lookup("java:comp/env/maxCreditBalance"));


Notice that to retrieve the values of the environment variables, you prefix each environment element with "java:comp/env/", which is the location that the container stored the environment variable.

If you wanted the value of the environment variable to be defined in the OC4J-specific deployment descriptor, you can map the <env-entry-name> to the <env-entry-mapping> element in the OC4J-specific deployment descriptor. This means that 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.

Figure 8-1 shows how the minBalance environment variable is defined as 500 within the OC4J-specific deployment descriptor.

Figure 8-1 Environment Variable Mapping

Text description of advanc16.gif follows

Text description of the illustration advanc16.gif

Environment References To Other Enterprise JavaBeans

You can define an environment reference to an EJB within the deployment descriptor. If your bean calls out to another bean, you can enable your bean to invoke the second bean using a reference defined within the deployment descriptors. You create a logical name within the EJB deployment descriptor, which is mapped to the concrete name of the bean within the OC4J-specific deployment descriptor.

Declaring the target bean as an environment reference provides a level of indirection: the originating bean can refer to the target bean with a logical name.

To define a reference to another EJB within the JAR or in a bean declared as a parent, you provide the following:

  1. Name--provide a name for the target bean. This name is what the bean uses within the JNDI URL for accessing the target bean. The name should begin with "ejb/", such as "ejb/myEmployee", and will be available within the "java:comp/env/ejb" context.

    • This name can be the actual name of the bean; that is, the name defined within the <ejb-name> element in the <session> or <entity> elements.

    • This name can be a logical name that you want to use in your implementation. But it is not the actual name of the bean. If you use a logical name, the actual name must either be specified in the <ejb-link> element in this <ejb-ref> element or in the <ejb-ref-mapping> element in the OC4J-specific deployment descriptor.

    These options are discussed below.

  2. Type--define whether the bean is a session or an entity bean. Value should be either "Session" or "Entity".

  3. Home--provide the fully qualified home interface name.

  4. Remote--provide the fully qualified remote interface name.

  5. Link--provide a name that links this EJB reference with the actual JNDI URL. This is optional.

If you have two beans in the JAR: BeanA and BeanB. If BeanB creates a reference to BeanA, you can define this reference in one of three methods:

As shown in Figure 8-2, the logical name for the bean is mapped to the JNDI name by providing the same name, "ejb/nextVal", in both the <ejb-ref-name> in the EJB deployment descriptor and the name attribute within the <ejb-ref-mapping> element in the OC4J-specific deployment descriptor.

Figure 8-2 EJB Reference Mapping

Text description of advance4.gif follows

Text description of the illustration advance4.gif

Example 8-3 Defining an EJB Reference Within the Environment

The following example defines a reference to the Hello bean, as follows:

  1. The logical name used for the target bean within the originating bean is "java:comp/env/ejb/HelloWorld".

  2. The target bean is a session bean.

  3. Its home interface is hello.HelloHome; its remote interface is hello.Hello.

  4. The link to the JNDI URL for this bean is defined in the OC4J-specific deployment descriptor under the "HelloWorldBean" name.

    Text description of advance5.gif follows

    Text description of the illustration advance5.gif

As shown in Figure 8-2, the <ejb-link> is mapped to the name attribute within the <ejb-ref-mapping> element in the OC4J-specific deployment descriptor by providing the same logical name in both elements. The Oracle-specific deployment descriptor would have the following definition to map the logical bean name of "java:comp/env/ejb/HelloWorld" to the JNDI URL "/test/myHello".

Text description of advance6.gif follows

Text description of the illustration advance6.gif

To invoke this bean from within your implementation, you use the <ejb-ref-name> defined in the EJB deployment descriptor. In EJB or pure Java clients, you prefix this name with "java:comp/env/ejb/", which is where the container places the EJB references defined in the deployment descriptor. Servlets only require the logical name defined in the <ejb-ref-name>.

The following is a lookup from an EJB client:

InitialContext ic = new InitialContext();
HelloHome hh = (HelloHome)ic.lookup("java:comp/env/ejb/HelloWorld");

The following is a lookup from a Servlet, if the Servlet defines the logical name of "ejb/HelloWorld" in <ejb-ref> in its web.xml file and maps it to the actual name of "/test/myHello" within the orion-web.xml file.

InitialContext ic = new InitialContext();
HelloHome hh = (HelloHome)ic.lookup("ejb/HelloWorld");

Environment References To Resource Manager Connection Factory References

The resource manager connection factory references can include resource managers such as JMS, Java mail, URL, and JDBC DataSource objects. Similar to the EJB references, you can access these objects from JNDI by creating an environment element for each object reference. However, these references can only be used for retrieving the object within the bean that defines these references. Each is fully described in the following sections:

JDBC DataSource

You can access a database through JDBC either using the traditional method or by creating an environment element for a JDBC DataSource. In order to create an environment element for your JDBC DataSource, you must do the following:

  1. Define the DataSource in the data-sources.xml file.

  2. Create a logical name within the <res-ref-name> element in the EJB deployment descriptor. This name should always start with "jdbc". In the bean code, the lookup of this reference is always prefaced by "java:comp/env/jdbc".

  3. Map the logical name within the EJB deployment descriptor to the JNDI name, created in step 1, within the OC4J-specific deployment descriptor.

  4. Lookup the object reference within the bean with the "java:comp/env/jdbc" preface and the logical name defined in the EJB deployment descriptor.

As shown in Figure 8-3, the JDBC DataSource uses the JNDI name "test/OrderDataSource". The logical name that the bean knows this resource as is "jdbc/OrderDB". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve the connection to OrderDataSource by using the "java:comp/env/jdbc/OrderDB" environment element.

Figure 8-3 JDBC Resource Manager Mapping

Text description of advance8.gif follows

Text description of the illustration advance8.gif

Example 8-4 Defining an environment element for JDBC Connection

The environment element is defined within the EJB deployment descriptor by providing the logical name, "jdbc/OrderDB", its type of javax.sql.DataSource, and the authenticator of "Application".

Text description of advance9.gif follows

Text description of the illustration advance9.gif

The environment element of "jdbc/OrderDB" is mapped to the JNDI bound name for the connection, "test/OrderDataSource" within the Oracle-specific deployment descriptor.

Text description of advanc10.gif follows

Text description of the illustration advanc10.gif

Once deployed, the bean can retrieve the JDBC DataSource as follows:

javax.sql.DataSource db;
java.sql.Connection conn;
.
.
.
db = (javax.sql.DataSource) 
initCtx.lookup("java:comp/env/jdbc/OrderDB");
conn = db.getConnection();


Note:

This example assumes that a DataSource is specified in the data-sources.xml file with the JNDI name of "/test/OrderDataSource".


Mail Session

You can create an environment element for a Java mail Session object through the following:

  1. Bind the javax.mail.Session reference within the JNDI name space in the application.xml file using the <mail-session> element, as follows:

    <mail-session location="mail/MailSession"
       smtp-host="mysmtp.oraclecorp.com">
       <property name="mail.transport.protocol" value="smtp"/>
       <property name="mail.smtp.from" value="emailaddress@oracle.com"/>
    </mail-session>
    
    

    The location attribute contains the JNDI name specified in the location attribute of the <resource-ref-mapping> element in the OC4J-specific deployment descriptor.

  2. Create a logical name within the <res-ref-name> element in the EJB deployment descriptor. This name should always start with "mail". In the bean code, the lookup of this reference is always prefaced by "java:comp/env/mail".

  3. Map the logical name within the EJB deployment descriptor to the JNDI name, created in step 1, within the OC4J-specific deployment descriptor.

  4. Lookup the object reference within the bean with the "java:comp/env/mail" preface and the logical name defined in the EJB deployment descriptor.

As shown in Figure 8-4, the Session object was bound to the JNDI name "/test/myMailSession". The logical name that the bean knows this resource as is "mail/testMailSession". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve the connection to the bound Session object by using the "java:comp/env/mail/testMailSession" environment element.

Figure 8-4 Session Resource Manager Mapping

Text description of advance7.gif follows

Text description of the illustration advance7.gif

This environment element is defined with the following information:

Element Description

<res-ref-name>

The logical name of the Session object to be used within the originating bean. The name should be prefixed with "mail/". In our example, the logical name for our ordering database is "mail/testMailSession".

<res-type>

The Java type of the resource. For the Java mail Session object, this is javax.mail.Session.

<res-auth>

Define who is responsible for signing on to the database. The value can be "Application" or "Container" based on who provides the authentication information.

Example 8-5 Defining an environment element for Java mail Session

The environment element is defined within the EJB deployment descriptor by providing the logical name, "mail/testMailSession", its type of javax.mail.Session, and the authenticator of "Application".

Text description of advanc11.gif follows

Text description of the illustration advanc11.gif

The environment element of "mail/testMailSession" is mapped to the JNDI bound name for the connection, "test/myMailSession" within the OC4J-specific deployment descriptor.

Text description of advanc12.gif follows

Text description of the illustration advanc12.gif

Once deployed, the bean can retrieve the Session object reference as follows:

InitialContext ic = new InitialContext();
Session session = (Session) 
ic.lookup("java:comp/env/mail/testMailSession");

//The following uses the mail session object
//Create a message object
MimeMessage msg = new MimeMessage(session);

//Construct an address array
String mailTo = "whosit@oracle.com";
InternetAddress addr = new InternetAddress(mailto);
InternetAddress addrs[] = new InternetAddress[1];
addrs[0] = addr;

//set the message parameters
msg.setRecipients(Message.RecipientType.TO, addrs);
msg.setSubject("testSend()" + new Date());
msg.setContent(msgText, "text/plain");

//send the mail message
Transport.send(msg);

URL

You can create an environment element for a Java URL object through the following:

  1. Create a logical name within the <res-ref-name> element in the EJB deployment descriptor. This name should always start with "url". In the bean code, the lookup of this reference is always prefaced by "java:comp/env/url".

  2. Map the logical name within the EJB deployment descriptor to the URL within the OC4J-specific deployment descriptor.

  3. Lookup the object reference within the bean with the "java:comp/env/url" preface and the logical name defined in the EJB deployment descriptor.

As shown in Figure 8-5, the URL object was bound to the URL "www.myURL.com". The logical name that the bean knows this resource as is "url/testURL". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve the connection to the bound Session object by using the "java:comp/env/url/testURL" environment element.

Figure 8-5 URL Resource Manager Mapping

Text description of advanc13.gif follows

Text description of the illustration advanc13.gif

This environment element is defined with the following information:

Element Description

<res-ref-name>

The logical name of the URL object to be used within the originating bean. The name should be prefixed with "url/". In our example, the logical name for our ordering database is "url/testURL".

<res-type>

The Java type of the resource. For the Java URL object, this is java.net.URL.

<res-auth>

Define who is responsible for signing on to the database. At this time, the only value supported is "Application". The application provides the authentication information.

Example 8-6 Defining an environment element for JDBC Connection

The environment element is defined within the EJB deployment descriptor by providing the logical name, "url/testURL", its type of java.net.URL, and the authenticator of "Application".

Text description of advanc14.gif follows

Text description of the illustration advanc14.gif

The environment element of "url/testURL" is mapped to the URL "www.myURL.com" within the OC4J-specific deployment descriptor.

Text description of advanc15.gif follows

Text description of the illustration advanc15.gif

Once deployed, the bean can retrieve the URL object reference as follows:

InitialContext ic = new InitialContext();
URL url = (URL) ic.lookup("java:comp/env/url/testURL");

//The following uses the URL object
URLConection conn = url.openConnection();

Configuring Security

EJB security involves two realms: granting permissions if you download into a browser and configuring your application for authentication and authorization. This section covers the following:

Granting Permissions in Browser

If you download the EJB application as a client where the security manager is active, you must grant the following permissions before you can execute:

permission java.net.SocketPermission "*:*", "connect,resolve";
permission java.lang.RuntimePermission "createClassLoader";
permission java.lang.RuntimePermission "getClassLoader";
permission java.util.PropertyPermission "*", "read";
permission java.util.PropertyPermission "LoadBalanceOnLookup", 
"read,write";

Authenticating and Authorizing EJB Applications

For EJB authentication and authorization, you define the principals under which each method executes by configuring of the EJB deployment descriptor. The container enforces that the user who is trying to execute the method is the same as defined within the deployment descriptor.

The EJB deployment descriptor enables you to define security roles under which each method is allowed to execute. These methods are mapped to users or groups in the OC4J-specific deployment descriptor. The users and groups are defined within your designated security user managers, which uses either the JAZN or XML user manager. For a full description of security user managers, see the Oracle9iAS Containers for J2EE User's Guide and Oracle9iAS Containers for J2EE Services Guide.

For authentication and authorization, this section focuses on XML configuration within the EJB deployment descriptors. EJB authorization is specified within the EJB and OC4J-specific deployment descriptors. You can manage the authorization piece of your security within the deployment descriptors, as follows:

Users and groups are identities known by the container. Roles are the logical identities each application uses to indicate access rights to its different objects. The username/passwords can be digital certificates and, in the case of SSL, private key pairs.

Thus, the definition and mapping of roles is demonstrated in Figure 8-6.

Figure 8-6 Role Mapping

Text description of advance2.gif follows

Text description of the illustration advance2.gif

Defining users, groups, and roles are discussed in the following sections:

Specifying Users and Groups

OC4J supports the definition of users and groups--either shared by all deployed applications or specific to given applications. You define shared or application-specific users and groups within either the JAZN or XML user managers. See the Oracle9iAS Containers for J2EE User's Guide and Oracle9iAS Containers for J2EE Services Guide. for directions.

Specifying Logical Roles in the EJB Deployment Descriptor

As shown in Figure 8-7, you can use a logical name for a role within your bean implementation, and map this logical name to the correct database role or user. The mapping of the logical name to a database role is specified in the OC4J-specific deployment descriptor. See "Mapping Logical Roles to Users and Groups" for more information.

Figure 8-7 Security Mapping

Text description of advance3.gif follows

Text description of the illustration advance3.gif

If you use a logical name for a database role within your bean implementation for methods such as isCallerInRole, you can map the logical name to an actual database role by doing the following:

  1. Declare the logical name within the <enterprise-beans> section <security-role-ref> element. For example, to define a role used within the purchase order example, you may have checked, within the bean's implementation, to see if the caller had authorization to sign a purchase order. Thus, the caller would have to be signed in under a correct role. In order for the bean to not need to be aware of database roles, you can check isCallerInRole on a logical name, such as POMgr, since only purchase order managers can sign off on the order. Thus, you would define the logical security role, POMgr within the <security-role-ref><role-name> element within the <enterprise-beans> section, as follows:

    
    <enterprise-beans>
    ...
      <security-role-ref>
       <role-name>POMgr</role-name>
       <role-link>myMgr</role-link>
      </security-role-ref>
    </enterprise-beans>
    
    

    The <role-link> element within the <security-role-ref> element can be the actual database role, which is defined further within the <assembly-descriptor> section. Alternatively, it can be another logical name, which is still defined more in the <assembly-descriptor> section and is mapped to an actual database role within the Oracle-specific deployment descriptor.


    Note:

    The <security-role-ref> element is not required. You only specify it when using security context methods within your bean.


  2. Define the role and the methods that it applies to. In the purchase order example, any method executed within the PurchaseOrder bean must have authorized itself as myMgr. Note that PurchaseOrder is the name declared in the <entity | session><ejb-name> element.

    Thus, the following defines the role as myMgr, the EJB as PurchaseOrder, and all methods by denoting the '*' symbol.


    Note:

    The myMgr role in the <security-role> element is the same as the <role-link> element within the <enterprise-beans> section. This ties the logical name of POMgr to the myMgr definition.


    <assembly-descriptor>
     <security-role>
      <description>Role needed purchase order authorization</description>
      <role-name>myMgr</role-name>
     </security-role>
     <method-permission>
      <role-name>myMgr</role-name>
      <method>
       <ejb-name>PurchaseOrder</ejb-name>
       <method-name>*</method-name>
      </method>
     </method-permission>
    ...
    </assembly-descriptor>
    
    

After performing both steps, you can refer to POMgr within the bean's implementation and the container translates POMgr to myMgr.


Note:

If you define different roles within the <method-permission> element for methods in the same EJB, the resulting permission is a union of all the method permissions defined for the methods of this bean.


The <method-permission><method> element is used to specify the security role for one or more methods within an interface or implementation. According to the EJB specification, this definition can be of one of the following forms:

  1. Defining all methods within a bean by specifying the bean name and using the '*' character to denote all methods within the bean, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
    	<ejb-name>EJBNAME</ejb-name>
    	<method-name>*</method-name>
      </method>
    </method-permission>
    
    
  2. Defining a specific method that is uniquely identified within the bean. Use the appropriate interface name and method name, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
    	<ejb-name>myBean</ejb-name>
    	<method-name>myMethodInMyBean</method-name>
      </method>
    </method-permission>
    


    Note:

    If there are multiple methods with the same overloaded name, the element of this style refers to all the methods with the overloaded name.


  3. Defining a method with a specific signature among many overloaded versions, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
    	<ejb-name>myBean</ejb-name>
    	<method-name>myMethod</method-name>
    	<method-params>
    		<method-param>javax.lang.String</method-param>
    		<method-param>javax.lang.String</method-param>
        	</method-params>
      </method>
    </method-permission>
    
    

    The parameters are the fully-qualified Java types of the method's input parameters. If the method has no input arguments, the <method-params> element contains no elements. Arrays are specified by the array element's type, followed by one or more pair of square brackets, such as int[ ][ ].

Specifying Unchecked Security for EJB Methods

If you want certain methods to not be checked for security roles, you define these methods as unchecked, as follows:

<method-permission>
  <unchecked/>
  <method>
     <ejb-name>EJBNAME</ejb-name>
     <method-name>*</method-name>
  </method>
</method-permission>

Instead of a <role-name> element defined, you define an <unchecked/> element. When executing any methods in the EJBNAME bean, the container does not check for security. Unchecked methods always override any other role definitions.

Specifying the runAs Security Identity

You can specify that all methods of an EJB execute under a specific identity. That is, the container does not check different roles for permission to run specific methods; instead, the container executes all of the EJB methods under the specified security identity. You can specify a particular role or the caller's identity as the security identity.

Specify the runAs security identity in the <security-identity> element, which is contained in the <enterprise-beans> section. The following XML demonstrates that the POMgr is the role under which all the entity bean methods execute.

<enterprise-beans>
 <entity>
 ... 
  <security-identity>
     <run-as>
        <role-name>POMgr</role-name>
     </run-as>
  </security-identity>
...
 </entity>
</enterprise-beans>

Alternatively, the following XML example demonstrates how to specify that all methods of the bean execute under the identity of the caller:

<enterprise-beans>
 <entity>
 ... 
  <security-identity>
     <use-caller-identity/>
  </security-identity>
...
 </entity>
</enterprise-beans>

Mapping Logical Roles to Users and Groups

You can use logical roles or actual users and groups in the EJB deployment descriptor. However, if you use logical roles, you must map them to the actual users and groups defined either in the JAZN or XML User Managers.

Map the logical roles defined in the application deployment descriptors to JAZN or XML User Manager users or groups through the <security-role-mapping> element in the OC4J-specific deployment descriptor.

Example 8-7 Mapping Logical Role to Actual Role

This example maps the logical role POMGR to the managers group in the orion-ejb-jar.xml file. Any user that can log in as part of this group is considered to have the POMGR role; thus, it can execute the methods of PurchaseOrderBean.

<security-role-mapping name="POMGR"> 
 <group name="managers" /> 
</security-role-mapping> 


Note:

You can map a logical role to a single group or to several groups.


To map this role to a specific user, do the following:

<security-role-mapping name="POMGR"> 
 <user name="guest" /> 
</security-role-mapping> 

Lastly, you can map a role to a specific user within a specific group, as follows:

<security-role-mapping name="POMGR"> 
 <group name="managers" />
 <user name="guest" /> 
</security-role-mapping> 

As shown in Figure 8-8, the logical role name for POMGR defined in the EJB deployment descriptor is mapped to managers within the OC4J-specific deployment descriptor in the <security-role-mapping> element.

Figure 8-8 Security Mapping

Text description of advancea.gif follows

Text description of the illustration advancea.gif

Notice that the <role-name> in the EJB deployment descriptor is the same as the name attribute in the <security-role-mapping> element in the OC4J-specific deployment descriptor. This is what identifies the mapping.

Specifying a Default Role Mapping for Undefined Methods

If any methods have not been associated with a role mapping, they are mapped to the default security role through the <default-method-access> element in the orion-ejb-jar.xml file. The following is the automatic mapping for any insecure methods:

<default-method-access>
   <security-role-mapping name="&lt;default-ejb-caller-role&gt;"
                          impliesAll="true" />
   </security-role-mapping>
</default-method-access>


The default role is <default-ejb-caller-role> and is defined in the name attribute. You can replace this string with any name for the default role. The impliesAll attribute indicates whether any security role checking occurs for these methods. This attribute defaults to true, which states that no security role checking occurs for these methods. If you set this attribute to false, the container will check for this default role on these methods.

If the impliesAll attribute is false, you must map the default role defined in the name attribute to a JAZN or XML user or group through the <user> and <group> elements. The following example shows how all methods not associated with a method permission are mapped to the "others" group.

<default-method-access>
   <security-role-mapping name="default-role" impliesAll="false" />
      <group name="others" />
   </security-role-mapping>
</default-method-access>

Specifying Users and Groups by the Client

In order for the client to access methods that are protected by users and groups, the client must provide the correct user or group name with a password that the JAZN or XML User Manager recognizes. And the user or group must be the same one as designated in the security role for the intended method. See "Specifying Credentials in EJB Clients" for more information.

Specifying Credentials in EJB Clients

When you access EJBs in a remote container, you must pass valid credentials to this container.

Credentials in JNDI Properties

Indicate the username (principal) and password (credentials) to use when looking up remote EJBs in the jndi.properties file.

For example, if you want to access remote EJBs as POMGR/welcome, define the following properties. The factory.initial property indicates that you will use the Oracle JNDI implementation:

java.naming.security.principal=POMGR
java.naming.security.credentials=welcome
java.naming.factory.initial=
com.evermind.server.ApplicationClientInitialContextFactory java.naming.provider.url=ormi://localhost/ejbsamples

In your application program, authenticate and access the remote EJBs, as shown below:

InitialContext ic = new InitialContext();
CustomerHome = 
(CustomerHome)ic.lookup("java:comp/env/purchaseOrderBean"); 

Credentials in the InitialContext

To access remote EJBs from a servlet or JavaBean, pass the credentials in the InitialContext object, as follows:

Hashtable env = new Hashtable(); 
env.put("java.naming.provider.url", "ormi://localhost/ejbsamples"); 
env.put("java.naming.factory.initial", 
        "com.evermind.server.ApplicationClientInitialContextFactory"); 
env.put(Context.SECURITY_PRINCIPAL, "POMGR"); 
env.put(Context.SECURITY_CREDENTIALS, "welcome"); 
Context ic = new InitialContext (env); 
CustomerHome =  
    (CustomerHome)ic.lookup("java:comp/env/purchaseOrderBean") 

Setting Performance Options

Most performance settings are discussed in the Oracle9i Application Server Performance Guide. This section discusses other performance options.

You can manage these performance settings yourself from either the OC4J command-line option or by editing the appropriate XML file element.

Performance Command-Line Options

Each -D command-line option, except for the dedicated.rmicontext option, defaults to the recommended setting. However, you can modify these options by providing each -D command-line option as an OC4J option. See the Oracle9iAS Containers for J2EE User's Guide for an example.

Thread Pool Settings

You can specify one or two thread pools for an OC4J process through the global-thread-pool element in the server.xml file. If you do not specify this element, then an infinite number of threads can be created.

There are two types of threads in OC4J:

OC4J always maintains a certain amount of worker threads, so that any client connection traffic bursts can be handled.

If you specify a single thread pool, then both short and long lived threads exist in this pool. The risk is that all the available threads in the pool are one type of thread. Then, performance can be poor because of a lack of resources for the other type of thread. However, OC4J always guarantees a certain amount of worker threads, which are normally mapped to short lived threads. If a need for a worker thread arises and no short lived thread is available, the work is handled by a long lived thread.

If you specify two thread pools, then each pool contains one type of thread.

To create a single pool, configure the min, max, queue, and keepAlive attributes. To create two pools, configure the min, max, queue, and keepAlive attributes for the first pool and the cx-min, cx-max, cx-queue, and cx-keepAlive attributes for the second pool.

The global-thread-pool element provides the following attributes:

Table 8-1 The Thread Pool Attributes  
Thread Pool Attributes Description

min

The minimum number of threads that OC4J can simultaneously execute. By default, a minimum number of threads are preallocated and placed in the thread pool when the container starts. Value is an integer. The default is 20. The minimum value you can set this to is 10.

max

The maximum number of threads that OC4J can simultaneously execute. New threads are spawned if the maximum size is not reached and if there are no idle threads. Idle threads are used first before a new thread is spawned. Value is an integer. The default is 40.

queue

The maximum number of requests that can be kept in the queue. Value is an integer. The default is 80.

keepAlive

The number of milliseconds to keep a thread alive (idle) while waiting for a new request. This timeout designates how long an idle thread remains alive. If the timeout is reached, the thread is destroyed. The minimum time is a minute. Time is set in milliseconds. To never destroy threads, set this timeout to a negative one.

Value is a long. The default is 600000 milliseconds.

cx-min

The minimum number of threads that OC4J can simultaneously execute. Value is an integer. The default is 20. The minimum value you can set this to is 10.

cx-max

The maximum number of threads that OC4J can simultaneously execute. Value is an integer. The default is 40.

cx-queue

The maximum number of requests that can be kept in the queue. Value is an integer. The default is 80.

cx-keepAlive

The number of milliseconds to keep a thread alive (idle) while waiting for a new request. This timeout designates how long an idle thread remains alive. If the timeout is reached, the thread is destroyed. The minimum time is a minute. Time is set in milliseconds. To never destroy threads, set this timeout to a negative one.

Value is a long. The default is 600000 milliseconds.

debug

If true, print the application server thread pool information at startup. The default is false.

Recommendations:

Example 8-8 Setting Thread Pool

The following example initializes two thread pools for the OC4J process. Each contains at minimum 10 threads and maximum of 100 threads. The number of requests outstanding in each queue can be 200 requests. Also, idle threads are kept alive for 700 seconds. The thread pool information is printed at startup.

<application-server ...>
...
	<global-thread-pool min="10" max="100" queue="200" 
	keepAlive=700000" cx-min="10" cx-max="100" cx-queue="200" 
	cx-keepAlive=700000" debug="true"/>
...
</application-server>

Statement Caching

You can cache database statements, which prevents the overhead of repeated cursor creation and repeated statement parsing and creation. In the DataSource configuration, you enable JDBC statement caching, which caches executable statements that are used repeatedly. A JDBC statement cache is associated with a particular physical connection. See Oracle9i JDBC Developer's Guide and Reference for more information on statement caching.

You can dynamically enable and disable statement caching programmatically through the setStmtCacheSize() method of your connection object or through the stmt-cache-size XML attribute in the DataSource configuration. An integer value is expected with the size of the cache, which must be a value greater than 60. The cache size you specify is the maximum number of statements in the cache. The user determines how many distinct statements the application issues to the database. Then, the user sets the size of the cache to this number.

If you do not specify this element, this cache is disabled.

Example 8-9 Statement Caching

The following XML sets the statement cache size to 200 statements.

<data-source>
 ...
 stmt-cache-size="200"
</data-source> 

Task Manager Granularity

The task manager is a background process that performs cleanup. However, the task manager can be expensive. You can manage when the task manager performs its duties through the taskmanager-granularity attribute in server.xml. This element sets how often the task manager is kicked off for cleanup. Value is in milliseconds. Default is 1000 milliseconds.

<application-server ...  taskmanager-granularity="60000" ...>

Using DNS for Load Balancing

To use DNS for your incoming load balancing, you can do one of the following:

You must start each OC4J process that is involved in load balancing on separate IP addresses, but with the same port number. Each IP address used must be configured in the DNS server.

Using RMILBInitialContextFactory Object

To retrieve a randomly selected machine from DNS, do the following:

  1. Within DNS, map a single host name to several IP addresses. Each of the OC4J RMI port numbers must be the same for each IP address.

  2. Within each client, use the RMILBInitialContextFactory as your initial context.

Then, the incoming calls are randomly routed to one of the back-end machines.

Example 8-10 RMILBInitialContextFactory Example

java.naming.factory.initial=
           com.evermind.server.rmi.RMILBInitialContextFactory
java.naming.provider.url=ormi://DNSserver:23792/applname
java.naming.security.principal=admin
java.naming.security.credentials=welcome
dedicated.rmicontext=true

Using RMIInitialContextFactory Object

You can choose to use the RMIInitialContextFactory object. In order for DNS round-robin to work properly, you must do the following:

  1. Within DNS, map a single host name to several IP addresses and configure DNS for round-robin lookups. Each of the OC4J RMI port numbers must be the same for each IP address.

  2. Turn off DNS caching on the client. For Solaris machines, you must turn off DNS caching as follows:

    1. Kill the NSCD daemon process on the client.

    2. Start the OC4J client with the -Dsun.net.inetaddr.ttl=0 option.

The incoming calls are routed in a round-robin fashion to one of the back-end machines.

Common Errors

The following are common errors that may occur when executing EJBs:

NamingException Thrown

If you are trying to remotely access an EJB and you receive an javax.naming.NamingException error, your JNDI properties are probably not initialized properly. See "Accessing EJBs" for a discussion on setting up JNDI properties when accessing an EJB from a remote object or remote servlet.

Deadlock Conditions

If the call sequence of several beans cause a deadlock scenario, the OC4J container notices the deadlock condition and throws a Remote exception that details the deadlock condition in one of the offending beans.

ClassCastException

When you have an EJB or Web application that references other shared EJB classes, you should place the referenced classes in a shared JAR. In certain situations, if you copy the shared EJB classes into WAR file or another application that references them, you may receive a ClassCastException because of a class loader issue. To be completely safe, never copy referenced EJB classes into the WAR file of its application or into another application.

See "Packaging and Sharing Classes" for more information.


Go to previous page Go to next page
Oracle
Copyright © 2002 Oracle Corporation.

All Rights Reserved.
Go To Core Documentation
Core
Go To Platform Documentation
Platform
Go To Table Of Contents
Contents
Go To Index
Index