0

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

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

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

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

javax.resource.spi.LocalTransactionException:com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource) 的 com.sun.gjc.spi.LocalTransactionImpl.commit(LocalTransactionImpl.java:112) 的 autocommit=true 时无法调用提交.java:124) ... 原因:java.sql.SQLException:com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927) at com.mysql.jdbc 的 autocommit=true 时无法调用提交。 SQLError.createSQLException(SQLError.java:924) 在 com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1724) 在 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:可以'在 com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:126) 的 com.sun.enterprise.resource.ConnectorXAResource.handleResourceException(ConnectorXAResource.java:115) 的 autocommit=true 时不调用提交 ...] ]115) 在 com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:126) ... ]]115) 在 com.sun.enterprise.resource.ConnectorXAResource.commit(ConnectorXAResource.java:126) ... ]]

查看 Jackrabbit 文档是状态:

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

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

我尝试将 Jackrabbit JCA 适配器和数据源连接池都设置为使用 XA 事务。我还将 Jackrabbit JCA 属性 bindSessionToTransaction 设置为 true。这些都不起作用。

4

1 回答 1

0

经过反复试验,我想出了以下方法:

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

我已经使用无状态 EJB 对此进行了测试,并且它可以正常工作。

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

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

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

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

更新1:

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

于 2013-10-29T16:53:10.607 回答