0

我设置了一个简单的请求/回复类型场景(JavaEE 7/Netbeans 7 with Glassfish),代码如下:

这是一个执行 JMS 生产者角色的无状态会话 bean,
destination并被factory注入到 EJB 中。

public void doStuff(int id) {

    try {
    Connection connection = factory.createConnection();
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageProducer producer = session.createProducer(destination);
    ObjectMessage message = session.createObjectMessage();

    MyObject obj = new MyObject(id);
    connection.start();

    TemporaryQueue replyQueue = session.createTemporaryQueue();
    MessageConsumer consumer = session.createConsumer(replyQueue);

    message.setJMSReplyTo(replyQueue);
    message.setObject(obj);

    producer.send(message, DeliveryMode.PERSISTENT, Message.DEFAULT_PRIORITY, 1800000);
    Message reply = consumer.receive();

    producer.close();
    session.close();
    connection.close();
    } catch (JMSException ex) {

    }
    }

我的问题是,当consumer.receive()被调用时,执行会按预期阻止-但是此消息的使用者永远不会运行。原始消息的使用者(它是一个 MDB)位于部署在同一 Glassfish 服务器上的另一个 netbeans 项目中。

我已经尝试调试两个项目(生产者和消费者),似乎当我的生产者项目被阻塞时,我的消费者项目根本没有做任何事情。

如果我按预期更改consumer.recieve()consumer.receive(20000)20 秒内没有任何反应 - 但是一旦超时突然到期,我的消费者项目就会遇到调试器断点,并且它会正常处理。但是当然没有回复发送回我的生产者项目,因为它不再在听了!

我的另一个项目(消费者项目)看起来像这样:

@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/myQueue")
})
---------------------
    @Override
public void onMessage(Message message) {
    try {
        ObjectMessage objMessage = (ObjectMessage) message;
        MyObject obj = (MyObject) objMessage.getObject();
        Connection connection = factory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer = session.createProducer(message.getJMSReplyTo());
        connection.start();

        try {
            myMethod(obj);
        } catch (Exception e) {

            Message response = session.createTextMessage(e.getMessage());
            producer.send(message.getJMSReplyTo(), response);
        }


    } catch (JMSException ex) {

    }
}

如何让 receive() 方法正常工作?我需要它暂停回复,但是在暂停时我需要我的另一个项目继续工作——如果它们是两个单独部署的项目,我会假设它们无论如何都在不同的线程上。

4

1 回答 1

0

我最终发现我遇到了这个问题,因为我的doStuff()方法是运行一个容器管理事务。

除此之外,您每笔交易只能执行一项操作(例如:请求/接收中的一项)

所以当我打电话时producer.send(),实际上并没有发送消息,因为事务还没有完成(方法没有完成)。然后它继续receive呼叫并阻止在那里,因为没有发送任何消息。

我通过使我的 doStuff() 方法成为 Bean Managed Transaction 来解决这个问题,我在 bean 上注入了一个UserTransaction带有@Resource注释的对象。

我去绑定发送操作,UserTransaction.beginUserTransaction.commit重复此操作以绑定我的第二个接收操作 - 它按预期工作。

这为我提供了关于 CMT 的清晰解释:http: //docs.oracle.com/cd/E19798-01/821-1841/bncij/index.html

于 2013-10-05T04:41:26.050 回答