/** * CopyRight by Chinamobile * * ComsumerTool.java */ package com.chinamobile.bcbsp.comm; import java.io.IOException; import java.util.Iterator; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.ObjectMessage; import javax.jms.Topic; import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Consumer tool for receiving messages from Message Queue. * * @author * @version */ public class ConsumerTool extends Thread implements MessageListener, ExceptionListener { // For log private static final Log LOG = LogFactory.getLog(ConsumerTool.class); private boolean running; private Session session; private Destination destination; private MessageConsumer consumer; private MessageProducer replyProducer; private boolean pauseBeforeShutdown = false; private int maxiumMessages = 0; // If >0, end consumer based on max message // number. private String subject = "BSP.DEFAULT"; // Should be jobID, if jobs's no = // 1, default is ok. private boolean topic = false; private String user = ActiveMQConnection.DEFAULT_USER; private String password = ActiveMQConnection.DEFAULT_PASSWORD; private String url = null; // "failover://vm://brokerName" private boolean transacted = false; private boolean durable = false; private String clientId; private int ackMode = Session.DUPS_OK_ACKNOWLEDGE; private String consumerName = "BSPConsumer"; private long sleepTime = 0; private long receiveTimeOut = 1000; // If < 0, set consuming mode to // listener. private long batch = 500; // Default batch size for CLIENT_ACKNOWLEDGEMENT or // SESSION_TRANSACTED private long messagesReceived = 0; private long messageCount = 0; private MessageQueuesInterface messageQueues; //brokerName for this staff to receive messages. private String brokerName; private Receiver receiver = null; /** * Constructor * * @param incomingQueues * @param subject1 * @param subject2 */ public ConsumerTool( Receiver aReceiver, MessageQueuesInterface messageQueues, String brokerName, String subject) { this.receiver = aReceiver; this.messageQueues = messageQueues; this.brokerName = brokerName; this.subject = subject; } public void showParameters() { System.out.println("Connecting to URL: " + url); System.out.println("Consuming " + (topic ? "topic" : "queue") + ": " + subject); System.out.println("Using a " + (durable ? "durable" : "non-durable") + " subscription"); } public void run() { try { running = true; this.url = "failover://vm://" + this.brokerName; ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( user, password, url); connectionFactory.setOptimizeAcknowledge(true); Connection connection = connectionFactory.createConnection(); if (durable && clientId != null && clientId.length() > 0 && !"null".equals(clientId)) { connection.setClientID(clientId); } connection.setExceptionListener(this); connection.start(); session = connection.createSession(transacted, ackMode); if (topic) { destination = session.createTopic(subject); } else { destination = session.createQueue(subject); } replyProducer = session.createProducer(null); replyProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); if (durable && topic) { consumer = session.createDurableSubscriber( ( Topic ) destination, consumerName); } else { consumer = session.createConsumer(destination); } consumeMessages(connection, session, consumer, receiveTimeOut); LOG.info("[ConsumerTool] has received " + this.messagesReceived + " object messages from <" + this.subject + ">."); LOG.info("[ConsumerTool] has received " + this.messageCount + " BSP messages from <" + this.subject + ">."); this.receiver.addMessageCount(this.messageCount); } catch (Exception e) { LOG.error("[ConsumerTool] caught: ", e); } } public void onMessage(Message message) { messagesReceived++; try { if (message instanceof ObjectMessage) { ObjectMessage objMsg = ( ObjectMessage ) message; BSPMessagesPack msgPack = ( BSPMessagesPack ) objMsg.getObject(); BSPMessage bspMsg; Iterator<BSPMessage> iter = msgPack.getPack().iterator(); while (iter.hasNext()) { bspMsg = iter.next(); String vertexID = bspMsg.getDstVertexID(); this.messageQueues.incomeAMessage(vertexID, bspMsg); this.messageCount ++; } } else { // Message received is not ObjectMessage. LOG.error("[ConsumerTool] Message received is not ObjectMessage!"); } if (message.getJMSReplyTo() != null) { replyProducer.send(message.getJMSReplyTo(), session .createTextMessage("Reply: " + message.getJMSMessageID())); } if (transacted) { if ((messagesReceived % batch) == 0) { System.out.println("Commiting transaction for last " + batch + " messages; messages so far = " + messagesReceived); session.commit(); } } else if (ackMode == Session.CLIENT_ACKNOWLEDGE) { if ((messagesReceived % batch) == 0) { System.out.println("Acknowledging last " + batch + " messages; messages so far = " + messagesReceived); message.acknowledge(); } } } catch (JMSException e) { LOG.error("[ConsumerTool] caught: ", e); } finally { if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } public synchronized void onException(JMSException ex) { System.out.println("[" + this.getName() + "] JMS Exception occured. Shutting down client."); running = false; } synchronized boolean isRunning() { return running; } protected void consumeMessagesAndClose(Connection connection, Session session, MessageConsumer consumer) throws JMSException, IOException { System.out.println("[" + this.getName() + "] We are about to wait until we consume: " + maxiumMessages + " message(s) then we will shutdown"); for (int i = 0; i < maxiumMessages && isRunning();) { Message message = consumer.receive(1000); if (message != null) { i++; onMessage(message); } } System.out.println("[" + this.getName() + "] Closing connection"); consumer.close(); session.close(); connection.close(); if (pauseBeforeShutdown) { System.out.println("[" + this.getName() + "] Press return to shut down"); System.in.read(); } } protected void consumeMessagesAndClose(Connection connection, Session session, MessageConsumer consumer, long timeout) throws JMSException, IOException { System.out .println("[" + this.getName() + "] We will consume messages while they continue to be delivered within: " + timeout + " ms, and then we will shutdown"); Message message; while ((message = consumer.receive(timeout)) != null) { onMessage(message); } System.out.println("[" + this.getName() + "] Closing connection"); consumer.close(); session.close(); connection.close(); } protected void consumeMessages(Connection connection, Session session, MessageConsumer consumer, long timeout) throws JMSException, IOException { Message message; while (!this.receiver.getNoMoreMessagesFlag()) { while ((message = consumer.receive(timeout)) != null) { onMessage(message); } } consumer.close(); session.close(); connection.close(); } public void setAckMode(String ackMode) { if ("CLIENT_ACKNOWLEDGE".equals(ackMode)) { this.ackMode = Session.CLIENT_ACKNOWLEDGE; } if ("AUTO_ACKNOWLEDGE".equals(ackMode)) { this.ackMode = Session.AUTO_ACKNOWLEDGE; } if ("DUPS_OK_ACKNOWLEDGE".equals(ackMode)) { this.ackMode = Session.DUPS_OK_ACKNOWLEDGE; } if ("SESSION_TRANSACTED".equals(ackMode)) { this.ackMode = Session.SESSION_TRANSACTED; } } public void setClientId(String clientID) { this.clientId = clientID; } public void setConsumerName(String consumerName) { this.consumerName = consumerName; } public void setDurable(boolean durable) { this.durable = durable; } public void setMaxiumMessages(int maxiumMessages) { this.maxiumMessages = maxiumMessages; } public void setPauseBeforeShutdown(boolean pauseBeforeShutdown) { this.pauseBeforeShutdown = pauseBeforeShutdown; } public void setPassword(String pwd) { this.password = pwd; } public void setReceiveTimeOut(long receiveTimeOut) { this.receiveTimeOut = receiveTimeOut; } public void setSleepTime(long sleepTime) { this.sleepTime = sleepTime; } public void setSubject(String subject) { this.subject = subject; } public void setTopic(boolean topic) { this.topic = topic; } public void setQueue(boolean queue) { this.topic = !queue; } public void setTransacted(boolean transacted) { this.transacted = transacted; } public void setUrl(String url) { this.url = url; } public void setUser(String user) { this.user = user; } public void setBatch(long batch) { this.batch = batch; } }