2012-09-13 129 views
1

我的應用程序中有一些行爲,我無法理解。我有1個有狀態bean,1個無狀態bean,我想從SLB(解析WEB頁面)的SFB 1方法調用。沒關係,但SLB調用將JMS消息發送到另一個應用程序的業務方法,並且由於事務類型(必需)而同時接收所有消息。瞭解EJB事務類型

因此,我將sendind方法的事務類型更改爲REQUIRES_NEW,但它是相同的,所有消息都在同一時間接收。

通過將解析方法更改爲REQUIRES_NEW,我異步接收消息。那麼如何解釋這種行爲呢?

總結:

SFB method -> REQUIRED 

SLB method (parsing of WEB page, urls stored in String[]) -> REQUIRED 

SLB method JMS -> REQUIRED 

==> JMS messages are received synchronously 



SFB method -> REQUIRED 

SLB method -> REQUIRED 

SLB method JMS -> REQUIRES_NEW 

==> JMS messages are received synchronously 



SFB method -> REQUIRED 

SLB method -> REQUIRES_NEW 

SLB method JMS -> REQUIRES_NEW 

==> JMS messages are received asynchronously 

我預期的情況下2發送異步JMS消息...

感謝澄清

奧利維爾

回答

0

謝謝JB Nizet(沒有立即回覆,因爲我回答之前等待8小時 - >中我StackOverflow的是全新的,需要聲望)

我已經測試發送使用新的JMS消息SLB,結果是一樣的,但是我的兩個SLB是強耦合的,因爲我將TopicPublisher和JMS消息傳遞給了我的新測試EJB。

我只是測試創建的TopicPublisher和消息我的測試EJB內......這是工作!

這是我的新的EJB:

package boursorama.stateless; 

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
import javax.annotation.Resource; 
import javax.ejb.LocalBean; 
import javax.ejb.Stateless; 
import javax.ejb.TransactionAttribute; 
import javax.ejb.TransactionAttributeType; 
import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.ObjectMessage; 
import javax.jms.Topic; 
import javax.jms.TopicConnection; 
import javax.jms.TopicConnectionFactory; 
import javax.jms.TopicPublisher; 
import javax.jms.TopicSession; 


@Stateless 
@LocalBean 
public class Test { 

    @Resource(mappedName="jms/boursoramaTopicFactory") 
    TopicConnectionFactory topicConnectionFactory; 

    @Resource(mappedName="jms/boursoramaTopicDestination") 
    Topic topic; 

    private TopicConnection _topicConnection; 
    private TopicSession _topicSession; 
    private TopicPublisher _topicPublisher; 

    @PostConstruct 
    public void postConstruct(){ 

     try { 
      _topicConnection = topicConnectionFactory.createTopicConnection(); 
      _topicSession = _topicConnection.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE); 
      _topicPublisher = _topicSession.createPublisher(topic);  
     } catch (JMSException e) {   
      e.printStackTrace(); 
     }  
    } 

    @PreDestroy 
    public void preDestroy(){ 
     try { 
      _topicConnection.close(); 
      _topicConnection = null;   
     } catch (JMSException e) {   
      e.printStackTrace(); 
     }  
    } 

    public Test() { 
     // TODO Auto-generated constructor stub 
    } 



    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void test(){ 
     try { 
      Message m = _topicSession.createObjectMessage();     
      _topicPublisher.send(m); 
     } catch (JMSException e) {   
      e.printStackTrace(); 
     } 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void test2(TopicPublisher to, Message m){ 
     try { 
      to.send(m); 
     } catch (JMSException e) {   
      e.printStackTrace(); 
     } 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void test3(Message m){ 
     try { 
      _topicPublisher.send(m); 
     } catch (JMSException e) {   
      e.printStackTrace(); 
     } 
    } 



} 

當我打電話試驗(+)或TEST3()我收到的所有消息異步但test2的()發送消息都在一起。

如果我沒理解好,我們不能當某些資源(與@Resource)方法之間共享管理同一個EJB內部還是外部事務中(與REQUIRES_NEW)?當然,我有這種行爲來尊重事務隔離?

再次

謝謝奧利維爾

3

你沒有表現你的代碼,但我懷疑你是從SLB實例的解析方法調用SLB中的send方法的。在這種情況下,方法調用是直接方法調用,它不通過bean代理,因此send方法上的事務註釋被完全忽略。

你有

SFB -> transactional proxy -> SLB -> SLB 

,你應該有

SFB -> transactional proxy -> SLB -> transactional proxy -> SLB 

最簡單的方法是將發送方法,在一個單獨的SLB。