Container Manager Transactions和JackRabbit

时间:2013-10-28 22:13:14

标签: transactions glassfish ejb jackrabbit

我目前使用JCA rar在Glassfish 4中部署了Jackrabbit 2.6.4。

我正在使用MySql并在Glassfish中配置了一个数据源来访问数据库。配置RepositoryManager时,我在Jackrabbit repository.xml中使用相同的数据源。

如果我通过@Resource注释将存储库注入到一个不会自动启动事务的容器托管bean中,一切都按预期工作。

如果我通过@Resource注释将存储库注入EJB(导致容器管理的事务),当我尝试使用存储库时,我得到以下堆栈跟踪:

  

javax.resource.spi.LocalTransactionException:当autocommit = true时无法调用commit       at com.sun.gjc.spi.LocalTransactionImpl.commit(LocalTransactionImpl.java:112)       在com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:124)       ...   引起:java.sql.SQLException:当autocommit = true时无法调用commit       在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)       在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:924)       在com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1724)       at com.sun.gjc.spi.LocalTransactionImpl.commit(LocalTransactionImpl.java:106)       ......还有72个   ]]   [2013-10-28T14:49:29.646-0700] [glassfish 4.0] [警告] [jts.unexpected_error_occurred_twopc_commit] [javax.enterprise.system.core.transaction.com.sun.jts.jtsxa] [tid:_ThreadID = 33 _ThreadName = http-listener-1(3)] [timeMillis:1382996969646] [levelValue:900] [[     JTS5067:提交中发生意外错误   javax.transaction.xa.XAException:javax.resource.spi.LocalTransactionException:当autocommit = true时无法调用commit       at com.sun.enterprise.resource.ConnectorXAResource.handleResourceException(ConnectorXAResource.java:115)       在com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:126)       ...   ]

查看Jackrabbit文档是:

  

如果使用数据库持久性管理器,则配置的数据库连接不得受外部事务管理器的控制。 Jackrabbit在更高级别实现分布式XA事务支持,并期望完全控制底层数据库连接。

鉴于此,如何配置Jackrabbit和Glassfish以允许容器管理的事务和Jackrabbit管理的事务一起参与同一个全局事务?

我已尝试将Jackrabbit JCA适配器和数据源连接池设置为使用XA Transactions。我还将Jackrabbit JCA属性bindSessionToTransaction设置为true。这些都没有奏效。

1 个答案:

答案 0 :(得分:0)

经过一些试验和错误后,我提出了以下方法:

  1. 在glassfish中创建用于访问Jackrabbit存储库表的JDBC连接池。
  2. 将资源类型设置为javax.sql.DataSource并启用“非事务性连接”
  3. 创建可用于访问Jackrabbit JDBC连接池的JDBC资源。使用Jackrabbit repository.xml中此资源中定义的JNDI名称来配置持久性管理器等。
  4. 使用Jackrabbit-jca资源适配器创建连接器连接池
  5. 将交易支持设置为XATransaction
  6. 添加属性'bindSessionToTransaction'并将其设置为true
  7. 创建可用于将存储库注入EJB的连接器资源
  8. 我已经使用无状态EJB测试了它,它可以正常工作。

    我还创建了第二个类型为javax.sql.DataSource的JDBC连接池和一个指向单独数据库的JDBC资源,该数据库维护应用程序其他表并创建了一个使用数据源的persistence.xml。

    然后,我修改了应用程序数据库中的repo和表(使用JPA)并确认如果事务回滚,则repo和application表上的更改都会正确回滚。

    我认为这是正确的方法,因为它允许Jackrabbit完全控制它的数据库连接,但仍然作为XA资源参与容器管理的事务。

    我测试了第二个数据源作为XADataSource和非XA数据源,两种方法都有效。我假设它不需要是XADataSource,因为事务中没有其他非XA数据源,它通过LLR(记录最后资源)参与全局事务。

    更新1:

    事实证明,您也可以通过绕过repo数据源并直接在存储库xml中配置JDBC URL来实现此功能。这样做的一个好处是,当您不需要在每个Glassfish实例中创建数据源的集群时,您只需复制repository.xml并更改集群节点ID。