我在Websphere Application Server上部署了一个EAR,它使用一个函数通过使用JMS向MQ发送消息,并从另一个队列中立即收到消息。
ConnectionFactory cf = null;
InitialContext context = null;
String[] arrDatos_SR = null;
Connection conn = null;
Session session = null;
Queue queue = null;
Queue queue2 = null;
Destination dest = null;
Destination dest2 = null;
MessageConsumer consumer = null;
MessageProducer producer = null;
TextMessage message = null;
String comando = "";
int tamanio = 0;
String tamanio2 = "";
String cadena = "";
try {
context = new InitialContext();
cf = (ConnectionFactory) context.lookup(arrDatos[1].trim());
conn = cf.createConnection();
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue) context.lookup(arrDatos[2].trim());
queue2 = (Queue) context.lookup(arrDatos[3].trim());
dest = (Destination) queue;
dest2 = (Destination) queue2;
producer = session.createProducer(dest);
// Create a text message using the queue session.
TextMessage textMessage = session.createTextMessage();
textMessage.setText(arrDatos[4]);
textMessage.setJMSReplyTo(dest2);
textMessage.setJMSMessageID(arrDatos[6]);
textMessage.setJMSCorrelationID(arrDatos[7]);
producer.send(textMessage);
} catch (NamingException e) {
// TODO Auto-generated catch block
logger.error("MQSendReceive() - Exception e2 = "
+ e, e);
} catch (JMSException e) {
// TODO Auto-generated catch block
logger.error("MQSendReceive() - Exception e2 = "
+ e, e);
}
arrDatos[5] = arrDatos[5].trim();
try{
conn.start();
consumer = session.createConsumer(dest2);
Message receivedMessage = consumer.receive(Long.parseLong(arrDatos[5]) * 1000);
if(receivedMessage != null)
{
message = (TextMessage)receivedMessage;
comando = message.getText();
comando = comando.trim();
tamanio = comando.length();
tamanio2 = StringUtils.leftPad(Integer.toString(tamanio), 9, '0');
comando = StringUtils.rightPad(comando, Constantes.TAMANIO_RESPUESTA_DES_C1, ' ');
cadena = arrDatos[0] + comando + tamanio2;
}
else
{
comando = new String();
comando = "";
tamanio = comando.length();
tamanio2 = StringUtils.leftPad(Integer.toString(tamanio), 9, '0');
cadena = arrDatos[0] + comando + tamanio2;
}
arrDatos_SR = new String[2];
arrDatos_SR[0] = cadena;
arrDatos_SR[1] = arrDatos[0];
}
catch(Exception e)
{
logger.error("MQSendReceive() - Excepcion:" + e);
}
finally
{
try {
consumer.close();
session.close();
conn.close();
context.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
logger.error("MQSendReceive() - Error desconectando de MQ - Excepcion:" + e);
} catch (NamingException e) {
// TODO Auto-generated catch block
logger.error("MQSendReceive() - Error desconectando de MQ - Excepcion:" + e);
}
}
return arrDatos_SR;
消息被发送到MQ队列#1,然后将其传送到另一个MQ队列#2,这是另一个MQ队列#3的传输队列。我使用Websphere MQ管理GUI测试将消息放入此队列,并且它们可以顺利传输。但是当我出于某种原因使用我的代码时,发送不会立即发送。相反,它是在接收结束后(超时到期或实际收到消息时)完成的
有人可以告诉我为什么会这样吗?
更新 :( 2014年3月31日)我忘了提到我正在使用带有@LocalBean,@ Singleton和@TransactionManagement(TransactionManagementType.CONTAINER)注释的EJB容器。通过从SO(http://goo.gl/JBSW7r)阅读这篇文章,我意识到我有3个类可以构成整个连接,还有一个主要使用它们作为我使用公共方法的对象。我决定使用相同的注释将这些类转换为EJB。我还尝试将每个方法的@TransactionAttribute类型一次更改为REQUIRED,NOT SUPPORTED和MANDATORY,只是为了测试其中一些是否有效。我还将会话行更改为:
session = conn.createSession(true, Session.SESSION_TRANSACTED);
结果似乎是一样的。在MessageConsumer的超时间隔期间收到消息时,消息仍然卡在传输队列中。
有人能给我一些关于这些的东西吗?
答案 0 :(得分:3)
根据您对问题的描述,我相信您提供的代码是在具有容器管理事务的EJB的上下文中执行的。在Java EE应用程序服务器中,JMS操作将由事务协调。这意味着在EJB方法结束时容器提交事务之前,send实际上不会完成。
虽然在Java EE应用程序服务器中创建会话时设置为false,但会忽略该会话,并且会话将在任何有效的全局事务中注册。
此问题的解决方案是确保在没有事务的情况下执行JMS发送。为此,应使用事务类型NOT_SUPPORTED配置EJB方法。
答案 1 :(得分:1)
经过这么多尝试,我结束了删除EJB。我用整个逻辑制作了一个web项目。我决定通过使用带有while循环的Thread来控制代码的重复。我使用布尔变量来控制EAR启动和关闭时while循环的初始化和停止。
好吧,回到Web应用程序,它可以正常工作。我不知道为什么它以这种方式工作而不是另一种,但我认为现在没问题。
答案 2 :(得分:1)
虽然看起来OP通过将他的逻辑转移到Web模块而得到了一个解决方案,但是我想在其他人需要使用EJB的情况下添加一个潜在的选项。
Alasdair的答案绝对是将EJB类型逻辑移回Web应用程序的首选方式。我们刚刚在创建新的EJB 3.0项目并定义发送消息并等待来自Websphere MQ的回复的bean时遇到此问题。我们发现我们确实在开始时使用事务类型Container定义了我们的会话bean,由于前面提到的确切原因而失败了。
将事务类型切换为 Bean ,然后为我们解决了这个问题。它仍然允许会话bean保留一些事务属性,但也让JMS发送一个已提交的消息。