目前,我开发了一个JCA出站适配器(具有LocalTransaction支持),并且在连接管理方面遇到了一些麻烦。我的适配器运行良好,但服务器(WebLogic 12c)不会将ManagedConnections放回池中。根据JavaDoc的说法,服务器必须调用ManagedConnection.cleanup()来重新初始化连接并将其放回池中,但事实并非如此。

当我从EJB使用适配器时,服务器创建一个新的ManagedConnection,开始一个新的事务,提交它,但是不调用ManagedConnection.cleanup()方法,也不将其放回池中。

在下面,您可以看到我的测试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));
}
}


经过10次调用,我得到以下信息:


  得到了初始上下文
  javax.ejb.EJBException:EJB异常:嵌套的异常是:
      java.lang.RuntimeException:javax.resource.spi.ApplicationServerInternalException:无法获得池=“ eis / myJCA”的连接,weblogic.common.resourcepool.ResourceLimitException:已配置的允许等待的最大线程数上限为(0)用于池eis / myJCA达到的资源


如您所见,它为每个调用使用一个新事务(REQUIRES_NEW属性)。服务器首先创建一个新的ManagedConnection实例10次,然后连接池达到其最大容量。

从跟踪日志中可以明显看出,没有发生ManagedConnection.cleanup()的单个调用,并且池中的每个连接都处于繁忙状态。我已经阅读了JCA规范,发现适配器可以使用回调函数将生命周期事件发送给侦听器,但是使用这些事件侦听器回调的任何尝试都以新的Exception结尾:


  javax.ejb.EJBException:BEA1-001471C1E76DE5A4E067;嵌套的异常是:
      weblogic.transaction.nonxa.NonXAException:java.lang.IllegalStateException:[Connector:199175]此ManagedConnection由容器管理以实现其事务处理行为,并且已被容器征用到JTA事务中;应用程序/适配器不得调用本地事务的begin / commit / rollback API。从适配器拒绝事件LOCAL_TRANSACTION_COMMITTED。
  javax.ejb.EJBException:EJB异常:嵌套的异常是:
      java.lang.IllegalStateException:[Connector:199175]此ManagedConnection由容器管理以实现其事务处理行为,并且已被容器征用到JTA事务中;应用程序/适配器不得调用本地事务的begin / commit / rollback API。从适配器拒绝事件LOCAL_TRANSACTION_ROLLEDBACK。


我想WebLogic不等待任何事件(也许我发送了错误的事件?)。

那么,我在做什么错呢?如何使服务器将连接放回池中?

UPD:我发现连接事件对服务器非常重要。服务器根据发送到侦听器的事件信息管理连接,并注册到ManagedConnection。现在,我在适配器中支持事件,但是WebLogic仍然不希望将连接放回池中。目前,我在日志中收到以下事件:


LOCAL_TRANSACTION_STARTED
CONNECTION_CLOSED
LOCAL_TRANSACTION_COMMITTED


对我来说看起来不错(CONNECTION_CLOSED事件表示应用程序关闭了连接,我添加了close方法来发送此事件)。提交成功,没有异常出现。看来我已经按正确的顺序发送了事件(早期的WebLogic引发Exceptions,但现在停止了),但是服务器仍然没有将连接放回池中。

我很困惑。

最佳答案

看来我已经解决了这个问题。在WebLogic控制台中查看时,我发现ManagedConnection实例具有-1个活动处理程序。因此,我决定注释MyConnection.close()方法调用,该方法调用已添加到测试bean中以发送CONNECTION_CLOSED事件。进行此更改后,连接池开始运行良好。我试图修改我的测试bean,并将其交易属性设置为NOT_SUPPORTED。之后,池中的ManagedConnections具有1个活动处理程序。所以我放回MyConnection.close()行,连接池再次开始工作。

我认为,在事务传播的情况下发送CONNECTION_CLOSED事件是错误的。我还假设在单个事务的情况下应使用发送ManagedConnection.close()事件的方法CONNECTION_CLOSED。但是对我来说似乎很奇怪,WebLogic不想清理ManagedConnections并在活动处理程序的数量为负数时将它们放回原处。

非常感谢您的帮助。

07-27 18:47