我正在启动一个JavaEE项目,它需要强大的可扩展性。到目前为止,概念是:
-
几个消息驱动的bean,负责体系结构的不同部分
-
每个MDB都注入了一个会话bean,处理业务逻辑
-
两个实体bean,提供对持久层的访问
-
通过请求/回复概念通过JMS消息在体系结构的不同部分之间进行通信:
-
MDB接收包含活动请求的消息
-
使用其会话bean执行必要的业务逻辑
-
将消息中的响应对象返回给原始请求者
其思想是,通过消息总线将体系结构的各个部分相互分离,对可伸缩性没有限制。只需启动更多的组件——只要它们连接到同一总线,我们就可以增长。
不幸的是,我们在请求-回复概念上遇到了巨大的问题。交易管理似乎在我们的方式很多。会话bean不应该使用消息的接缝?!
阅读
http://blogs.oracle.com/fkieviet/entry/request_reply_from_an_ejb
和
http://forums.sun.com/message.jspa?messageID=10338789
我觉得人们确实推荐
反对
EJB的请求/应答概念。
如果是这样,如何
做
您在EJB之间通信?(记住,可伸缩性是我追求的目标)
我当前设置的详细信息:
-
mdb 1“testcontroller”,将(本地)slsb 1“testservice”用于业务逻辑
-
testcontroller.onmessage()使testservice向队列xyz发送消息并请求答复
-
testservice使用bean管理的事务
-
testservice在初始化时通过联合连接工厂建立与JMS代理的连接和会话(@postconstruct)
-
testservice在发送后提交事务,然后开始另一个事务,并等待10秒的响应
-
消息获取到MDB 2“locationController”,后者将(本地)SLSB 2“locationService”用于业务逻辑
-
locationController.onMessage()使locationService发送消息
后面
到请求的jmsreplyto队列
-
相同的BMT概念,相同的@postconstruct概念
-
都使用同一个连接工厂访问代理
问题:第一条消息(由SLSB 1发送)和接收(由MDB 2接收)正常。返回消息的发送(由SLSB 2)也可以。然而,
SLSB 1从未收到任何东西
-只是超时了。
我尝试不使用messageselector,不更改,仍然没有接收消息。
会话bean是否可以使用消息?
slsb 1-测试服务.java
@Resource(name = "jms/mvs.MVSControllerFactory")
private javax.jms.ConnectionFactory connectionFactory;
@PostConstruct
public void initialize() {
try {
jmsConnection = connectionFactory.createConnection();
session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
System.out.println("Connection to JMS Provider established");
} catch (Exception e) { }
}
public Serializable sendMessageWithResponse(Destination reqDest, Destination respDest, Serializable request) {
Serializable response = null;
try {
utx.begin();
Random rand = new Random();
String correlationId = rand.nextLong() + "-" + (new Date()).getTime();
// prepare the sending message object
ObjectMessage reqMsg = session.createObjectMessage();
reqMsg.setObject(request);
reqMsg.setJMSReplyTo(respDest);
reqMsg.setJMSCorrelationID(correlationId);
// prepare the publishers and subscribers
MessageProducer producer = session.createProducer(reqDest);
// send the message
producer.send(reqMsg);
System.out.println("Request Message has been sent!");
utx.commit();
// need to start second transaction, otherwise the first msg never gets sent
utx.begin();
MessageConsumer consumer = session.createConsumer(respDest, "JMSCorrelationID = '" + correlationId + "'");
jmsConnection.start();
ObjectMessage respMsg = (ObjectMessage) consumer.receive(10000L);
utx.commit();
if (respMsg != null) {
response = respMsg.getObject();
System.out.println("Response Message has been received!");
} else {
// timeout waiting for response
System.out.println("Timeout waiting for response!");
}
} catch (Exception e) { }
return response;
}
SLSB 2 - LooService .java(只有应答方法,REST与上面相同)
public boolean reply(Message origMsg, Serializable o) {
boolean rc = false;
try {
// check if we have necessary correlationID and replyTo destination
if (!origMsg.getJMSCorrelationID().equals("") && (origMsg.getJMSReplyTo() != null)) {
// prepare the payload
utx.begin();
ObjectMessage msg = session.createObjectMessage();
msg.setObject(o);
// make it a response
msg.setJMSCorrelationID(origMsg.getJMSCorrelationID());
Destination dest = origMsg.getJMSReplyTo();
// send it
MessageProducer producer = session.createProducer(dest);
producer.send(msg);
producer.close();
System.out.println("Reply Message has been sent");
utx.commit();
rc = true;
}
} catch (Exception e) {}
return rc;
}
sun-resources.xml文件
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerRequest" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerRequestQueue"/>
</admin-object-resource>
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerResponse" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerResponseQueue"/>
</admin-object-resource>
<connector-connection-pool name="jms/mvs.MVSControllerFactoryPool" connection-definition-name="javax.jms.QueueConnectionFactory" resource-adapter-name="jmsra"/>
<connector-resource enabled="true" jndi-name="jms/mvs.MVSControllerFactory" pool-name="jms/mvs.MVSControllerFactoryPool" />