2
votes

Currently I developed a JCA outbound adapter (with LocalTransaction support) and I've got some troubles with connection management. My adapter works well, except the server (WebLogic 12c) does not put the ManagedConnections back to the pool. According to JavaDoc, the server must call ManagedConnection.cleanup() to reinitialize the connection and put it back to the pool, but it does not.

When I use the adapter from EJB, the server creates a new ManagedConnection, begins a new transaction, commits it, but does not call the ManagedConnection.cleanup() method and does not put it back to the pool.

Below you can see my testing bean:

@Stateless(mappedName = "TestingBean")
@Local(value = TestingBeanLocal.class)
@Remote(value = TestingBeanRemote.class)
@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public class TestingBean implements TestingBeanCommon{

@Resource(mappedName = "eis/myJCA")
private MyDataSource dataSource;

@Override
public void performTestAction(String param1, String param2) {
    MyConnection connection = dataSource.getMyConnection();
    connection.performAction(ActionFactory.getSomeAction(param1, param2));
}
}

After 10 invocations I get the following:

Got Initial context javax.ejb.EJBException: EJB Exception: ; nested exception is: java.lang.RuntimeException: javax.resource.spi.ApplicationServerInternalException: Unable to get a connection for pool = "eis/myJCA", weblogic.common.resourcepool.ResourceLimitException: Configured maximum limit of (0) on number of threads allowed to wait for a resource reached for pool eis/myJCA

As you noticed, it uses a new transaction for each invocation (REQUIRES_NEW attribute). The Server creates a new ManagedConnection instance first 10 times and then the connection pool reaches its maximal capacity.

It is clear from tracing the logs that no single call of ManagedConnection.cleanup() occurs and every connection in the pool is busy. I've read the JCA spec and discovered that the adapter can send lifecycle events to listeners using callback functions, but any attempt to use those event listeners callbacks ended with a new Exception:

javax.ejb.EJBException: BEA1-001471C1E76DE5A4E067; nested exception is: weblogic.transaction.nonxa.NonXAException: java.lang.IllegalStateException: [Connector:199175]This ManagedConnection is managed by a container for its transactional behavior and has been enlisted to a JTA transaction by a container; application/adapter must not call the local transaction begin/commit/rollback API. Reject event LOCAL_TRANSACTION_COMMITTED from adapter. javax.ejb.EJBException: EJB Exception: ; nested exception is: java.lang.IllegalStateException: [Connector:199175] This ManagedConnection is managed by a container for its transactional behavior and has been enlisted to a JTA transaction by a container; application/adapter must not call the local transaction begin/commit/rollback API. Reject event LOCAL_TRANSACTION_ROLLEDBACK from adapter.

I suppose WebLogic does not wait for any event (maybe I've sent the wrong one?).

So, what am I doing wrong? How to make the server put connections back to the pool?

UPD: I discovered that connection events are very important to the server. A server manages connections based on events info, that were send to listeners, which it registers to ManagedConnection. Now I supported events in my adapter, but WebLogic still does not want to put connections back to the pool. Currently I get following events in logs:

  1. LOCAL_TRANSACTION_STARTED
  2. CONNECTION_CLOSED
  3. LOCAL_TRANSACTION_COMMITTED

It looks fine for me (the CONNECTION_CLOSED event means application closed the connection, I added close method, that sends this event). Commit successful and no Exceptions appears. It seems that I've sent events in right order (earlier WebLogic throws Exceptions, but now stops doing it), but the server still does not put connections back to the pool.

I am confused.

1
What if you just called close() on connection (if implemented)? Connection based JCA APIs typically require this. Off topic, but you can omit @TransactionManagement and most likely the mappedName. The first is the default and the second rarely needed.Arjan Tijms
I do not implement close() method. What this method should do? I've seen close method in JCA file adapter example,where this method just sends the CONNECTION_CLOSED event to listeners, but WebLogic does not wait for events... BTW, I completely agree with you about mappedName and @TransactionManagement attribute.gkuzmin

1 Answers

2
votes

It seems that I've resoved this issue. When I looked in WebLogic console I discovered that ManagedConnection instances have -1 active handlers. So I decided to comment MyConnection.close() method call, which I added to my testing bean to send the CONNECTION_CLOSED event. After this chages have been made connection pooling began working great. I tried to modify my testing bean and set its transaction attribute to NOT_SUPPORTED. After that ManagedConnections in pool had 1 active handler. So i put back MyConnection.close() line and connection pooling starts working again.

I assume, that sending the CONNECTION_CLOSED event is wrong in case of transaction propagation. Also I assume that method ManagedConnection.close(), which sends the CONNECTION_CLOSED event should be used in case of single transaction. But it seems strange to me, that WebLogic does not want to cleanup ManagedConnections and put them back to pull if they have negative number of active handlers.

Thanks a lot for help.