Package org.openeai.jms.producer

Source Code of org.openeai.jms.producer.PubSubProducer$MonitorProducer

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/jms/producer/PubSubProducer.java,v $
$Revision: 1.26 $
*******************************************************************************/

/**********************************************************************
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.producer;

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

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

// General
import java.util.*;
import java.io.*;

// JDOM
import org.jdom.Document;
import org.jdom.output.XMLOutputter;

import org.openeai.config.*;
import org.openeai.transport.ProducerId;
import org.openeai.transport.SyncService;
import org.openeai.transport.TransportException;
import org.openeai.moa.ActionableEnterpriseObject;
import org.openeai.moa.XmlEnterpriseObject;

/**
* The PubSubProducer produces messages to a JMS Topic.
* <P>
* @author      Tod Jackson (tod@openeai.org)
* @author      Steve Wheat (steve@openeai.org)
* @version     3.0  - 4 February 2003
* @see PointToPointProducer
* @see org.openeai.jms.consumer.PubSubConsumer
*/
public class PubSubProducer
extends MessageProducer implements SyncService {

  private TopicConnectionFactory m_tcf = null;
  private Topic m_topic = null;
  private TopicConnection m_topicConnection;
  private TopicSession m_topicSession;
  private TopicPublisher m_topicPublisher;
  private PubSubProducer m_loggingProducer = null;
  private boolean m_monitorRunning = false;

  public PubSubProducer() {
    setAppName("Pub/Sub Producer v1.0");
  }
  /**
  * As AppConfig reads through an application's deployment document, it will build a
  * ProducerConfig Java object and pass that object to this constructor.  Then
  * this producer will have all the information it needs to initialize itself which.
  * <P>
  * @param pConfig org.openeai.config.ProducerConfig
  * @see org.openeai.config.ProducerConfig
  * @see org.openeai.jms.producer.PointToPointProducer
  **/
  public PubSubProducer(ProducerConfig pConfig) throws IOException, JMSException {
    setAppName("Pub/Sub Producer v1.0");
    init(pConfig.getProperties());
    if (getStartOnInitialization()) {
      startPublisher();
    }
    setLoggingProducer(pConfig.getLoggingProducer());
  }

  // StartGetter/Setters
  /**
  * Returns the Producers'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 Producers'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 Producers'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 Producers'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 Producers'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 Producers'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 Producers'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 Producers'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 Producers's TopicPublisher object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicPublisher
  **/
  public final TopicPublisher getTopicPublisher() {
    return m_topicPublisher;
  }
  /**
  * Sets the Producers's TopicPublisher object.
  * <P>
  * See the JMS Specification to learn more about JMS objects.
  * <P>
  * @return javax.jms.TopicPublisher
  **/
  public final void setTopicPublisher(TopicPublisher topicPublisher) {
    m_topicPublisher = topicPublisher;
  }
  // End Getter/Setters

  /**
  * Sets the Logging Producer associated to this producer which is simply another
  * PubSubProducer that may be configured in the deployment document to publish
  * messages published by this producer to a second "logging" destination.
  * <P>
  * @param producer PubSubProducer the "logging producer"
  * @see org.openeai.config.ProducerConfig
  **/
  public final void setLoggingProducer(PubSubProducer producer) {
    m_loggingProducer = producer;
  }
  /**
  * Returns the Logging Producer associated to this producer which is simply another
  * PubSubProducer that may be configured in the deployment document to publish
  * messages published by this producer to a second "logging" destination.
  * <P>
  * @return PubSubProducer the "logging producer"
  * @see org.openeai.config.ProducerConfig
  **/
  public final PubSubProducer getLoggingProducer() {
    return m_loggingProducer;
  }

  /**
  * This method stops the Producer's "Monitor Thread" so it won't attempt
  * to restart the producer.
  * <P>
  * When the producer is started it starts a Thread that monitors the Producer's
  * connection to the broker.  If that connection is broken for some reason, that
  * "Monitor Thread" will attempt to restart the producer.  This continues indefinitely
  * until the producer 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 producer down without it restarting itself.
  **/
  public void stopMonitor() {
    m_monitorRunning = false;
  }
  /**
  * This method starts the Producer's "Monitor Thread".  This is a thread that runs
  * for the life of the producer and checks the status of the producer's connection
  * to the broker every thirty seconds.  If that connection is broken
  * for some reason, the Monitor Thread will attempt to restart the producer,
  * re-connecting it to the broker.  It will continue to do this until either the
  * producer is able to re-connect or the producer is shutdown.
  **/
  public void startMonitor() {
    if (m_monitorRunning == false) {
      MonitorProducer monitorProducer = new MonitorProducer(30000);
      new Thread(monitorProducer).start();
      m_monitorRunning = true;
    }
  }
  public final void stop() {
    stopPublisher();
  }
  /**
  * Attempts to cleanly shutdown the Producer.  This includes closing all JMS
  * resources (TopicPublisher, TopicSession and TopicConnection).  If errors
  * occur, it will log those errors as warnings.  However, regardless of the
  * outcome of the "clean" shutdown attempt, the producer will be stopped.  This
  * method is called anytime the producer detects connection problems to the broker
  * or when specifically called from an application or gateway using this Producer.
  * <P>
  * @see MonitorProducer
  **/
  public final void stopPublisher() {
    boolean exceptionOccurred = false;

    setProducerStatus(STOPPING);
    stopMonitor();
    try {
      if (m_topicPublisher != null) {
        m_topicPublisher.close();
      }
    }
    catch (Exception jmse) {
      exceptionOccurred = true;
      logger.warn("Error closing TopicPublisher: " + jmse.getMessage());
    }

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

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

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

    if (getLoggingProducer() != null) {
      if (getLoggingProducer().isStarted()) {
        getLoggingProducer().stopPublisher();
      }
    }
  }

  /**
  * Commit any transactions pending on this publisher and on its LoggingProducer.
  **/
  public final void commit() throws JMSException {
    // commit any pending transactions on this producer's session.
    getTopicSession().commit();
    if (getLoggingProducer() != null) {
      if (getLoggingProducer().isStarted()) {
        // commit any pending transactions on the logging producer's session.
        if (getLoggingProducer().getTransacted()) {
          getLoggingProducer().commit();
        }
      }
    }
  }

  /**
  * Rollback any transactions pending on this publisher and on its LoggingProducer.
  **/
  public final void rollback() throws JMSException {
    // commit any pending transactions on this producer's session.
    getTopicSession().rollback();
    if (getLoggingProducer() != null) {
      if (getLoggingProducer().isStarted()) {
        // commit any pending transactions on the logging producer's session.
        if (getLoggingProducer().getTransacted()) {
          getLoggingProducer().rollback();
        }
      }
    }
  }

  public final boolean start() throws JMSException {
    return startPublisher();
  }
  /**
  * Starts the producer making it ready to publish messages to the Topic that
  * it connects to.  This follows the typical JMS pattern of starting a message producer.
  * 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 TopicPublisher with the TopicSession and Topic
  * </ul>
  * <P>
  * @return boolean indicating whether or not the start was successful.
  * @throws JMSException
  * @see PointToPointProducer#startProducer
  **/
  public final boolean startPublisher() throws JMSException {
    setProducerStatus(STOPPED);
    logger.info("I'm the " + getProducerName() + " JMS Pub/Sub Producer");

    if (getConnectionFactoryName() == null || getDestinationName() == null ||
        getProviderUrl() == null || getInitialContextFactory() == null) {
      logger.fatal("Nothing's been initialized, can't start.");
      return false;
    }

    if (getProducerId(null) == null) {
      try {
        logger.debug("Getting a ProducerId object...");
        setProducerId(new ProducerId(getProducerIdUrl()));
        logger.debug("Producer id is " + getProducerId(null).getId());
      }
      catch (IOException ioe) {
        logger.fatal(ioe.getMessage(), ioe);
        return false;
      }
    }

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

    // Lookup TopicConnectionFactory and Topic names
    try {
      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
      logger.debug("Closing initial context");
      ic.close();
    }
    catch (NamingException ne) {
      logger.fatal(ne.getMessage(), ne);
      throw new JMSException(ne.getMessage());
    }
    catch (ClassCastException ce) {
      logger.fatal(ce.getMessage(), ce);
      throw new JMSException(ce.getMessage());
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new JMSException(e.getMessage());
    }
    }
    else {
      logger.info("No need to create TCF or Topic.");
    }

    try {
      logger.debug("Creating topic connection");
      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);

      logger.debug("Creating topic publisher");
      m_topicPublisher = m_topicSession.createPublisher(m_topic);
      m_topicPublisher.setPriority(9);    // Default to highest priority unless it's overridden.
      logger.debug("Starting topic connection");
      m_topicConnection.start();
      setProducerStatus(STARTED);
      logger.info(getProducerName() + " - Pub/Sub Producer Started successfully.");
    }
    catch (javax.jms.JMSException jmse) {
      logger.fatal(jmse.getMessage(), jmse);
      logger.fatal("Username: " + getUserName() + " Password: " + getPassword());
      throw jmse;
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      logger.fatal("Username: " + getUserName() + " Password: " + getPassword());
      throw new JMSException(e.getMessage());
    }
    catch (Throwable te) {
      logger.fatal(te.getMessage(), te);
      logger.fatal("Username: " + getUserName() + " Password: " + getPassword());
      throw new JMSException(te.getMessage());
    }
   
    // Start the monitor if it isn't already running.
    startMonitor();
    return true;
  }

  /**
  * Convenience method that allows calling applications to use this producer to
  * create a JMS TextMessage that is used during message production.  This is used
  * most commonly by the OpenEAI Message Object API (MOA) foundation.
  * <P>
  * @return a JMS TextMessage
  **/
  public final TextMessage createTextMessage() {
    TextMessage message = null;
    try {
      message = m_topicSession.createTextMessage();
    }
    catch (JMSException jmse) {
      logger.fatal(jmse.getMessage(), jmse);
    }
    return message;
  }

  /**
  * Publishes the message passed in to the Topic the producer
  * is connected to.  If an error occurs
  * publishing the message the first time, the producer will be restarted and
  * the producer will attempt to publish the message again.  If it cannot successfully
  * restart and re-publish the message, an exception will be thrown.
  * <P>
  * If the "logging producer" is started, the message will
  * also be published to the Topic it is connected to.
  * @param aMessage javax.jms.Message the message to produce
  * @throws JMSException if errors occur.
  **/
  public final synchronized boolean publishMessage(Message aMessage) throws JMSException {
    try {
      logger.debug("Started - Publishing message through " + m_topic.getTopicName());

      if (getDeliveryMode().equals(PERSISTENT_DELIVERY)) {
        m_topicPublisher.publish(aMessage, javax.jms.DeliveryMode.PERSISTENT, 9, 0);
      }
      else {
        m_topicPublisher.publish(aMessage, javax.jms.DeliveryMode.NON_PERSISTENT, 9, 0);
      }

      logger.debug("Done - Published message through " + m_topic.getTopicName());
      incrementMessageSequence();
      publishMessageToLog(aMessage);
    }
    catch (JMSException jmse) {
      try {
        // Attempt to restart the publisher and re-publish the message...
        logger.warn("Error publishing message: " + jmse.getMessage() +
          " attempting to restart publisher and re-publish the message.");
        try {
          stopPublisher();
          startPublisher();
          logger.info("Publisher was re-started successfully, attempting to re-publish the message.");
          m_topicPublisher.publish(aMessage);
          incrementMessageSequence();
          logger.debug("Published message through " + m_topic.getTopicName());
          publishMessageToLog(aMessage);
        }
        catch (JMSException e) {
          logger.fatal("Attempt to restart the producer failed.  Exception: " + e.getMessage());
          throw e;
        }
      }
      catch (JMSException je) {
        logger.fatal("Error rolling transaction back or determining the transaction mode.");
        logger.fatal(je.getMessage(), je);
        throw je;
      }
    }
    catch (Exception e) {
      logger.fatal("Unknown exception occurred while attempting to publish the message.  Exception: " + e.getMessage());
      logger.fatal(e.getMessage(), e);
      TextMessage tMsg = (TextMessage)aMessage;
      logger.fatal("Message contents: \n" + tMsg.getText());
      throw new JMSException(e.getMessage());
    }
    return true;
  }

  /**
  * Publishes the message passed in to the Topic the producer
  * is connected to.  If an error occurs
  * publishing the message the first time, the producer will be restarted and
  * the producer will attempt to publish the message again.  If it cannot successfully
  * restart and re-publish the message, an exception will be thrown.
  * <P>
  * If the "logging producer" is started, the message will
  * also be published to the Topic it is connected to.
  * @param theObject the ActionableEnterpriseObject on which the action is being performed
  * @param doc the XML document that has been built from the contents of theObject
  * @throws TransportExceptom if errors occur.
  **/
  public boolean publishMessage(ActionableEnterpriseObject theObject, Document doc)
  throws TransportException {
    TextMessage outMessage = createTextMessage();
    XMLOutputter xmlOut = new XMLOutputter();
    String messageBody = xmlOut.outputString(doc);
    String xmlMsgId = theObject.getMessageId().toString();
    logger.debug("PubSubProducer: ProducerId is: " + getProducerId(null).getId());
    logger.debug("PubSubProducer: MessageId is: " + xmlMsgId);

    try {
      logger.debug("Started - Publishing message through " + m_topic.getTopicName());

      outMessage.setText(messageBody);
      outMessage.setStringProperty(MessageProducer.COMMAND_NAME, theObject.getCommandName());
      outMessage.setStringProperty(MessageProducer.MESSAGE_NAME, theObject.getCommandName());   // backward compatibility
      outMessage.setStringProperty(MessageProducer.MESSAGE_ID, xmlMsgId);

      if (getDeliveryMode().equals(PERSISTENT_DELIVERY)) {
        m_topicPublisher.publish(outMessage, javax.jms.DeliveryMode.PERSISTENT, 9, 0);
      }
      else {
        m_topicPublisher.publish(outMessage, javax.jms.DeliveryMode.NON_PERSISTENT, 9, 0);
      }

      logger.debug("Done - Published message through " + m_topic.getTopicName());
      incrementMessageSequence();
      publishMessageToLog(outMessage);
    }
    catch (JMSException jmse) {
      try {
        // Attempt to restart the publisher and re-publish the message...
        logger.warn("Error publishing message: " + jmse.getMessage() +
          " attempting to restart publisher and re-publish the message.");
        try {
          stopPublisher();
          startPublisher();
          logger.info("Publisher was re-started successfully, attempting to re-publish the message.");
          m_topicPublisher.publish(outMessage);
          incrementMessageSequence();
          logger.debug("Published message through " + m_topic.getTopicName());
          publishMessageToLog(outMessage);
        }
        catch (JMSException e) {
          logger.fatal("Attempt to restart the producer failed.  Exception: " + e.getMessage());
          throw e;
        }
      }
      catch (JMSException je) {
        logger.fatal("Error rolling transaction back or determining the transaction mode.");
        logger.fatal(je.getMessage(), je);
        throw new TransportException(je.getMessage(), je);
      }
    }
    catch (Exception e) {
      logger.fatal("Unknown exception occurred while attempting to publish the message.  Exception: " + e.getMessage());
      logger.fatal(e.getMessage(), e);
      TextMessage tMsg = (TextMessage)outMessage;
      try {
        logger.fatal("Message contents: \n" + tMsg.getText());
      }
      catch (JMSException je2) { }
      throw new TransportException(e.getMessage(), e);
    }
    return true;
  }

  /**
  * @param theObject the ActionableEnterpriseObject on which the action is being performed
  * @param doc the XML document that has been built from the contents of theObject
  * @throws TransportExceptom if errors occur.
  **/
  private final void publishMessageToLog(ActionableEnterpriseObject theObject, Document doc)
  throws TransportException {
    if (getLoggingProducer() != null) {
      if (getLoggingProducer().isStarted()) {
        getLoggingProducer().publishMessage(theObject, doc);
      }
    }
  }

  /**
  * @param aMessage javax.jms.Message the message to produce
  * @throws JMSException if errors occur.
  **/
  private final void publishMessageToLog(Message aMessage) throws JMSException {
    if (getLoggingProducer() != null) {
      if (getLoggingProducer().isStarted()) {
        if (getLoggingProducer().getDefaultCommandName().length() == 0 ||
          getLoggingProducer().getDefaultCommandName() == null) {
          getLoggingProducer().setDefaultCommandName("EnterpriseSyncLogger");
        }
        String messageId = aMessage.getStringProperty("MESSAGE_ID");
        aMessage.clearProperties();
        aMessage.setStringProperty("COMMAND_NAME",getLoggingProducer().getDefaultCommandName());
        aMessage.setStringProperty("MESSAGE_ID",messageId);
        getLoggingProducer().publishMessage(aMessage);
      }
    }
  }

  public void createSync(ActionableEnterpriseObject theObject)
  throws TransportException {
    try {
      theObject.createSync(this);
    }
    catch (Exception e) {
      String errMessage = "Error processing the create sync for object " +
        getClass().getName() + "  Exception: " + e.getMessage();
      throw new TransportException(errMessage, e);
    }
  }

  public void updateSync(ActionableEnterpriseObject theObject)
  throws TransportException {
    try {
      theObject.updateSync(this);
    }
    catch (Exception e) {
      String errMessage = "Error processing the update sync for object " +
        getClass().getName() + "  Exception: " + e.getMessage();
      throw new TransportException(errMessage, e);
    }
  }

  public void deleteSync(String deleteAction, ActionableEnterpriseObject theObject)
  throws TransportException {
    try {
      theObject.deleteSync(deleteAction, this);
    }
    catch (Exception e) {
      String errMessage = "Error processing the delete sync for object " +
        getClass().getName() + "  Exception: " + e.getMessage();
      throw new TransportException(errMessage, e);
    }
  }

  /**
  * Invokes MessageProducer.init(Properties).  Additionally, adds the shutdown hook.
  * <P>
  * @param props Properties
  * @throws IOException
  * @see MessageProducer#init(Properties)
  **/
  protected void init(Properties props) throws IOException {
    super.init(props);

    Runtime.getRuntime().addShutdownHook(new ProducerShutdownHook());
  }
  /**
   * This Thread will sleep for 30 seconds and then wake up
   * and check the status of the producer by attempting to create/delete a TemporaryTopic.
   * If the creation of the TemporaryTopic fails, it assumes there is something wrong
   * with the producer's connection to the broker and it will therefore not be able to produce
   * any messages.  When that happens, it attempts to do a "clean" shutdown on the producer and
   * then restarts the producer which will re-establish its connection to the broker
   * and it will be able to produce messages again.  This means, if we have to take down
   * a broker for any reason (on purpose or not), we will NOT have to restart all our
   * "long running" producers when the broker comes back up, rather, they will do that themselves.
   * <P>
   * The thread is started when the producer is started the first time and continues
   * this process for the life of the producer.
   * <P>
   * @author Tod Jackson
   */
  protected class MonitorProducer implements java.lang.Runnable {
    private int m_sleepInterval = 30000;   // thirty seconds
    public MonitorProducer(int sleepInterval) {
      m_sleepInterval = sleepInterval;
    }

    private void restartProducer() {
      if (getProducerStatus().equalsIgnoreCase(STOPPING) == false) {
        stopPublisher();
        try {
          startPublisher();
        }
        catch (Exception e1) {
          logger.fatal("Error restarting producer.  Exception: " + e1.getMessage());
        }
      }
      else {
        logger.info("Publisher " + getProducerName() + " is in the process of being restarted, can't restart it in the MonitorProducer thread now.");
      }
    }
   
    public void run() {
      // sleep for m_sleepInterval
      // wake up, try to do something with the session
      // if an exception occurs, restart the producer
      boolean stayAlive = true;
      while(stayAlive) {
        try {
          Thread.sleep(m_sleepInterval);
        }
        catch (Exception e) {
          logger.fatal("Error sleeping...");
        }
        // wake up and try to access the session
        if (m_monitorRunning == false) {
          logger.info("Monitor has been stopped.  Returning from Monitor Thread.");
          return;
        }
        try {
          if (m_topicSession != null) {
            TemporaryTopic tb = m_topicSession.createTemporaryTopic();
            tb.delete();
            logger.debug("Session is okay.");
          }
          else {
            logger.warn("Session is null, need to restart the " + getProducerName() + " producer.");
            restartProducer();
          }
        }
        catch(JMSException e) {
          logger.warn("Session is not usable, need to restart the " + getProducerName() + " producer.  Exception: " + e.getMessage());
          restartProducer();
        }
      }
    }
  }
  /**
   * This Thread will be started when the producer receives a shutdown signal from the os.
   * It is established via the Runtime.getRuntime().addShutdownHook(new ProducerShutdownHook());
   * in the init() method.  The purpose of this is to allow a "clean" shutdown of the producer.
   * <P>
   * @author Tod Jackson
   */
  protected class ProducerShutdownHook extends Thread {
    public void run() {
      logger.info(getProducerName() + " - Producer shutdown hook, stopping producer");
      m_monitorRunning = false;
      stopPublisher();
      logger.info(getProducerName() + " - Producer shutdown hook, producer stopped, now exiting.");
    }
  }
}
TOP

Related Classes of org.openeai.jms.producer.PubSubProducer$MonitorProducer

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.
d', 'pageview');