2009-09-04 67 views
0

我將嘗試描述情況。我們有一個網絡服務;在每個請求Web服務啓動一個JTA事務。它通過內部的XA數據源執行多個數據庫調用,並調用其他一些Web服務(不在事務上下文中),並在其他服務器上進行一些遠程EJB調用。在事務內部進行無事務EJB調用

問題是容器似乎試圖將EJB引入事務(而且這似乎是合乎邏輯的),但實際上我希望它不參與該事務,因爲它參與該事務時總是超時最終提交階段,但是當我排除EJB調用時,它工作正常。

我無法更改EJB實現,只能控制Web服務代碼。所以,我的問題是:如何對事務感知型EJB進行EJB調用,但是不在我的JTA事務中,但仍在JTA事務中處理其他XA資源?我希望我明確提出了我的問題:)。

編輯:試圖使其與僞代碼示例更清晰:

// Begin transaction 
UserTransaction tx = (UserTransaction) ctx.lookup(USER_TRANSACTION); 
tx.begin(); 

// Do some database operations on XA datasource 

// Call remote EJB which has transcation attribute set to 'Supports' 
AccountInfo account = accountEjb.getAccountInfo(userId, accountId); // <-- Is it possible to make this to be not be part of user transction? 

// Do some more database operations on XA datasource 

// Commit transaction 
tx.commit(); 
+0

你爲什麼不增加超時? – 2009-09-10 12:16:54

+0

,因爲問題不在超時時間內,所有的調用在milleseconds內都會正常工作,但是當事務提交到最後時會超時,如果ejb調用從調用序列中移除,它會提交正常。所以,我認爲它實際上必須做一些與服務器間通信,但不是超時值。 – 2009-09-10 14:03:49

回答

2

您可以創建另一個具有適當事務屬性的bean。這個bean可以將所有調用委託給第一個bean。

或者你可以從另一個線程調用這個ejb。

+0

我會嘗試使用另一個線程。 – 2009-09-05 08:21:51

1

EJB事務聲明:對於給定的EJB的部署給你指定的事務語義。確切的EJB可以部署(當然,使用不同的名稱),您可以爲該部署指定不同的需求。這是假定(a)你至少有ejb的jar,(b)該ejb是獨立的,並且不依賴於其他組件,並且(c)ejb的開發者並不是沒有違反聲明式交易的想法,而且他的bean也在事務環境之外工作。

+0

我無法控制EJB,但我知道它的事務屬性被設置爲「支持」,並且我也獨立(對容器外)調用了該EJB,沒有任何問題。此外,EJB和我的Web服務部署在不同的服務器上,我也無法改變這一點。 – 2009-09-04 20:21:20

+0

所以,這是不可能的? – 2009-09-05 06:08:08

0

您可以創建合適的TX屬性的另一個方法,然後通過自我注射用代理調用它(僞代碼):

@Stateless 
public class LocalEJB1 { 

    @EJB 
    private LocalEJB1 localEJB1; 

    @EJB 
    private AccountEJB accountEjb; 

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
    public AccountInfo callNonTx() { 
     return accountEjb.getAccountInfo(userId, accountId); 
    } 

    public void yourCurrentMethod() { 
     // Begin transaction 
     UserTransaction tx = (UserTransaction) ctx.lookup(USER_TRANSACTION); 
     tx.begin(); 

     AccountInfo account = localEJB1.callNonTx(); 
     // Do some more database operations on XA datasource 

     // Commit transaction 
     tx.commit(); 
    } 
}