JCA 1.5: Choices are not Always a Good Thing
In JCA 1.5 Inbound Connection (IC) is added allowing developers to invoke Message Driven Beans (MBD) with other types of messages than JMS like emails, files etc. When a MDB is deployed using an IC the application server is calling endpointActivation() on the Resource Adapter (RA). This is the point when a RA can start sending messages to the MDB. The application server is providing a Message Endpoint Factory (MEF) to the RA so that it can create Message Endpoints (ME) acting as a proxy of the MDB to be invoked. This proxy implements the interface of the MDB and so works like a local interface of a Stateless Session Bean (SLSB).
Because the MDB works more or less like a SLSB MDB instances are pooled and used only for the duration of an invocation on the interface. So an invocation of a MDB could be delayed if there is no MDB instance available in the pool. The JCA specification leave the application server the choice to either throw an exception when no instance is available when the ME is created or to block the invocation on the ME. But this leaves the RA developer in limbo and is quit a headache also due the inability of the specification to provide enough information to separate an empty pool for another, maybe permanent, failure.
When a RA creates an Endpoint on the MEF it can throw an UnavailableException if something goes wrong but it has no information if this is a permanent or temporary failure that is vendor neutral. So, for example SunOne, is throwing immediately an UnavailableException when the MDB pool is depleted. Personally, I think this is not a good thing because a depleted pool is a natural state of a pool and not an exception. Other application server block the invocation on the ME until a MDB instance becomes available preventing the RA to react on a depleted pool.
I would like to see some changes on the MEF/ME specification:
- createEndpoint() should not throw an UnavailableException when the MDB pool is depleted
- MEF/ME should have a timeout attribute specifying a timeout when a MDB pool is depleted (either on the creation or invocation of the ME)
- createEndpoint() and the invocation on the ME should throw a Timeout Exception if a MDB instance does not become available so that the RA can react on that
A timeout exception would give the RA the information to schedule further invocations on the ME correctly. A timeout on createEndpoint() would allow the thread to sleep for a certain period to avoid trashing the system with a ton of exception thrown. A timeout on the invocation on the ME would allow the RA to choose another route of actions when no MDB is available.
Have fun - Andy