我目前使用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。这些都没有奏效。
答案 0 :(得分:0)
经过一些试验和错误后,我提出了以下方法:
我已经使用无状态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。