【问题标题】:JCA ManagedConnection lifecycleJCA ManagedConnection 生命周期
【发布时间】:2012-03-20 07:55:32
【问题描述】:

目前我开发了一个 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 规范,发现适配器可以使用回调函数将生命周期事件发送到侦听器,但是任何使用这些事件侦听器回调的尝试都以新的异常结束:

javax.ejb.EJBException: BEA1-001471C1E76DE5A4E067;嵌套异常是: weblogic.transaction.nonxa.NonXAException: java.lang.IllegalStateException: [Connector:199175]这个 ManagedConnection 由一个容器管理它的事务行为,并且已经被一个容器登记到一个 JTA 事务中;应用程序/适配器不得调用本地事务开始/提交/回滚 API。拒绝来自适配器的事件 LOCAL_TRANSACTION_COMMITTED。 javax.ejb.EJBException:EJB 异常:;嵌套异常是: java.lang.IllegalStateException: [Connector:199175] 此 ManagedConnection 由容器管理其事务行为,并已被容器登记到 JTA 事务中;应用程序/适配器不得调用本地事务开始/提交/回滚 API。拒绝来自适配器的事件 LOCAL_TRANSACTION_ROLLEDBACK。

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

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

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

  1. LOCAL_TRANSACTION_STARTED
  2. CONNECTION_CLOSED
  3. LOCAL_TRANSACTION_COMMITTED

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

我很困惑。

【问题讨论】:

  • 如果您刚刚在connection 上调用close() 会怎样(如果已实施)?基于连接的 JCA API 通常需要这个。题外话,但你可以省略@TransactionManagement,很可能是mappedName。第一个是默认设置,第二个很少需要。
  • 我没有实现close() 方法。这个方法应该做什么?我在 JCA 文件适配器示例中看到了 close 方法,该方法只是将 CONNECTION_CLOSED 事件发送给侦听器,但 WebLogic 不等待事件...顺便说一句,我完全同意您对 mappedName@TransactionManagement 的看法属性。

标签: java weblogic jca


【解决方案1】:

看来我已经解决了这个问题。当我查看 WebLogic 控制台时,我发现 ManagedConnection 实例有 -1 个活动处理程序。所以我决定评论MyConnection.close() 方法调用,我将它添加到我的测试bean 以发送CONNECTION_CLOSED 事件。进行此更改后,连接池开始正常工作。我试图修改我的测试 bean 并将其事务属性设置为NOT_SUPPORTED。之后,池中的 ManagedConnections 有 1 个活动处理程序。所以我放回MyConnection.close() 线,连接池又开始工作了。

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

非常感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2014-09-10
    • 2021-09-14
    • 2012-02-10
    • 1970-01-01
    • 2012-06-03
    相关资源
    最近更新 更多