9

Glassfish にデプロイされた Java EE アプリケーションで、同じトランザクション内で 2 つの永続ユニットを使用しようとしています。

次のように、persistence.xml で 2 つの持続性ユニットが定義されています。

<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 リソースと接続プールに対応します (名前とデータベース接続情報を除いて両方とも同一であるため、ここに 1 つ含めます)。

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

LimsServiceBean、AnalysisServiceBean、AnalysisDataTransformationServiceBean の 3 つのステートレス セッション Bean があります。

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'."

何か案は?

4

2 に答える 2

7

Glassfish の接続プールの構成を変更します。

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

Senthil Balakrishnan のブログ「How to make MSSQL Server XA Datasource Work?」の手順に従います。ここでは、http://www.senthilb.com/2010/01/how-to-make-xa-datasource-work-in-mssql.html

グラスフィッシュを再起動します。

于 2010-04-15T11:13:00.243 に答える
5

トランザクション内で 2 つの永続ユニット (したがって 2 つのデータソース) を使用するには、実際に XA 接続を使用し、それに応じてプールを構成する必要があります (少なくともそのうちの 1 つ。GlassFish は、1 つの非 XA を登録できる最後のエージェントの最適化をサポートしています)。リソースについては、http://docs.sun.com/app/docs/doc/820-7695/beanm?a=viewを参照してください)。それが最初のエラーでした。

2 番目のエラーについては、現在の詳細レベルでは何とも言えません。スタック トレースを提供していただけますか (必要に応じて、より詳細なログを有効にしてください)。

于 2010-04-10T05:02:58.077 に答える