2
votes

I successfully managed to send the message to queue name ReceiverQueue on my localhost Jboss server, how can I retrieve message I sent to it or how do I check if there is any messages in the queue if any retrieve them. or can I get an explanation of some sort what is the best way to do this. Thank you

A working send/receive tutorial would be accept as well. Anything that will get me to just send to the queue and receive message from that queue will get accepted answer.

I'm using Spring.

I want a solution that does it using application context with bean injection ..

4
@Gandalf StormCrow: Since there are no answers about MDB, I added something to my answer..Enno Shioji

4 Answers

5
votes

Standard JMS API steps:
1. Create a javax.naming.Context with the access details of the server

context = new InitialContext(environment)

2. Look up javax.jms.QueueConnectionFactory in the context. Factory name is specific to the JMS server

factory = (QueueConnectionFactory)context.lookup(factoryName)

3. Create a javax.jms.QueueConnection

connection = factory.createQueueConnection(...)

4. Create a javax.jms.QueueSession

session = connection.createQueueSession(...)

5. Look up your javax.jms.Queue in the context

queue = (Queue) context.lookup(qJndiName)

Till now it is the same as sending....
6. Create a javax.jms.QueueReceiver with the session

receiver = session.createReceiver(queue)

7. JMS API provides 2 ways to retrieve a message:
7.a Wait for a message with one of the receiver.receive() methods
7.b Implement javax.jms.MessageListener in your class and register it as the listener

receiver.setMessageListener(this)

JMS API will call your onMessage() method whenever a new message arrives
8. Don't forget to start the listener:

connection.start()

9. Close the context (very important, when you access multiple JMS servers from the same program):

context.close()

The above is a typical solution from a stand-alone application. In EJB environment you should use message driven beans. You can find ino on them on http://java.sun.com/javaee/6/docs/tutorial/doc/gipko.html and a tutorial on http://schuchert.wikispaces.com/EJB3+Tutorial+5+-+Message+Driven+Beans

Here is the working example you've asked for:

import java.util.Hashtable;
import javax.naming.*;
import javax.jms.*;

public class JMSJNDISample implements MessageListener {

    public static final String JNDI_URL = "jnp://localhost:1099";
    public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
    public static final String JMS_USER = null;
    public static final String JMS_PASSWORD = null;
    public static final String JMS_CONNECTION_FACTORY = "MyConnectionFactory";
    public static final String QUEUE_JNDI_NAME = "ReceiverQueue";

    QueueConnection qConn = null;
    QueueSession qSession = null;
    QueueSender qSender = null;
    QueueReceiver qReceiver = null;

    public JMSJNDISample () {
    }


    public void init() throws JMSException, NamingException {
        // Set up JNDI Context
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY);
        env.put(Context.PROVIDER_URL, JNDI_URL);
        if (JMS_USER != null)
            env.put(Context.SECURITY_PRINCIPAL, JMS_USER);
        if (JMS_PASSWORD != null)
            env.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
        Context jndiContext = new InitialContext(env);

        // Lookup queue connection factory
        QueueConnectionFactory cFactory = (QueueConnectionFactory)jndiContext.lookup(JMS_CONNECTION_FACTORY);

        // Create Connection
        if (JMS_USER == null || JMS_PASSWORD == null)
            qConn = cFactory.createQueueConnection();
        else {
            qConn = cFactory.createQueueConnection(JMS_USER, JMS_PASSWORD);
        }

        // Create Session
        qSession = qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        // Lookup Queue
        Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);

        // Create Queue Sender
        qSender = qSession.createSender(queue);

        // Create Queue Receiver
        qReceiver = qSession.createReceiver(queue);
        qReceiver.setMessageListener(this);

        // Start receiving messages
        qConn.start();

        // Close JNDI context
        jndiContext.close();
    }


    public void sendMessage (String str) throws JMSException {
        TextMessage msg = qSession.createTextMessage(str);
        qSender.send(msg);
    }


    public void onMessage (Message message) {
        try {
            if (message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage)message;
                System.out.println("Text Message Received: "+textMessage.getText());
            } else {
                System.out.println(message.getJMSType()+" Message Received");
            }
        } catch (JMSException je) {
            je.printStackTrace();
        }
    }


    public void destroy() throws JMSException {
        if (qSender != null) qSender.close();
        if (qReceiver != null) qReceiver.close();
        if (qSession != null) qSession.close();
        if (qConn != null) qConn.close();
    }


    public static void main(String args[]) {
        try {
            JMSJNDISample sample = new JMSJNDISample();
            // Initialize connetion
            sample.init();
            // Send Message
            sample.sendMessage("Hello World");
            // Wait 2 sec for answer
            Thread.sleep(2000);
            // Disconnect
            sample.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
2
votes

Other than having a MessageDrivenBean listening to that queue?

EDIT: You are using spring just to create the payload, right? JMS is a JavaEE spec. You don't need to use Spring for actually sending/receiving messages. You don't have to manually check whether there are messages in the queue etc., either. All you need to do is have an MDB(MessageDrivenBean) set up like this,

@MessageDriven(activationConfig = {
      @ActivationConfigProperty(
          propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty(
          propertyName = "destination", propertyValue = "queue/myqueue")
     })
public class MyMessageDrivenBean implements MessageListener {
     public void onMessage(Message message) {
         ObjectMessage objMsg = (ObjectMessage) message;
         Payload payload = (Payload)objMsg.getObject();
         //do stuff
}

}

And then send some JMS messages.

@Stateless
public class QueuerBean implements QueuerLocal {

    @Resource(mappedName = "java:/JmsXA")
    private ConnectionFactory jmsConnectionFactory;
    @Resource(mappedName = "queue/myqueue")
    private Queue queue;

    private void queue(MyPayload payload) {
        try {
            Connection connect = jmsConnectionFactory.createConnection();
            Session session = connect.createSession(false,
                Session.DUPS_OK_ACKNOWLEDGE);
            MessageProducer producer = session.createProducer(queue);
            // create a JMS message and send it
            ObjectMessage objMsg = session.createObjectMessage(payload);
            producer.send(objMsg);
            producer.close();
            session.close();
            connect.close();
        } catch (JMSException e) {
            log.error("Bad thing happened", e);
        }
    }
}

The queue is configured by the annotation. When a message is sent, JBoss will automatically trigger the MDB.

1
votes

Here's an example showing how to set up a message-driven POJO in Spring. I'd recommend following this idiom if you're already using Spring.

As for the part about seeing how many messages are on the queue, I'd say you should be using the admin console for JBOSS, not your code.

0
votes

I would recommend also using a tool like HermesJMS (http://www.hermesjms.com/confluence/display/HJMS/Home) to inspect the queue manager and queues. It's a great debugging tool.