3
\$\begingroup\$

I need a standalone client that consumes messages from the queue every time a message exists. I already have set-up an ActiveMQ queue named hello.world.

ConsumerClient.java

public class ConsumerClient {

    public static void main(String[] args){

        Thread thread = new Thread(new Consumer("tcp://localhost:61616", "hello.world"));
        thread.start();
    }
}

Consumer.java

public class Consumer implements Runnable{

    private String brokerUrl;
    private String queueName;
    private boolean isRunning;

    public Consumer(String brokerUrl, String queueName) {
        this.brokerUrl = brokerUrl;
        this.queueName = queueName;
        isRunning = true;
    }

    @Override
    public void run() {


        while (isRunning) {

            System.out.println("Listening for messages...");

            Connection connection = null;
            MessageConsumer consumer = null;
            Session session = null;

            try {

                //Create a connection factory 
                ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);

                //Create a connection 
                connection = connectionFactory.createConnection();
                connection.setExceptionListener(new ExceptionListener(){
                    @Override
                    public void onException(JMSException arg0) {
                        System.out.println("JMS Exception occurred...");
                    }
                });


                //Create a session
                session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

                //Create destination
                Destination destination = session.createQueue(queueName);

                //Create consumer
                consumer = session.createConsumer(destination);

                //Start the connection
                connection.start();

                Message message = consumer.receive();
                if (message instanceof TextMessage) {
                    TextMessage txtMessage = (TextMessage) message;
                    try {
                        //Persist message to database
                        //...some code that persists message to database
                        session.commit();
                    } catch (Exception e) { 
                        //Persistence failed
                        session.rollback();
                    }
                }


            } catch (JMSException e) {
                e.printStackTrace();
            } finally {
                if (consumer != null)
                    try {
                        consumer.close();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }

                if (session != null)
                    try {
                        session.close();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }

                if (connection != null)
                    try {
                        connection.close();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
            }
        }
    }
}

I'm not sure if I need to use a MessageListener instead (honestly, I don't know where the MessageListener would fit in my code since if I remove MessageConsumer.receive() and added my own listener, my application hangs since there's no synchronous blocking). We're planning to have at least two of these consumers up just in case one fails.

Is this best practice? We don't use JNDI and I feel that Apache Camel would be too much for a simple process like this.

Should I be creating a deployable .war file instead?

\$\endgroup\$
10
  • \$\begingroup\$ Why would you want a *.war file? A JAR file can be run standalone too... Also, are you on Java 6/7/8? \$\endgroup\$
    – h.j.k.
    Commented Jun 30, 2015 at 23:45
  • \$\begingroup\$ By "every time a message exists" do you mean in real time? \$\endgroup\$
    – dev_feed
    Commented Jul 1, 2015 at 14:01
  • \$\begingroup\$ Is there a business rule against the application hanging? Why are you tryng to achieve blocking? You can set message IDs if you're interested in specific messages. \$\endgroup\$
    – dev_feed
    Commented Jul 1, 2015 at 14:02
  • \$\begingroup\$ @dev_feed Yes, real time. \$\endgroup\$
    – mpmp
    Commented Jul 1, 2015 at 16:46
  • \$\begingroup\$ @h.j.k I don't really know the best practice with regards to standalone apps. Seeing that we run all our projects in a servlet container, I was wondering if a .war could be suitable for this. \$\endgroup\$
    – mpmp
    Commented Jul 1, 2015 at 16:47

1 Answer 1

1
\$\begingroup\$

a standalone client that consumes messages from the queue every time a message exists

If you want to process the messages in real time, implementing a message listener is the most practical way -- this way you let ActiveMQ and JMS handle the continuous checking that you're currently doing. As you said, you could do this in a WAR, but a JAR, or thread could accomplish the same task.

If you weren't implementing runnable and coding inside your current while (isRunning) { loop, your current setup would be more appropriate for retrieving one message at a specific time. Since you are, you're basically telling the JVM to create a connection, create a session, retrieve one message, kill everything, and start over. This just adds a ton of overhead best left to the API.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.