1

我的应用程序中有一些我无法理解的行为。我有 1 个有状态 bean,1 个无状态 bean,我想从 SLB 的 SFB 1 方法调用(解析 WEB 页面)。没关系,但是 SLB 调用业务方法将 JMS 消息发送到另一个应用程序,并且由于事务类型(必需)而同时接收到所有消息。

所以我已经将我的 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 消息...

感谢您的澄清

奥利维尔

4

2 回答 2

3

您没有显示代码,但我怀疑您从同一个 SLB 实例的 parse 方法调用 SLB 中的 send 方法。在这种情况下,方法调用是直接的方法调用,不经过 bean 代理,因此 send 方法上的事务性注解被完全忽略。

你有

SFB -> transactional proxy -> SLB -> SLB

你应该在哪里

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

最简单的方法是将发送方法放在单独的 SLB 中。

于 2012-09-13T09:07:31.897 回答
0

谢谢 JB Nizet(没有快速回复,因为我必须等待 8 小时才能回复 -> 我是 StackOverflow 的新手,需要声誉)

我已经测试使用新的 SLB 发送 JMS 消息,结果相同,但我的两个 SLB 强耦合,因为我将 TopicPublisher 和 JMS 消息传递给我的新测试 EJB。

我刚刚测试了在我的测试 EJB 中创建 TopicPublisher 和消息,并且......它的工作!

这是我的新 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();
        }
    }



}

当我调用 test() 或 test3() 时,我异步接收所有消息,但 test2() 一起发送消息。

如果我理解得很好,当方法之间共享某些资源(使用@Resource)时,我们无法在同一个 EJB 内部或外部管理事务(使用 REQUIRES_NEW)?我肯定有这种行为来尊重事务隔离吗?

再次感谢你

奥利维尔

于 2012-09-13T21:15:52.027 回答