我的应用程序中有一些我无法理解的行为。我有1个有状态bean,1个无状态bean,我想从SFB的1个SLB方法(解析WEB页面)调用。没关系,但是SLB调用将JMS消息发送到另一个应用程序的业务方法,并且由于事务类型(REQUIRED),所有消息都被同时接收。
所以我已将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 :(得分:3)
您没有显示您的代码,但我怀疑您从同一SLB实例的解析方法中调用SLB中的send方法。在这种情况下,方法调用是一个直接的方法调用,它不通过bean代理,因此完全忽略了send方法上的事务注释。
你有
SFB -> transactional proxy -> SLB -> SLB
你应该在哪里
SFB -> transactional proxy -> SLB -> transactional proxy -> SLB
最简单的方法是将send方法放在单独的SLB中。
答案 1 :(得分: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)?当然,我有这种行为来尊重事务隔离吗?
再次感谢您
奥利弗