Package org.openeai.config

Source Code of org.openeai.config.ProducerConfig

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/config/ProducerConfig.java,v $
$Revision: 1.14 $
*******************************************************************************/

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

import org.jdom.Attribute;
import org.jdom.Element;

import org.openeai.xml.*;
import org.openeai.*;
import org.openeai.jms.producer.PubSubProducer;

/**
* A ProducerConfig is a wrapper class that takes information stored in an
* OpenEAI Deployment document (ProducerConfig Element) and stores it in a Java object.
* Then the configuration object is passed to the constructor of the OpenEAI
* MessageProducers (PointToPointProducer and PubSubProducer)
* and they are able to configure themselves with the information found in the
* config object.
* <P>
* Both PubSub and PointToPoint Producers use the same configuration information
* to initialize themselves.  However, some items listed in a ProducerConfig Element
* are only used by PubSubProducers and some are only used by PointToPointProducers.
* Where this is the case, it is noted.
* <P>
* <B>Configuration Parameters:</B>
* <P>
* These are the configuration parameters specified by the ProducerConfig
* Element in the Deployment document.  NOTE:  Like all other OpenEAI configuration
* objects, there is a "container" level associated to ProducerConfig objects.
* Many Elements and attributes are required at that level and may be optionally
* overridden at this level.  This is to avoid having to enter redundant information
* in the Deployment document if all (or most) Producers being configured should use
* the same configuration information.  Therefore, many of the Producer configuration
* parameters are optional at this level but required at the "container" level.  Where
* this is the case, it will be indicated by an "*".
* <P>
* Many of the parameters specified for a producer are simply JMS parameters required
* by the JMS Specification.
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>name</TD>
* <TD>yes</TD>
* <TD>Name of the Producer.  This will be used in many logged messages and is
* the name by which a producer is stored in AppConfig.  A Producer name should
* be unique within an application.  If the 'numberOfProducers' attribute is specified
* this name will be the name of the ProducerPool object which is stored in AppConfig
* and is a collection of initialized producer objects.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>numberOfProducers</TD>
* <TD>no (default is 1)</TD>
* <TD>This parameter indicates how many producers of this type should be initialized
* with the configuration information listed and stored in a ProducerPool object.  The
* ProducerPool is then stored in AppConfig and can be retrieved just like any other object
* housed by AppConfig.  If the numberOfProducers attribute is specified, a ProducerPool
* will be created with that number of producers in it.  If numberOfProducers is not specified
* only the Producer being configured will be stored in AppConfig.
* <P>
* It is recommended that most applications utilize a ProducerPool even if the
* number of producers in the pool is only 1.  This gives the application
* flexibility to increase this number at a later time
* and potentially improve the application's performance by increasing the number of
* producers in the pool.  This would be determined after a period of time depending
* on how much load the application is under on a regular basis.  By increasing this
* number, performance is generally improved in a multi-threaded application because
* of Thread synchronization that must occur when only one producer is used across threads.
* Generally, this is only used for PointToPoint producers but it can be used for
* PubSubProducers as well.  Generally, PointToPoint production is most critical
* when it comes to performance.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>tempPoolSize</TD>
* <TD>no (default is 5)</TD>
* <TD>This parameter indicates how many TemporaryQueues and QueueReceivers on
* those TemporaryQueues will be initialized when the Producer is first started.
* During message production, TempoaryQueues and QueueRecievers will be dynamically
* created when necessary.  This is another performance enhancement that reduces
* the overhead associated to PointToPoint message production and response consumption.
* The OpenEAI PointToPoint producers use TemporaryQueues to send messages.  However,
* since the producers must be thread safe, they cannot use the same temporary queue
* when a message is produced.  If they did, producers being used by two threads
* concurrently, would potentially step on each other when a response was returned
* by the consumer of the request produced.
* <P>
* There are two ways to avoid this situation:
* One is to create a new TemporaryQueue and QueueReciever each time the producer produces
* a Request.  This is expensive.  The second alternative is to create a "pool" of
* TempoaryQueues and QueueReceivers upon initialization and restrict access to those
* resources when messages are produced and only create a new TemporaryQueue/QueueReceiver
* if an available resource cannot be obtained from the pool.  Any TempoaryQueue/QueueReceiver
* that must be created because the pool is busy, is cleaned up when the request
* has been completed.  By monitoring how many TempoaryQueues are being created dynamically
* for an application and setting this number higher, one can affect the
* performance of Point-To-Point messaging significantly
* because fewer resources have to be allocated each time a request is produced.
* <P>
* This is only relevant to PointToPointProducers.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>startOnInitialization</TD>
* <TD>no*</TD>
* <TD>This parameter tells the Producer whether or not it should start
* (be ready to produce/publish messages) upon initialization.  If the flag is
* set to true, the Producer will initialize itself and then actually create
* the connection to the broker.  If this flag is false, the Producer will
* initialize itself so that it is ready to be started but it won't actually
* create the connection to the broker.  Therefore, before a producer that
* hasn't been started can actually produce/publish messages, it must be
* started explicitly by the application using it.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>acknowledgementMode</TD>
* <TD>no</TD>
* <TD>JMS parameter </TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>transacted</TD>
* <TD>no</TD>
* <TD>JMS parameter </TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>deliveryMode</TD>
* <TD>no</TD>
* <TD>JMS parameter </TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>LoggingProducer</TD>
* <TD>no</TD>
* <TD>This is a PubSubProducer object configured to publish PubSubMessages
* to a "logging" destination as they are published by the PubSubProducer being
* configured.  Therefore, when a PubSubProducer publishes a message via the
* publishMessage method, that message will potentially be published to
* the logging destination by the LoggingProducer as well.  This is a feature
* that allows an organization to specifically track every PubSub message
* published within their organization.
* <P>
* Because PubSub messages are not used for "synchronous" messaging as
* specified by the OpenEAI Message Protocol
* they are typically published and processed by messaging applications and gateways
* when no one is watching.  Therefore, it is useful to be able to keep track of
* all messages that are published incase an emergency occurs where a message
* needs to be resubmitted etc.  OpenEAI provides one logging gateway
* as a reference implementation to demonstrate the usefulness of this.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ConnectionFactoryName</TD>
* <TD>no*</TD>
* <TD>The name of the JMS Administered object (TopicConnectionFactory or
* QueueConnectionFactory) that this Producer will use
* to initialize itself from a JMS perspective.  To maintain broker independance,
* this adminstered object should be stored in a Directory server.</TD>
* </TR>
* <TD>DestinationName</TD>
* <TD>yes</TD>
* <TD>The name of the JMS Administered object (Topic or Queue) that this Producer
* will produce/publish messages to.  To maintain broker independance,
* this administered object should be stored in a Directory server.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>InitialContextFactory</TD>
* <TD>no*</TD>
* <TD>The name of the JNDI context factory that will be used to retrieve the JMS
* administered objects from a Directory Server or wherever the administered
* objects are stored.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ProviderURL</TD>
* <TD>no*</TD>
* <TD>Location where the administered objects can be retrieved from. 
* To maintain broker independance, this should reference a location in a
* Directory server.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>SecurityPrincipal</TD>
* <TD>no*</TD>
* <TD>The user with which to create the InitialContext when retrieving the
* Administered objects.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>SecurityCredentials</TD>
* <TD>no*</TD>
* <TD>The credentials associated to the user with which to create the
* InitialContext when retrieving the Administered objects.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>Username</TD>
* <TD>no*</TD>
* <TD>Broker user with which to connect to the broker as.  Generally, this is
* stored within the ConnectionFactory administered object so it is not needed
* here.  However, if it isn't stored or you wish to override what's stored
* in the AO, you can specify that here.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>Password</TD>
* <TD>no*</TD>
* <TD>Password associated to the broker user with which to connect to the broker
* as.  Generally, this is stored within the ConnectionFactory administered
* object so it is not needed here.  However, if it isn't stored or you wish
* to override what's stored in the AO, you can specify that here.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ProducerIdURL</TD>
* <TD>no*</TD>
* <TD>URL used to generate a unique Producer Id for this producer.  Generally,
* this is a URL that resolves to the OpenEAI UuidGen servlet which generates
* a unique UUID and returns it to the caller.  If this URL is "localhost"
* the id will be generated locally and will be unique for the machine running
* the application.  This ProducerId will become part of all messages using
* the OpenEAI foundation that are produced with this producer.</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ConfigClass</TD>
* <TD>no*</TD>
* <TD>Name of the configuration class that wraps the config Element (this class)</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ObjectClass</TD>
* <TD>yes</TD>
* <TD>Name of the Java object that will be instantiated with this Config class
* (PointToPointProducer or PubSubProducer)</TD>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>DefaultCommandName</TD>
* <TD>no</TD>
* <TD>Used by the LoggingProducer when it publishes messages to set the COMMAND_NAME
* JMS Property on the Message that it publises to the "logging" destination.  Generally, this is
* not needed because the EnterpriseLoggingService should generally execute only one
* Command (absolute command).</TD>
* </TR>
* </TABLE>
* @author      Tod Jackson (tod@openeai.org)
* @author      Steve Wheat (steve@openeai.org)
* @version     3.0  - 28 January 2003
* @see org.openeai.jms.producer.PointToPointProducer
* @see org.openeai.jms.producer.PubSubProducer
* @see org.openeai.jms.producer.ProducerPool
* @see org.openeai.jms.producer.TempQueuePool
* @see ConsumerConfig
*/
public class ProducerConfig
extends EnterpriseConfigurationObjectImpl
implements EnterpriseConfigurationObject {

  private PubSubProducer m_loggingProducer = null;

  /**
   * This is the constructor used by AppConfig to instantiate the config object.
   * Then, AppConfig calls this object's init(Element) method passing the configuration
   * element it retrieved from the XML configuration document which this object uses
   * to configure itself.  After this object has initialized itself,
   * it will be used to instantiate and initialize the framework object
   * (MessageObject, Producers, Consumers etc.)
   * with the properties it's been initialized with.
   */
  public ProducerConfig() {
    setType("ProducerConfig");
  }

  public ProducerConfig(String configDocUrl, String producerName) throws EnterpriseConfigurationObjectException {
    setType("ProducerConfig");
    XmlDocumentReader xmlReader = new XmlDocumentReader();
    try {
      setConfigDoc(xmlReader.initializeDocument(configDocUrl, getValidation()));
    }
    catch (XmlDocumentReaderException e) {
      logger.fatal(e.getMessage(), e);
    }
    setName(producerName);
    init();
  }

  public ProducerConfig(Element configElement) throws EnterpriseConfigurationObjectException {
    setType("ProducerConfig");
    init(configElement);
  }

  /**
   * This method sets the logging producer that will be associated to an OpenEAI PubSubProducer.
   *<P>
   * All OpenEAI PubSubProducers have a LoggingProducer associated to them.  This is just another
   * PubSubProducer that is configured to publish messages to a "logging topic".  This event
   * occurs when a message is published by the publisher if the logging producer exists and is started.
   * So, the end result is that messages published by PubSubProducers may get published twice.  Once to the
   * intended destination as specified in the PubSubProducer's configuration and once to the destination
   * associated to the PubSubProducer's LoggingProducer.  These "logged" messages serve as a tracking
   * mechanism so that every message published by a message aware application can be persisted in a
   * repository.
   *<P>
   * @param producer PubSubProducer the configured and potentially started "logging producer"
   * @see org.openeai.jms.producer.PubSubProducer
   */
  public void setLoggingProducer(PubSubProducer producer) {
    m_loggingProducer = producer;
  }
  /**
   * This method returns the logging producer that will be associated to an OpenEAI PubSubProducer.
   * @return PubSubProducer
   * @see PubSubProducer
   */
  public PubSubProducer getLoggingProducer() {
    return m_loggingProducer;
  }

  /**
   * Implements the init(Element) method that all EnterpriseConfiguration objects must implement.
   * This init method takes the Configuration element passed in and pulls out configuration information
   * specific to the Producer (PubSub or PointToPoint) being initialized.
   * Then it sets various instance variables and properties on itself which will
   * be used by the Producer when AppConfig instantiates it passing this configuration object.
   * The Producer will then use the configuration java object to initialize itself.
   *
   * @param configElement Element the configuration element that AppConfig has pulled from the configuration document
   * relevant to the Producer being configured.  Or, the element that was found in the init() method.
   * @throws EnterpriseConfigurationObjectException if errors occur processing the configuration Element.
   */
  public void init(Element configElement) throws EnterpriseConfigurationObjectException {
    try {
    String producerName = configElement.getAttribute("name").getValue();
    logger.debug("Element returned: ");
    logger.debug("  - " + configElement.getName());
    logger.debug("  Producer Name: " + producerName);
    String start = configElement.getAttribute("startOnInitialization").getValue();

    // Add all attributes as 'Properties'
    java.util.List attrs = configElement.getAttributes();
    for (int i=0; i<attrs.size(); i++) {
      Attribute attr = (Attribute)attrs.get(i);
      String key = attr.getName();
      String value = attr.getValue();
      logger.debug("ProducerConfig, Adding " + key + " - " + value);
      addProperty(key, value);
    }

    // Add all elements as 'Properties'
    java.util.List props = configElement.getChildren();
    for (int i=0; i<props.size(); i++) {
      Element aProp = (Element)props.get(i);
      if (aProp.getName().equals("LoggingProducer")) {
        try {
          setLoggingProducer(new PubSubProducer(new ProducerConfig(aProp)));
        }
        catch (Exception e) {
          logger.fatal(e.getMessage(), e);
        }
      }
      else {
        String key = aProp.getName();
        String value = aProp.getText();
        logger.debug("Adding " + key + " - " + value);
        addProperty(key, value);
      }
    }
    }
    catch (Exception e) {
      String errMessage = "Exception configuring ProducerConfig.  Exception: " + e.getMessage();
      logger.fatal(errMessage, e);
      throw new EnterpriseConfigurationObjectException(errMessage, e);
    }
  }

  /**
   * Implements the init() method that all EnterpriseConfiguration objects must implement.
   * This init method retreives the root element of the confuration document and
   * then finds the specific configuration element associated to the Producer being configured
   * then it calls the init(Element) method which actually initializes the ProducerConfig
   * with the information found in the configuration element.
   *
   */
  private void init() throws EnterpriseConfigurationObjectException {
    Element rootElement = getConfigDoc().getRootElement();
    logger.debug("RootElement is: " + rootElement.getName());
    logger.debug("Looking for ProducerConfig named: " + getName());
    // Find the element specified by producerName in the document
    Element configElement = getConfigElementByAttributeValue(getName(), "name");
    init(configElement);
  }
}
TOP

Related Classes of org.openeai.config.ProducerConfig

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.