Continuing with the posts about outbound JCA connectors lets have a quick look at one of the main flows of an outbound JCA connector: the connection request flow.
By now you might be wondering: “What on earth is responsible for making my connectors poolable? Is there any dark magic involved?”.
First answer: “the ConnectionManager” and second answer: “Yes and it is container dependant!”. That’s the reason you should keep an instance of the ConnectionManager inside your ConnectionFactory when it is created, that’s how you delegate the connection creation to the pooling implementation of the container.
Enough explanation let’s have a look on a sequence diagram for a connection creation when we have no connections inside the pool.
First flow: connection request with no matching connections
First thing to take note, it is up to you to implement the matchManagedConnections, I’ve put a note on the next diagram that might help on this implementation: making the ManagedConnection be able to compare itself to a ConnectionRequestInfo makes the things easier. Also beaware that some Application Servers (eg.: WebSphere) skip the matchManagedConnections part if it detects by itself that the pool is empty or there isn’t any matching connection.
Another point about the specification is that it states that a single managed connection may be responsible for more than a single physical connection (FooConnectionImpl), this is required for scenarios where connection sharing is possible (refer to section 184.108.40.206 of the specification).
Previously I tried implementing using a single handle but I noticed that it does not take much effort to make it fully adherent, in fact, it is only necessary to use a delegate (FooConnectionHandle) that implements the FooConnection interface and delegates almost all the methods to the FooConnectionImpl instance that is inside the FooManagedConnection instance (refer to sections 220.127.116.11 and 6.8.1 of the specifications). The exception to the delegation is the close method that your connection must provide, this method in the delegate will be responsible for raising the Connection Closed Event, this is the way you signal the container that you are giving the connection back to the pool.
Second flow: connection request when there are matching connections inside the pool.
This flow is executed whenever the container guesses there are potential matching connections. The matchManagedConnection method is invoked with the minimal connection set that the container can identify. The connection set is a key point: specification states that the container is responbile for determining the minimal set that has a potential match to avoid degrading performance while looking for the connection. Also I noticed that some containers don’t check the connections inside this Set before sending them for matching.
Here are some decisions that might help on the implementation of the ManagedConnection and ManagedConnectionFactory.
- Store the ConnectionRequestInfo that was passed to the ManagedConnectionFactory on the creation of the ManagedConnection as an attribute inside the ManagedConnection this leads to the next tip
- Use the ConnectionRequestInfo stored in the ManagedConnection as argument to an overload of the equals method of the ManagedConnection class this helps in the implementation of the matchManagedConnection method
- Never ever forget to include your ManagedConnection object on equals(Object) method implementation. The tip above may lead you to forget this details. Dont do this under any circumstance since specification requires this and some containers freak out after some use time if this method is not implemented (connection borrow time goes all way up if not implemented)
Next post I’ll focus on how to signal the container that something went wrong with the connection and how to validate the connection before it is returned to the requestor.