BEA Home | Events | Solutions | Partners | Products | Services | Download | Developer Center | WebSUPPORT
| WebLogic Server Doc Home | J2EE Connector Architecture | Previous Topic | Next Topic | Contents | View as PDF

Workarounds for Common BEA J2EE Connector Architecture Exceptions

This document provides solutions for two common WebLogic J2EE connector exceptions and provides workarounds for these exceptions:

- Problem Granting Connection Request to a ManagedConnectionFactory That Does Not Exist in Connection Pool

- ClassCastException

- ResourceAllocationException

Problem Granting Connection Request to a ManagedConnectionFactory That Does Not Exist in Connection Pool

The ConnectionPoolManager's getConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cxInfo) method throws this exception internal to WebLogic Server when it is unable to find a ConnectionPool associated with a given ManagedConnectionFactory.

What Causes This Exception? How Can it Be Resolved?

Two causes exist for this exception, as well as one related behavior, which can be confusing:

- Cause Number One: Client-modified ManagedConnectionFactory is Not Hashed on the Server Such That It Can Be Found Again on Subsequent Lookups

- Cause Number Two: A Client is Attempting to Use a Resource Adapter from a Remote JVM

- Related Behavior: Client-side Mutators Do Not Work as Expected

Cause Number One: Client-modified ManagedConnectionFactory is Not Hashed on the Server Such That It Can Be Found Again on Subsequent Lookups

This issue is caused by a combination of the basic behavior of Hashtables in Java and how Serializable objects work with JNDI.

Hashtables allow arbitrary key-value pairs to be stored in memory and found quickly later using the key from the key-value pair. When a key and its associated object is written into a Java Hashtable, the key's hashCode() method is invoked to obtain an integer value that is not guaranteed to be unique but is guaranteed to be well distributed with respect to all of the Hashtable keys.

This hashing occurs once when an object is written into the Hashtable. The server writes this object into the data structure with the purpose of later using this same derived integer value repeatedly as a method for finding a small candidate set of matching keys quickly.

When the server performs a subsequent lookup into the Hashtable, it hashes the requested key using its overridden hashCode() method or the one found in java.lang.Object. Note that the default hashCode() method simply returns the memory address of the object whose hashCode() method was invoked. It then obtains the set of keys in the backing data structure whose hashed values match the lookup key's hashed key value. Then, the implementation iterates through this candidate list and determines whether there is an appropriate match by executing the following code:

>     for (Entry e = tab[index] ; e != null ; e = e.next) {

>         if ((e.hash == hash) && e.key.equals(key)) {

>             return e.value;

>         }

>     }

>     return null;

This code compares the lookup key to each candidate list by calling the equals() method on each candidate key. If it finds a match, it returns the value. If it falls through the loop without finding a match, it returns a null value.

Consider the object interactions in the deployment of a resource adapter and a JNDI lookup of a resource adapter's ConnectionFactory implementation when the application server only supports Serializable JNDI entries (as opposed to Referencable entries). On deployment of a resource adapter, the application server creates an instance of the ManagedConnectionFactory associated with that resource adapter. The server further associates its ConnectionManager implementation with the ManagedConnectionFactory it just created.

Next, the ManagedConnectionFactory creates an instance of the ConnectionFactory and the ConnectionFactory associates itself with its ManagedConnectionFactory (MCF). At this point, the critical triad of resources is set up. Internally, this link is represented as a pair of Hashtables—one that maps JNDI names to MCFs (jndiToMCFMap) and another that maps MCFs to internal representations of connection pools (poolTable). The ConnectionManager is implicit to the application server so no explicit mapping is required.

The ConnectionFactory (what a resource adapter's client sees) has an MCF, and the MCF has a ConnectionManager implementation courtesy of the application server (through the implicit mapping mentioned above). Finally, the ConnectionFactory (the client-facing object) is bound into JNDI. This is where the confusion may occur.

The current WebLogic Server JNDI implementation supports java.io.Serializable objects but not javax.naming.Referenceable ones. When Referenceable objects are bound to JNDI, a reference (containing an endpoint) to the actual object is actually bound to JNDI. The binding does not actually transport the object into the naming tree. When the server binds Serializable objects into the JNDI tree, the object (and all of its referenced Serializable objects) is literally serialized into the tree.

When a client performs a lookup() on its naming context for the ConnectionFactory, the same serialization process happens in reverse. The ConnectionFactory implementation is serialized into the address space of the client. Even if the client is running in the same address space as the JNDI implementation (the server), this serialization takes place. The application component (client) now has a copy of the actual object graph in the JNDI tree.

Note the MCF is serialized to the client as part of the object graph. Suppose a resource adapter's MCF contains fields used to manage the state of the MCF. Further, assume that the MCF's overridden hashCode() and equals() methods take these fields into account. For an example, consider a debug flag.

Note that when the resource adapter is deployed, an entry is made into the jndiToMCFMap Hashtable. Recalling how Hashtables work in Java, the hash is calculated using all fields, including our debug flag since those fields are used in the hashCode() method. When a client performs a JNDI lookup(), it obtains its own copy of the CF (and its MCF).

Next, the client sets the debug flag to true and calls getConnection() on the CF. The CF then calls allocateConnection() on the CM with the MCF and the ConnectionRequestInfo objects as parameters. The CM attempts to look up the MCF in its poolTable Hashtable using the MCF as the key for the lookup. The Java Hashtable implementation hashes the MCF (including the debug flag) to obtain a candidate list of matches in the poolTable Hashtable. Since the internal state of the MCF has changed between the original deploy-time put into the Hashtable and this subsequent lookup, the MCF is not found and the following exception is logged:

Problem granting connection request to a ManagedConnectionFactory which does not exist in connection pool. Check your MCF's hashcode().

Preventing the Manifestation of This Exception

The simplest way to prevent this exception is to have WebLogic Server support JNDI objects that implement the javax.naming.Referenceable interface. This requires no additional work on the part of the resource adapter developer. This functionality is planned for the next major release of the product.

In the meantime, developers can take a number of steps to avoid this exception, depending on the resource adapter's MCF state requirements. The easiest solution is to implement the hashCode() and equals() methods for the resource adapter's MCF. Of course, if you—based on the information in this document—choose to solve the problem in another resource adapter-specific way, that is fine too.

The guideline for implementing hashCode() and equals() is that these methods should only consider the internal state that is absolutely necessary to uniquely identify the resource adapter instance from any other resource adapter instances running in the server. For example, if a resource adapter is built to talk to a mainframe TP instance, then it might consider its host IP address, port, and region in its hashCode() and equals() methods. It is also desirable to have something else in the method that can break a tie between two different types of resource adapters that happen to use the same configuration data. This could be a name, class type, and so on.

Cause Number Two: A Client is Attempting to Use a Resource Adapter from a Remote JVM

Cause number two for this exception is a simpler case. The J2EE Connector Architecture is a model that is—at least for the time being—not intended to be accessed remotely. None of the defined interfaces are remote, and the architected system contracts presume a local relationship between an MCF and a ConnectionManager.

Having said that, the fact that WebLogic Server's J2EE Connector Architecture implementation reports an attempt to access a ConnectionFactory remotely as being a problem with an MFC's hashCode() implementation is a bug and will be fixed in an upcoming release. There will be a better error message.

Related Behavior: Client-side Mutators Do Not Work as Expected

Another side effect of the lack of a Referenceable JNDI implementation is that since there are two copies of the MCF during a client interaction, client-side changes made to an MCF are not reflected on the server side.

Note that during deployment of a resource adapter, WebLogic Server binds an object graph into the JNDI tree. Also, when a client looks up this graph with Naming.lookup(), it obtains a copy of this graph that is serialized—not the original. If a client changes the internal state of an MCF, those changes are not reflected on the server side. Using the debug flag again, if a client executes a setDebug(true) method, that change to the state (debug) of the MCF is local to that client's copy of the MCF and the server-side copy will not share the same state as the client.

ClassCastException

Currently, the WebLogic J2EE Connector Architecture container uses a custom classloader to allow for some extended features related to loading and finding classes used by resource adapters. One problem with the current implementation is that referencing resource adapter classes from WebLogic Server containers such as the Web (servlet/JSP) or EJB containers does not behave intuitively. When performing type comparison and casting, the JVM prepends the classloader that loaded the class to the class type (in other words, com.acb.ra.MyCF is represented internally as RARClassloader@abcdef:com.acb.ra.MyCF). For detailed information, see the Java Language Specification.

The Web and EJB containers use a classloader that is inherited from a WebLogic Server classloader, so it works well with other WebLogic Server resources and is capable of hot deploy and other features. The RARClassLoader—used by the J2EE Connector Architecture—inherits from the Java classloader and is not in the WebLogic hierarchy. This will be fixed at the earliest possible opportunity.

When an application component (running in the Web or EJB container) looks up a ConnectionFactory in JNDI, the returned object is an instance of the object created by the RARClassloader (RARClassloader@abcdef.com.acb.ra.MyCF). The object the application component expects is actually WebLogicClassloader@fedcba:com.acb.ra.MyCF. When you try to assign a variable or cast, a ClassCastException is thrown.

Preventing the Manifestation of This Exception

The most reliable way to avoid this error is to place the resource adapter's classes in the WebLogic Server classpath by adding the path to the resource adapter's classes into the CLASSPATH setting in the startup script for WebLogic Server. This disables the hot deploy and redeploy features that WebLogic Server provides. Again, we recognize that this is not desirable and intend to fix it as soon as possible.

ResourceAllocationException

BlackBoxNoTx > ResourceAllocationException of javax.resource.spi.EISSystemException: SQLException: No suitable driver on createManagedConnection.

The BlackBox resource adapter is a resource adapter that provides a JDBC connection to any database. To avoid this exception, follow these steps to configure this resource adapter to point to a particular database:

1. Make sure that a JDBC connection pool is set up in WebLogic Server for your database.

2. In that RAR, set the CONNECTION_URL configuration property, in the weblogic-ra.xml file, to the appropriate JDBC pool that you configured in step 1 above.

3. Make sure that the database's JAR file is specified on the WebLogic Server classpath.

BEA ships a BlackBox sample that is configured to use Cloudscape as part of the WebLogic 6.1 kit. Refer to the BlackBox sample for an example on how to set up this configuration.

Copyright © 2001 BEA Systems, Inc. All rights reserved. Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.