Package org.openeai.jms.consumer

Source Code of org.openeai.jms.consumer.PubSubConsumer$ConsumerShutdownHook

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/jms/consumer/PubSubConsumer.java,v $
$Revision: 1.19 $
*******************************************************************************/

/**********************************************************************
This file is part of the OpenEAI Application Foundation or
OpenEAI Message Object API created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.

Copyright (C) 2002 The OpenEAI Software Foundation

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For specific licensing details and examples of how this software
can be used to build commercial integration software or to implement
integrations for your enterprise, visit http://www.OpenEai.org/licensing.
*/

package org.openeai.jms.consumer;

// JNDI Stuff
import javax.naming.*;
import javax.naming.directory.*;

// Java Messaging Service
import javax.jms.*;

// General
import java.util.*;

import java.io.IOException;

import java.sql.SQLException;

import org.openeai.config.*;
import org.openeai.threadpool.*;
import org.openeai.jms.consumer.commands.SyncCommand;

/**
* This consumer consumes messages from a JMS Topic.  Then based on the content of the message
* it executes 'SyncCommands' associated to the consumer and the message consumed as specified
* in it's configuration document (deployment descriptor).
*<P>
* The actual business logic related to the message consumed is performed by the Sync command
* implementations.
* <P>
  * @author      Tod Jackson (tod@openeai.org)
  * @author      Steve Wheat (steve@openeai.org)
  * @version     3.0  - 4 February 2003
*/
public class PubSubConsumer extends MessageConsumer {

  private TopicConnectionFactory m_tcf = null;
  private Topic m_topic = null;
  private TopicConnection m_topicConnection = null;
  private TopicSession m_topicSession = null;
  private TopicSubscriber m_topicSubscriber = null;
  private MyTopicListener m_listener = null;
  private PubSubMessageBalancer m_balancer = null;
  private boolean m_monitorRunning = false;

  public PubSubConsumer() {
    setAppName("Pub/Sub Consumer v1.0");
  }

  public PubSubConsumer(String cfName, String tName) {
    setAppName("Pub/Sub Consumer v1.0");
    setConnectionFactoryName(cfName);
    setDestinationName(tName);
  }

  /**
  * As AppConfig reads through a gateway's deployment document, it will build a
  * ConsumerConfig Java object and pass that object to this constructor.  Then
  * this consumer will have all the information it needs to initialize itself which
  * includes:
  * <ul>
  * <li>Initializing the consumer itself
  * <li>Initializing all Commands that the consumer may execute
  * <ul>
  * <P>
  * @param cConfig org.openeai.config.ConsumerConfig
  * @see org.openeai.config.ConsumerConfig
  **/
  public PubSubConsumer(ConsumerConfig cConfig) throws JMSException,
                                                       NamingException,
                                                       IOException {
    setAppName(cConfig.getAppName());
    setConfig(cConfig);
    setCommandConfigs(cConfig.getCommandConfigs());
    if (cConfig.getThreadPoolConfig() == null) {
      String errMessage =
        "Could not locate a ThreadPoolConfig object in the " +
        "configuration document for the PubSub Consumer named " +
        getConsumerName() + ".  This is required for all consumers.";
      logger.fatal(errMessage);
      throw new JMSException(errMessage);
    }
    setThreadPool(new ThreadPoolImpl(cConfig.getThreadPoolConfig()));

    // set up the utility class to check if another consumer
    // is/has processing this message (dbconnection info).
    try {
      setBalancer(new PubSubMessageBalancer(cConfig.getDbConnectionPoolConfig()));
      logger.info("Initialized message balancer.");
    }
    catch (IOException e) {
      logger.warn("Could not initialize the MessageBalancer for consumer named " +
                  getConsumerName() + ".  " +
                  "All messages delivered to this Consumer will be processed.  If you wish to run multiple instances of this " +
                  "PubSubConsumer and want the Messages balanced between instances, you must specify " +
                  "DbConnectionPoolConfig information for the PubSubConsumer in the configuration document.  Exception: " +
                  e.getMessage());
      setBalancer(null);
    }

    init(cConfig.getProperties());
    if (getStartOnInitialization()) {
      startConsumer();
    }
  }

  // StartGetter/Setters

  /**
  * This method stops the Consumer's "Monitor Thread" so it won't attempt
  * to restart the consumer.
  * <P>
  * When the consumer is started it starts a Thread that monitors the Consumer's
  * connection to the broker.  If that connection is broken for some reason, that
  * "Monitor Thread" will attempt to restart the consumer.  This continues indefinitely
  * until the consumer is able to re-connect to the broker.
  * <P>
  * This method allows an application to in effect stop that monitor thread so they can
  * shut the consumer down without it restarting itself.
  **/
  public void stopMonitor() {
    m_monitorRunning = false;
  }

  /**
  * This method starts the Consumer's "Monitor Thread".  This is a thread that runs
  * for the life of the consumer and checks the status of the consumer's connection
  * to the broker every thirty seconds.  If that connection is broken
  * for some reason, the Monitor Thread will attempt to restart the consumer,
  * re-connecting it to the broker.  It will continue to do this until either the
  * consumer is able to re-connect or the consumer is shutdown.
  **/
  public void startMonitor() {
    if (m_monitorRunning == false) {
      MonitorConsumer monitorConsumer = new MonitorConsumer(30000);
      new Thread(monitorConsumer).start();
      m_monitorRunning = true;
    }
  }

  /**
  * Returns the PubSubMessageBalancer associated to this Consumer.
  * <P>
  * @return PubSubMessageBalancer
  * @see PubSubMessageBalancer
  **/
  public final PubSubMessageBalancer getBalancer() {
    return m_balancer;
  }

  /**
  * Sets the PubSubMessageBalancer associated to this Consumer.
  * <P>
  * @param balancer PubSubMessageBalancer
  * @see PubSubMessageBalancer
  **/
  public final void setBalancer(PubSubMessageBalancer balancer) {
    m_balancer = balancer;
  }

  /**
  * Returns the Consumer's TopicConnectionFactory object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicConnectionFactory
  **/
  public final TopicConnectionFactory getTopicConnectionFactory() {
    return m_tcf;
  }

  /**
  * Sets the Consumer's TopicConnectionFactory object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @param tcf javax.jms.TopicConnectionFactory
  **/
  public final void setTopicConnectionFactory(TopicConnectionFactory tcf) {
    m_tcf = tcf;
  }

  /**
  * Returns the Consumer's Topic object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.Topic
  **/
  public final Topic getTopic() {
    return m_topic;
  }

  /**
  * Sets the Consumer's Topic object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @param topic javax.jms.Topic
  **/
  public final void setTopic(Topic topic) {
    m_topic = topic;
  }

  /**
  * Returns the Consumer's TopicConnection object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicConnection
  **/
  public final TopicConnection getTopicConnection() {
    return m_topicConnection;
  }

  /**
  * Sets the Consumer's TopicConnection object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @param topicConnection javax.jms.TopicConnection
  **/
  public final void setTopicConnection(TopicConnection topicConnection) {
    m_topicConnection = topicConnection;
  }

  /**
  * Returns the Consumer's TopicSession object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicSession
  **/
  public final TopicSession getTopicSession() {
    return m_topicSession;
  }

  /**
  * Sets the Consumer's TopicSession object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @param session javax.jms.TopicSession
  **/
  public final void setTopicSession(TopicSession session) {
    m_topicSession = session;
  }

  /**
  * Returns the Consumer's TopicSubscriber object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicSubscriber
  **/
  public final TopicSubscriber getTopicSubscriber() {
    return m_topicSubscriber;
  }

  /**
  * Sets the Consumer's TopicSubscriber object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @param topicSubscriber javax.jms.TopicSubscriber
  **/
  public final void setTopicSubscriber(TopicSubscriber topicSubscriber) {
    m_topicSubscriber = topicSubscriber;
  }
  // End Getter/Setters

  /**
  * Starts the consumer making it ready to consume messages from the Topic that
  * it connects to.  This follows the typical JMS pattern of starting a message consumer.
  * This includes:
  * <ul>
  * <li>Retrieving the JMS Administered objects (TopicConnectionFactory and Topic)
  * from a directory server or other JNDI source
  * <li>Creating a TopicConnection with the TopicConnectionFactory
  * <li>Creating a TopicSession with the TopicConnection
  * <li>Creating a TopicSubscriber with the TopicSession and Topic.  NOTE:  All OpenEAI
  * PubSubConsumers establish a durable subscription when they start.
  * <li>Establishing the MessageListener that will be used when messages are delivered
  * to the Topic.
  * </ul>
  * <P>
  * Additionally, this method starts the Consumer's Monitor that will monitor and
  * attempt to resolve any broker connection issues encountered for the life of the
  * Consumer.
  * <P>
  * @throws JMSException
  * @throws NamingException
  * @see PointToPointConsumer#startConsumer
  * @see MonitorConsumer
  **/
  public final void startConsumer() throws NamingException, JMSException {
    try {
      if (getInitializationStatus().equals(NOT_INITIALIZED)) {
        initializeConsumer();
      }
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new JMSException(e.getMessage());
    }
    logger.info("I'm the " + getConsumerName() + " Pub/Sub Consumer");

    // Create InitialContext object
    // Create InitialContext object
    logger.debug("Creating InitialContext");
    DirContext ic = null;
    // Assume the m_providerUrl and m_initCtxFactory variables have already
    // been set.
    try {
      ic = getInitialContext();
      if (ic == null) {
        throw new NamingException("Error creating initial context");
      }
      logger.debug("Created initial context");
    }
    catch (NamingException ne) {
      logger.fatal(ne.getMessage(), ne);
      throw new NamingException(ne.getMessage());
    }
    try {
      logger.debug("Connected to InitialContext");

      // Lookup TopicConnectionFactory and Topic names
      logger.debug("Looking up topic connection factory name " +
                   getConnectionFactoryName());
      m_tcf = (TopicConnectionFactory)ic.lookup(getConnectionFactoryName());
      logger.debug("Looking up topic name " + getDestinationName());
      m_topic = (Topic)ic.lookup(getDestinationName());

      // Close InitialContext resources
      ic.close();
    }
    catch (NamingException ne) {
      logger.fatal(ne.getMessage(), ne);
      throw new NamingException(ne.getMessage());
    }

    // Create and start a TopicConnection
    logger.debug("Creating topic connection");
    try {
      if (getUserName() == null || getUserName().length() < 1) {
        m_topicConnection = m_tcf.createTopicConnection();
      }
      else {
        m_topicConnection =
            m_tcf.createTopicConnection(getUserName(), getPassword());
      }
      logger.debug("Creating topic session");
      m_topicSession =
          m_topicConnection.createTopicSession(getTransacted(), TopicSession.AUTO_ACKNOWLEDGE);

      // Create TopicSubscriber
      logger.debug("Creating topic subscriber");
      if (getInstanceName() != null && getInstanceName().length() > 0) {
        m_topicSubscriber =
            m_topicSession.createDurableSubscriber(m_topic, getConsumerName() +
                                                   "-" + getInstanceName());
      }
      else {
        m_topicSubscriber =
            m_topicSession.createDurableSubscriber(m_topic, getConsumerName());
      }

      // Listen for messages
      m_listener = new MyTopicListener(m_topicSubscriber, m_topicConnection);

      setConsumerStatus(STARTED);
    }
    catch (JMSException jmsE) {
      // Don't throw exception here?  Let MonitorConsumer keep trying???
      String errMessage =
        "Error starting consumer.  Exception: " + jmsE.getMessage() +
        "  Will let MonitorConsumer Thread attempt to restart.";
      logger.fatal(errMessage);
    }

    // Start the monitor if it isn't already running.
    startMonitor();

    return;
  }

  public void stop() {
    stopConsumer();
    shutdownCommands();
  }

  /**
  * Attempts to cleanly shutdown the Consumer.  This includes closing all JMS
  * resources (TopicSubscriber, TopicSession and TopicConnection).  If errors
  * occur, it will log those errors as warnings.  However, regardless of the
  * outcome of the "clean" shutdown attempt, the consumer will be stopped.  This
  * method is called anytime the consumer detects connection problems to the broker
  * or when the consumer receives a shutdown hook from the operating system.
  * <P>
  * NOTE:  This method DOES NOT unsubscribe from durable subscriptions.  This way,
  * when the gateway is brought back up, its consumers will have any missed messages
  * available for consumption.  Durable subscriptions must be cleaned up manually
  * if that is desired.
  * <P>
  * @see MonitorConsumer
  * @see ConsumerShutdownHook
  **/
  public final void stopConsumer() {
    boolean exceptionOccurred = false;

    setConsumerStatus(STOPPED);
    stopMonitor();

    try {
      if (m_topicSubscriber != null) {
        m_topicSubscriber.close();
      }
    }
    catch (Exception e) {
      exceptionOccurred = true;
      logger.warn("Error closing TopicSubscriber: " + e.getMessage());
    }

    try {
      if (m_topicSession != null) {
        m_topicSession.close();
      }
    }
    catch (Exception e) {
      exceptionOccurred = true;
      logger.warn("Error closing TopicSession: " + e.getMessage());
    }

    try {
      if (m_topicConnection != null) {
        m_topicConnection.stop();
      }
    }
    catch (Exception e) {
      exceptionOccurred = true;
      logger.warn("Error Stopping TopicConnection: " + e.getMessage());
    }

    try {
      if (m_topicConnection != null) {
        m_topicConnection.close();
      }
    }
    catch (Exception e) {
      exceptionOccurred = true;
      logger.warn("Error Closing TopicConnection: " + e.getMessage());
    }

    if (exceptionOccurred) {
      logger.info("Everything was stopped but there were exceptions.");
    }
    else {
      logger.info("Everything was stopped successfully!");
    }

    m_tcf = null;
    m_topic = null;
  }

  /**
  * Shuts down all commands executed by this consumer.
  **/
  public void shutdownCommands() {
    // (tj) 4/17/2003 - now, shutdown the commands this consumer executes.
    Iterator it = m_messages.keySet().iterator();
    while (it.hasNext()) {
      String key = (String)it.next();
      SyncCommand s = (SyncCommand)m_messages.get(key);
      try {
        logger.info("Shutting down SyncCommand '" + key + "'");
        s.shutdown();
      }
      catch (Exception e) {
        logger.warn("Error shutting down SyncCommand '" + key +
                    "'  Processing will continue.");
      }
    }
    logger.info("All SyncCommands have been shutdown.");
  }

  /**
  * Invokes MessageConsumer.init(Properties) and adds the ConsumerShutDownHook
  * for this consumer.
  * <P>
  * @param props Properties
  * @throws IOException
  * @see MessageConsumer#init(Properties)
  **/
  protected void init(Properties props) throws IOException {
    super.init(props);

    Runtime.getRuntime().addShutdownHook(new ConsumerShutdownHook());
  }


  /**
  * Invoked by onMessage of the message listener to add this
  * message to the thread pool or to start a new thread for
  * processing this message.  This method will block if no threads
  * are available to handle this message.
  * <P>
  * @param messageCount the index of the message to be processed.
  * @param mesg The jms message to be processed.
  **/
  protected void addMessageToThreadPool(int messageCount, Message mesg) {

    if (consumptionStopped()) {
      logger.info(getConsumerName() +
                  " - Cannot consume any more messages, because the consumer is being shutdown.  Going to sleep.");
      m_inProcessMessages = new Vector();
      m_inProcessMessages.add(mesg);
      try {
        Thread.sleep(300000);
      }
      catch (Exception te) {
      }
    }

    logger.info(getConsumerName() + " - Handling Message number: " +
                messageCount);

    // MessageTransaction will process the incoming message.
    if (getThreadPool() != null) {
      boolean keepTrying = true;
      while (keepTrying) {
        try {
          getThreadPool().addJob(new MessageTransaction(messageCount, mesg));
          keepTrying = false;
        }
        catch (ThreadPoolException e) {
          logger.warn("ThreadPool is busy, sleeping and trying it again.");
          try {
            Thread.sleep(1000);
            logger.info("Woke up, trying to add message to ThreadPool again...");
          }
          catch (Exception te) {
          }
        }
      }
    }
    else {
      new MessageTransaction(messageCount, mesg).run();
    }

  }


  /**
  * This is the JMS MessageListener implementation for OpenEAI PubSubConsumers.  It
  * uses the TopicSubscriber and TopicConnection established when the consumer was
  * started to listen for messages delivered to the Topic specified in the Consumer's
  * ConsumerConfig object.
  * <P>
  * When a message is delivered to the topic the this objects onMessage method is invoked.
  * <P>
  * @author      Tod Jackson (tod@openeai.org)
  * @version     3.0  - 28 January 2003
  * @see org.openeai.config.ConsumerConfig
  * @see org.openeai.config.ThreadPoolConfig
  * @see org.openeai.threadpool.ThreadPool
  * @see PubSubConsumer.MyTopicListener#onMessage(Message)
  **/
  protected class MyTopicListener implements MessageListener {

    private int messageCount = 1;

    public MyTopicListener(TopicSubscriber topicSub,
                           TopicConnection topicConn) throws JMSException {
      topicSub.setMessageListener(this);
      topicConn.start();
      logger.info(getConsumerName() + " - Ready to receive messages...");
    }

    /**
    *
    **/
    public void onMessage(Message mesg) {
      try {
        // Before we attempt to 'handle' the message, we need to
        // check and see if anyone else that may be connected to
        // the same topic is or has handled this message.
        // This will be done using properties of the message
        // and a lightweight db that all pub/sub consumers connect
        // to.....
        String msgId = mesg.getStringProperty("MESSAGE_ID");
        if (msgId == null) {
          msgId = mesg.getStringProperty("message_id");
          if (msgId == null) {
            // error, or at least have to default to something??
            logger.warn("Null message id in JMS Message.");
            // Could send it to a command that re-publishes it to the same
            // topic with a message id...
          }
        }

        if (getBalancer() != null) {
          try {
            if (getBalancer().canConsumerProcess(msgId) == false) {
              // another consumer is handling this message
              logger.info("Another consumer is already handling message: " +
                          msgId);
              return;
            }
          }
          catch (SQLException e) {
            // there was an error determining if we can handle this
            // message.  Should we continue or not???
            logger.fatal("Error determining if we can process this message.  Exception: " +
                         e.getMessage());
          }
        }

        addMessageToThreadPool(messageCount, mesg);

        if (m_topicSession.getTransacted()) {
          m_topicSession.commit();
        }
        messageCount++;
        logger.info(getConsumerName() + " - Ready to receive messages...");
      }
      catch (Exception e) {
        logger.fatal("Error processing message " + messageCount +
                     "  Exception: " + e.getMessage());
        logger.fatal(e.getMessage(), e);
        try {
          if (m_topicSession.getTransacted()) {
            m_topicSession.rollback();
          }
        }
        catch (JMSException je) {
          logger.fatal("Error rolling transaction back or determining the transaction mode.");
          logger.fatal(je.getMessage(), je);
        }
      }
    }
  }

  /**
   * This Thread will be started when the consumer receives a shutdown signal from the os.
   * It is established via the Runtime.getRuntime().addShutdownHook(new ConsumerShutdownHook());
   * in the init() method.  The purpose of this is to allow a "clean" shutdown of the consumers
   * without losing any messages that might be in progress when shutdown occurrs.
   * <P>
   * @author Tod Jackson
   */
  protected class ConsumerShutdownHook extends Thread {
    public void run() {
      logger.info(getConsumerName() +
                  " - Consumer shutdown hook, stopping consumer");
      logger.info(getConsumerName() + " - Waiting for threads to complete...");

      // Stop all consumption to give our thread pool a chance to finish up.
      stopConsumption();

      // we'll probably only want to wait for a maximum period of time
      // until we go ahead and stop the consumer regardless of threads
      // in progress??
      if (getThreadPool() != null) {
        int elapsedWaitTime = 0;
        while (getThreadPool().getJobsInProgress() > 0 &&
          elapsedWaitTime < getMaximumThreadPoolShutdownWaitTime()) {
         
          try {
            elapsedWaitTime += 500;
            Thread.sleep(500);           
          }
          catch (Exception e) {
          }
        }
      }
     
      if (getThreadPool() != null && getThreadPool().getJobsInProgress() > 0) {
        logger.warn("There are still " + getThreadPool().getJobsInProgress() +
          " threads in process.  However, the maximum time to wait for the " +
          "thread pool to empty (" + getMaximumThreadPoolShutdownWaitTime() +
          " milliseconds) has expired.  Consumer shutdown is continuing.");
      }
      else {
        logger.info(getConsumerName() + " - All threads are complete.");
      }
     
      // Process any messages that were in process when shutdown started.
      if (m_inProcessMessages != null) {
        logger.info(getConsumerName() + " - Processing " +
                    m_inProcessMessages.size() +
                    " messages that were in progress when shutdown was started.");
        for (int i = 0; i < m_inProcessMessages.size(); i++) {
          Message msg = (Message)m_inProcessMessages.get(i);
          new MessageTransaction(0, msg).run();
        }
      }

      stopConsumer();
      logger.info(getConsumerName() +
                  " - Consumer shutdown hook, consumer stopped, now exiting.");
    }
  }

  /**
   * This Thread will sleep for a specified period of time and then wake up
   * and check the status of the consumer by attempting to create/delete a TemporaryTopic.
   * If the creation of the TemporaryTopic fails, it assumes there is something wrong
   * with the consumer's connection to the broker and it is not consuming any messages.
   * When that happens, it attempts to do a "clean" shutdown on the consumer and
   * then restarts the consumer which will re-establish its connection to the broker
   * and it will start consuming messages again.  This means, if brokers must be taken down
   * for any reason (on purpose or not), gateways will NOT need to be restarted
   * when the broker comes back up, rather, they will do that themselves.  This process
   * continues until it is stopped via the stopMonitor method or until the gateway
   * is stopped.  If a broker is down for an extended period of time, this Monitor
   * will continue to try and reconnect until the broker is back online.
   * <P>
   * The thread is started when the consumer is started the first time.
   * <P>
   * @author Tod Jackson
   * @see #stopMonitor
   */
  protected class MonitorConsumer implements java.lang.Runnable {
    private int m_sleepInterval = 30000; // thirty seconds

    public MonitorConsumer(int sleepInterval) {
      m_sleepInterval = sleepInterval;
    }

    private boolean restartConsumer() {
      if (consumptionStopped() == false) {
        stopConsumer();
        try {
          startConsumer();
        }
        catch (Exception e1) {
          logger.fatal("Error restarting consumer.  Exception: " +
                       e1.getMessage());
        }
        return true;
      }
      else {
        logger.info("Consumer is being shutdown, won't attempt to restart in MonitorConsumer.");
        return false;
      }
    }

    public void run() {
      // sleep for m_sleepInterval
      // wake up, try to do something with the session
      // if an exception occurs, restart the consumer
      boolean stayAlive = true;
      while (stayAlive) {
        try {
          Thread.sleep(m_sleepInterval);
          if (m_monitorRunning == false) {
            logger.info("Monitor has been stopped.  Returning from Monitor Thread.");
            return;
          }
        }
        catch (Exception e) {
          logger.fatal("Error sleeping...");
        }
        // wake up and try to access the session
        try {
          if (m_topicSession != null) {
            TemporaryTopic tb = m_topicSession.createTemporaryTopic();
            tb.delete();
            logger.debug("Session is okay.");
          }
          else {
            logger.fatal("Session is null, need to restart the consumer.");
            stayAlive = restartConsumer();
          }
        }
        catch (JMSException e) {
          logger.fatal("Session is not usable, need to restart the consumer.  Exception: " +
                       e.getMessage());
          stayAlive = restartConsumer();
        }
      }
    }
  }
}
TOP

Related Classes of org.openeai.jms.consumer.PubSubConsumer$ConsumerShutdownHook

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.