-1

I encountered a knotty problem when receiving message from WildFly JMS queue. My code is below:

Session produceSession = connectionFactory.createConnection().createSession(false, Session
                    .CLIENT_ACKNOWLEDGE);
            Session consumerSession = connectionFactory.createConnection().createSession(false, Session
                    .CLIENT_ACKNOWLEDGE);
            ApsSchedule apsSchedule = new ApsSchedule();

            boolean success;
            MessageProducer messageProducer = produceSession.createProducer(outQueueMaxusOrder);
            success = apsSchedule.sendD90Order(produceSession,messageProducer, d90OrderAps);
            if (!success) {
                logger.error("Can't send APS schedule msg ");
            } else {
                MessageConsumer consumer = consumerSession.createConsumer(inQueueDeliveryDate);
                data = apsSchedule.receiveD90Result(consumerSession,consumer);
            }

then getting into the receiveD90Result():

public DeliveryData receiveD90Result(Session session, MessageConsumer consumer) {
    DeliveryData data = null;
    try {
         Message message = consumer.receive(10000);

        if (message == null) {
            return null;
        }
        TextMessage msg = (TextMessage) message;
        String text = msg.getText();
        logger.debug("Receive APS d90 result: {}", text);

        ObjectMapper mapper = new ObjectMapper();
        data = mapper.readValue(text, DeliveryData.class);
    } catch (JMSException je) {
        logger.error("Can't receive APS d90 order result: {}", je.getMessage());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            consumer.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
    return data;
}

But when implementing the consumer.receive(10000), the project can't get a message from queue. If I use asynchronous way of MDB to listen the queue, I can get the message from queue. How to resolve it?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
JoeXu
  • 41
  • 1
  • 8

2 Answers2

0

There are multiple modes you can choose to get a message from the queue. Message Queues are by default asynchronous in usage. There are however cases when you want to read it synchronously , for example sending a message with account number and using another queue to read the response and match it with a message id or a message correlation id. When you do a receive , the program is waiting for a message to arrive within that polling interval specified in receive.

The code snippet you have , as i see it uses the psuedo synchronous approach. If you have to use it as an MDB , you will have to implement message driven bean (EJB Resource) or message listener.

The way that MDB/Message Listener works is more event based , instead of a poll with a timeout (like the receive) , you implement a callback called onMessage() that is invoked every time there is a message. Instead of a synchronous call , this becomes asynchronous. Your application may require some changes both in terms of design.

Ramachandran.A.G
  • 4,788
  • 1
  • 12
  • 24
  • Is true that using asynchronous way to get message ? But I just want to use synchronous way to receive message from jms queue in wildfly,the code will not throw any exception. – JoeXu Aug 20 '17 at 07:56
  • You can use synchronous way to get the message , you should a) Match the request with response , because order or processing is not guarenteed - one application may response posting the message may be faster than another b) How long will you poll before confirming message as "lost". If you are getting a specific stack trace, please post it your question – Ramachandran.A.G Aug 20 '17 at 08:01
0

I don't see where you're calling javax.jms.Connection.start(). In fact, it doesn't look like you even have a reference to the javax.jms.Connection instance used for your javax.jms.MessageConsumer. If you don't have a reference to the javax.jms.Connection then you can't invoke start() and you can't invoke close() when you're done so you'll be leaking connections.

Furthermore, connections are "heavy" objects and are meant to be re-used. You should create a single connection for both the producer and consumer. Also, if your application is not going to use the javax.jms.Session from multiple threads then you don't need multiple sessions either.

Justin Bertram
  • 29,372
  • 4
  • 21
  • 43