EJB3 - 在事务中使用2个持久化单元(异常:本地事务已经有1个非XA资源)

9

我正在尝试在部署在Glassfish上的Java EE应用程序中,在同一个事务中使用2个持久性单元。

这2个持久化单元在persistence.xml中定义如下:

<persistence-unit name="BeachWater">
<jta-data-source>jdbc/BeachWater</jta-data-source>
...
<persistence-unit name="LIMS">
<jta-data-source>jdbc/BeachWaterLIMS</jta-data-source>
...

这些持久性单元对应于我在Glassfish中定义的JDBC资源和连接池(包括一个示例,两者除名称和数据库连接信息外完全相同):

JDBC Resource:
JNDI Name: jdbc/BeachWaterLIMS
Pool Name: BEACHWATER_LIMS

Connection Pool:
Name: BEACHWATER_LIMS
Datasource Classname: com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
Resource Type: javax.sql.ConnectionPoolDataSource

有三个无状态会话Bean,LimsServiceBean、AnalysisServiceBean和AnalysisDataTransformationServiceBean。

以下是LimsServiceBean中相关的代码片段:

@PersistenceContext(unitName = "LIMS")
EntityManager em;
...
public ArrayList<Sample> getLatestLIMSData() {
    Query q = em.createNamedQuery("Sample.findBySubTypeStatus");
    return new ArrayList<Sample>(q.getResultList());
}

来自AnalysisServiceBean:

@PersistenceContext(unitName = "BeachWater")
EntityManager em;
...
public ArrayList<AnalysisType> getAllAnalysisTypes() {
    Query q = em.createNamedQuery("AnalysisType.findAll");
    return new ArrayList<AnalysisType>(q.getResultList());
}

同时来看 AnalysisDataTransformationServiceBean:

@EJB
private AnalysisService analysisService;

@EJB
private LimsService limsService;

public void transformData() {
    List<AnalysisType> analysisTypes = analysisService.getAllAnalysisTypes();
    ArrayList<Sample> samples = limsService.getLatestLIMSData();

调用limsService.getLatestLIMSData()时出现以下异常:

     [exec] Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean; nested exception is: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.1 (Build b60e-fcs (12/23/2008))): oracle.toplink.essentials.exceptions.DatabaseException
 [exec] Internal Exception: java.sql.SQLException: Error in allocating a connection. Cause: java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources.

在查看了许多资料之后,包括http://msdn.microsoft.com/en-us/library/ms378484.aspx,我尝试将连接池的定义更改为:

Connection Pool:
Name: BEACHWATER_LIMS
Datasource Classname: com.microsoft.sqlserver.jdbc.SQLServerXADataSource
Resource Type: javax.sql.XADataSource

通过Glassfish管理控制台进行的Ping测试成功,但现在调用analysisService.getAllAnalysisTypes()时出现异常:
Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean; nested exception is: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.1 (Build b60e-fcs (12/23/2008))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error in allocating a connection. Cause: javax.transaction.SystemException

The resource manager is doing work outside a global transaction javax.transaction.xa.XAException: com.microsoft.sqlserver.jdbc.SQLServerException: Failed to create the XA control connection. Error: "Could not find stored procedure 'master..xp_sqljdbc_xa_init_ex'."

有什么想法吗?

可能是重复的问题:如何防止“Local transaction already has 1 non-XA Resource”异常?(https://dev59.com/rU3Sa4cB1Zd3GeqPuFT6) - Michał Piątkowski
2个回答

7

修改Glassfish连接池的配置:

Connection Pool:
Name: BEACHWATER_LIMS
Datasource Classname: com.microsoft.sqlserver.jdbc.SQLServerXADataSource
Resource Type: javax.sql.XADataSource

请按照以下步骤进行:

请参考Senthil Balakrishnan的博客文章“如何让MSSQL Server XA数据源正常工作?”http://www.senthilb.com/2010/01/how-to-make-xa-datasource-work-in-mssql.html

重新启动Glassfish。


提供存档链接非常重要:https://web.archive.org/web/20180823061808/http://www.senthilb.com/2010/01/how-to-make-xa-datasource-work-in-mssql.html - John Manko

5
为了在一个事务中使用两个持久化单元(因此需要使用两个数据源),确实需要使用XA连接并相应地配置您的池(至少其中一个,GlassFish支持最后一个代理优化,允许注册一个非XA资源,请参见http://docs.sun.com/app/docs/doc/820-7695/beanm?a=view)。这是第一个错误。
对于第二个错误,目前的细节水平似乎很难说任何事情。您能提供堆栈跟踪吗(如有必要,请激活更详细的日志记录)?

谢谢Pascal。我在日志中发现了更多细节:资源管理器正在全局事务之外进行工作 javax.transaction.xa.XAException: com.microsoft.sqlserver.jdbc.SQLServerException: 无法创建XA控制连接。错误:“找不到存储过程'master..xp_sqljdbc_xa_init_ex'。”我在这里找到了一个建议的解决方案,http://www.senthilb.com/2010/01/how-to-make-xa-datasource-work-in-mssql.html,并请求在服务器上进行相关更改。重新测试后将在此更新。 - Sorcha
@Sorcha 感谢您的反馈。请在更新后留下评论,以便我得到通知。但我有一种感觉,您正在正确的轨道上! - Pascal Thivent
现在已经完美地工作了。 再次感谢您的贡献。 - Sorcha
我在使用WLS 10.3和两个数据源Oracle和Informix时遇到了类似的问题。非常有帮助。谢谢。 - cosmos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接