2012-09-13 46 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。