Package org.openeai.implementations.services.els.commands

Source Code of org.openeai.implementations.services.els.commands.EnterpriseSyncErrorLogger

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/implementations/services/els/commands/EnterpriseSyncErrorLogger.java,v $
$Revision: 1.6 $
*******************************************************************************/

/**********************************************************************
This file is part of the OpenEAI sample, reference implementation,
and deployment management suite 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 program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; 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 implement integrations for your enterprise, visit
http://www.OpenEai.org/licensing.
*/

package org.openeai.implementations.services.els.commands;

import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.*;
import javax.jms.*;

import org.apache.log4j.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.*;
import org.jdom.output.XMLOutputter;

import org.openeai.config.*;
import org.openeai.dbpool.*;
import org.openeai.jms.producer.*;
import org.openeai.jms.consumer.*;
import org.openeai.jms.consumer.commands.*;
import org.openeai.loggingutils.MailService;
import org.openeai.xml.*;

/**
* The EnterpriseSyncErrorLogger is a part of the OpenEAI "Enterprise Logging Service" (ELS). 
* This particular command consumes messages published to an organization's
* Enterprise sync error logging topic and stores those messages.  Synchronization error messages
* are published by any sync consuming gateway when errors occur processing those messages. 
* This way, a concise record can be kept of each error that occurs within that gateway.  This is of
* course in addition to any information that gets logged by the gateway at the time of the error.
* <P>
* By deploying a EnterpriseSyncErrorLogger, an organization can keep track of all errors that
* occur in other Sync consuming gateways and keep a record of them.  Then, interfaces can be developed to query those errors
* in order to determine what errors have occurred etc. and link them back to the actual message that
* was consumed by the gateway that had the problem.  Protocol information (SenderAppId, MessageId etc.)
* is used to link these messages together.
* <P>
* @author Alan Schuele and Greg Hunt
* @version #
*/
public class EnterpriseSyncErrorLogger extends SyncCommandImpl implements SyncCommand {

  private String m_xmlFileSpec = null;
  private EnterpriseConnectionPool m_connPool = null;

  /**
   * Constructor
   * @param Command Config
   */
  public EnterpriseSyncErrorLogger(CommandConfig cConfig) throws InstantiationException {
    super(cConfig);

    // This is so the inherited Logger configuration (specified at the gateway level)
    // can be overriden at the command level.
    try {
      LoggerConfig lConfig = new LoggerConfig();
      lConfig = (LoggerConfig)getAppConfig().getObjectByType(lConfig.getClass().getName());
      logger = Category.getInstance(getClass().getName());
      PropertyConfigurator.configure(lConfig.getProperties());
      logger.warn("got a LoggerConfig from the command's app config..." + lConfig.getProperties());
    }
    catch (Exception e) {
      logger = org.openeai.OpenEaiObject.logger;
      logger.debug("no LoggerConfig in the command's app config...");
      logger.debug(e.getMessage(), e);
    }

    try {
      PropertyConfig pConfig = new PropertyConfig();
      pConfig = (PropertyConfig)getAppConfig().getObjectByType(pConfig.getClass().getName());
      setProperties(pConfig.getProperties());

      // get PropertyConfig Properties
      PropertyConfig propConfig = (PropertyConfig)getAppConfig().getObject("SyncLoggerProperties");
      if (propConfig == null) {
        String msg = "Unable to find PropertyConfig 'SyncLoggerProperties'";
        logger.fatal(msg);
        throw new InstantiationException(msg);
      }

      Properties props = propConfig.getProperties();

      // Initialize email settings
      this.setToAddr(props.getProperty("toAddr"));
      this.setFromAddr(props.getProperty("fromAddr"));
      this.setMailHost(props.getProperty("mailHost"));

      m_xmlFileSpec = props.getProperty("xmlFileSpec");

      // Initialize db connection pool (actually, it's already initialized and ready for use in AppConfig.)
      m_connPool = (EnterpriseConnectionPool)getAppConfig().getObject("EnterpriseSyncErrorLoggerDbPool");

      logger.info("EnterpriseSyncErrorLogger, instantiated successfully.");
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new InstantiationException(e.getMessage());
    }
  }

  /**
  * Takes the message passed in, breaks it into the appropriate parts and logs it
  * to the repository.
  * <P>
  * @param int the message number associated to the message consumed by the consumer executing this command.
  * @param javax.jms.Message the message consumed by the consumer.  In this case, the message should
  * always be a CoreMessaging/Sync/Error-Sync message.
  * @throws CommandException if errors occur initializing the command with the message
  * passed in.  This particular command may throw this exception when it has errors
  * turning the text associated to the Message into a JDOM Document or if it has problems
  * persisting the contents.  This is because it would be redundant for this consumer to
  * publish CoreMessaging/Sync/Error-Sync messages to itself.  Instead of publishing the Sync/Error-Sync
  * message, this command may either throw an exception or write the message to the file system if
  * it has problems persisting the message.
  **/
  /**
  * Inserts the current contents of this object into the database (T_SYNC_ERR_MSG).
  * The object was populated by the calling command (EnterpriseSyncLoggerCommand) and
  * the java.sql.Connection object was retrieved from the Database Connection Pool object
  * associated to this command.
  * <P>
  * This method not only logs the appropriate ControlArea information into the T_LOGGED_MESSAGE
  * table but it breaks the actual message into segments if the message body is
  * larger than 3900 bytes.  This implementation was originally developed for an Oracle
  * database and VARCHAR2 fields can be a maximum of 4000 characters.  This is why the
  * message body is broken into segments.  Depending on the database implementation being
  * used, this number may be different.  The class could also be written to either allow this
  * setting to be configurable or to break the message body into a universal segment that
  * would work for any database.  These individual segments are stored in the T_MESSAGE_SEGMENT
  * table.
  * <P>
  * The ControlArea information (metadata) is inserted into the T_SYNC_ERR_MSG table.  The
  * information is pulled from the ControlArea of the message and inserted into the
  * T_SYNC_ERR_MSG table:
  * <P>
  * <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
  * <TR>
  * <TH>ControlArea Element</TH>
  * <TH>Column</TH>
  * <TH>Description</TH>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Sender/MessageId/SenderAppId</TD>
  * <TD>CONSUMING_APPL_NAME</TD>
  * <TD>SenderAppId of the gateway that published the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Sender/MessageId/ProducerId</TD>
  * <TD>CONSUMING_PRODUCER_ID</TD>
  * <TD>ProducerId associated to the gateway that published the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Sender/MessageId/MessageSequence</TD>
  * <TD>CONSUMING_MSG_SEQ</TD>
  * <TD>MessageSequence associated to the gateay that published the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/ProcessedMessageId/SenderAppId</TD>
  * <TD>PRODUCING_APPL_NAME</TD>
  * <TD>SenderAppId of the gateway that published the message consumed by the gateway that had the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/ProcessedMessageId/ProducerId</TD>
  * <TD>PRODUCING_PRODUCER_ID</TD>
  * <TD>ProducerId of the gateway that published the message consumed by the gateway that had the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/ProcessedMessageId/MessageSequence</TD>
  * <TD>PRODUCING_MSG_SEQ</TD>
  * <TD>MessageSequence of the gateway that published the message consumed by the gateway that had the error.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result@action</TD>
  * <TD>PRODUCING_MSG_ACTION</TD>
  * <TD>Message action associated to the message that consumed by the gateway that had the error.</TD>
  * </TR>
  * </TABLE>
  * <P>
  * The error information associated to the Sync-Error message consumed by this gateway is logged to
  * the T_SYNC_ERROR table.  This includes all Errors listed in the Result element of the Sync-Error
  * message.  A row will be inserted for each Error listed in the Result element.  This information is stored as follows:
  * <P>
  * <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
  * <TR>
  * <TH>ControlArea Element</TH>
  * <TH>Column</TH>
  * <TH>Description</TH>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/Error@type</TD>
  * <TD>ERROR_TYPE</TD>
  * <TD>The type of error that occurred in the consuming gateway when it tried to process the message.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/Error/ErrorNumber</TD>
  * <TD>ERROR_NUMBER</TD>
  * <TD>The error number generated by the gateway that had the error processing the message.</TD>
  * </TR>
  * <TR HALIGN="left" VALIGN="top">
  * <TD>ControlAreaSync/Result/Error/ErrorDescription</TD>
  * <TD>CONSUMING_APPL_NAME</TD>
  * <TD>The error description generated by the gateway that had the error processing the message.</TD>
  * </TR>
  * </TABLE>
  * <P>
  * @param int the message number associated to the message consumed by the consumer executing this command.
  * @param javax.jms.Message the message consumed by the consumer.  In this case, the message should
  * always be a CoreMessaging/Sync/Error-Sync message.
  * @throws CommandException if errors occur initializing the command with the message
  * passed in.  This particular command may throw this exception when it has errors
  * turning the text associated to the Message into a JDOM Document or if it has problems
  * persisting the contents.  This is because it would be redundant for this consumer to
  * publish CoreMessaging/Sync/Error-Sync messages to itself.  Instead of publishing the Sync/Error-Sync
  * message, this command may either throw an exception or write the message to the file system if
  * it has problems persisting the message.
  **/
  public void execute(int messageNumber, Message aMessage) throws CommandException {
    Document inDoc = null;
    try {
      inDoc = initializeInput(messageNumber, aMessage);
    }
    catch (Exception e) {
      e.printStackTrace();
      logger.fatal(e.getMessage(), e);
      throw new CommandException(e.getMessage());
    }

    try {
      insertMessage(inDoc);
    }
    catch (java.sql.SQLException e) {
      e.printStackTrace();
      logger.fatal(e.getMessage(), e);
      throw new CommandException(e.getMessage());
    }
  }

  private void insertMessage(Document doc) throws SQLException {
    // Get the appropriate information out of the message
    // Insert the values into the database along with the actual
    // message as a string.

    //boolean successOnInsert = false;
    java.sql.Connection conn = null;
    PreparedStatement insertStmt = null;

    String consAppName, consProdId, consMsgSeq, prodAppName, prodProdId;
    String prodMsgSeq, prodMsgAction, message;
    //String logConsumerId = "SyncErrorLogConsumer";

    String insertString =
    "INSERT INTO T_SYNC_ERROR_MSG " +
    " (CONSUMING_APPL_NAME, CONSUMING_PRODUCER_ID, CONSUMING_MSG_SEQ, PRODUCING_APPL_NAME, " +
    "  PRODUCING_PRODUCER_ID, PRODUCING_MSG_SEQ, PRODUCING_MSG_ACTION, MESSAGE, CREATE_DATE, CREATE_USER, MOD_DATE, MOD_USER) " +
    "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";

    String insertString2 =
    "INSERT INTO T_SYNC_ERROR " +
    " (SYNC_ERROR_MSG_ID, ERROR_TYPE, ERROR_NUMBER, ERROR_DESC, CREATE_DATE, CREATE_USER, MOD_DATE, MOD_USER) " +
    "VALUES (?,?,?,?,?,?,?,?)";

    String syncErrorMsgId=null, errorType, errorNumber, errorDescr;

    Element controlArea = getControlArea(doc.getRootElement());

    // Getting data to insert into T_SYNC_ERROR_MSG
    consAppName = controlArea.getChild("Sender").getChild("MessageId").getChild("SenderAppId").getText();
    consProdId = controlArea.getChild("Sender").getChild("MessageId").getChild("ProducerId").getText();
    consMsgSeq = controlArea.getChild("Sender").getChild("MessageId").getChild("MessageSeq").getText();
    prodAppName = controlArea.getChild("Result").getChild("ProcessedMessageId").getChild("SenderAppId").getText();
    prodProdId = controlArea.getChild("Result").getChild("ProcessedMessageId").getChild("ProducerId").getText();
    prodMsgSeq = controlArea.getChild("Result").getChild("ProcessedMessageId").getChild("MessageSeq").getText();
    prodMsgAction = controlArea.getChild("Result").getAttribute("action").getValue();

    // Getting data to insert into T_SYNC_ERROR

    XMLOutputter xmlOut = new XMLOutputter();
    ByteArrayOutputStream bArray = new ByteArrayOutputStream();
    try {
      xmlOut.output(doc, bArray);
    }
    catch (IOException e) {
      logger.fatal(e.getMessage(), e);
      errorHandler(e, doc)// Call routine to write doc out to a file
      return;
    }
    byte[] b = bArray.toByteArray();
    message = new String(b);

    try {
      conn = m_connPool.getConnection();
//      conn.setAutoCommit(false);
// Setting to true to work around jdbc shortcomings - 1/24/02 Alan, Jun and Greg
      conn.setAutoCommit(true);

      insertStmt = conn.prepareStatement(insertString);
      insertStmt.clearParameters();
      insertStmt.setString(1, consAppName);
      insertStmt.setString(2, consProdId);
      insertStmt.setString(3, consMsgSeq);
      insertStmt.setString(4, prodAppName);
      insertStmt.setString(5, prodProdId);
      insertStmt.setString(6, prodMsgSeq);
      insertStmt.setString(7, prodMsgAction);
      insertStmt.setString(8, message);
      insertStmt.setTimestamp(9, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(10, conn.getMetaData().getUserName());
      insertStmt.setTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(12, conn.getMetaData().getUserName());
      logger.debug("InsertStmt = " + insertStmt);
      int insertRc = insertStmt.executeUpdate();
      insertStmt.close();

      if (insertRc != 1) {
        // the insert wasn't successful
        SQLException exc = new SQLException("Error inserting into T_SYNC_ERROR_MSG.  Return Code: " + insertRc);
        errorHandler(exc, doc);
        throw exc;
      }
      else {
        logger.info("Successfully inserted Message into T_SYNC_ERROR_MSG.");

        // get id of row just entered
        Statement stmt = conn.createStatement();
        String query =
        "SELECT SYNC_ERROR_MSG_ID FROM T_SYNC_ERROR_MSG WHERE " +
        " CONSUMING_APPL_NAME = '" + consAppName + "' AND CONSUMING_PRODUCER_ID = '" +
        consProdId + "' AND CONSUMING_MSG_SEQ = '"+ consMsgSeq +"'";
        logger.debug("Query = " + query);
        ResultSet rs = stmt.executeQuery(query);
        rs.next();

        syncErrorMsgId = rs.getString(1);
        logger.debug("syncErrorMsgId from Select = " + syncErrorMsgId);
        rs.close();
        stmt.close();

        logger.debug("about to insert error portion");

        // Getting data to insert into T_SYNC_ERROR
        insertStmt = conn.prepareStatement(insertString2);

        Iterator itr = controlArea.getChild("Result").getChildren().iterator();
        while (itr.hasNext()) {
          Element errorElement = (Element)itr.next();
          logger.debug(errorElement.getName());

          if (errorElement.getName().equals("Error")) {
            // Do something with these children

            errorType = errorElement.getAttribute("type").getValue();
            errorNumber = errorElement.getChild("ErrorNumber").getText();
            errorDescr = errorElement.getChild("ErrorDescription").getText();
            // check if greater than 3800 size
            if (errorDescr.length() > 3800) {
              errorDescr = errorDescr.substring(0, 3800);
            }

            logger.debug("about to insert error portion, errorNumber = " + errorNumber);

            // Insert into T_SYNC_ERROR
            insertStmt.clearParameters();
            insertStmt.setString(1, syncErrorMsgId);
            insertStmt.setString(2, errorType);
            insertStmt.setString(3, errorNumber);
            insertStmt.setString(4, errorDescr);
            insertStmt.setTimestamp(5, new java.sql.Timestamp(System.currentTimeMillis()));
            insertStmt.setString(6, conn.getMetaData().getUserName());
            insertStmt.setTimestamp(7, new java.sql.Timestamp(System.currentTimeMillis()));
            insertStmt.setString(8, conn.getMetaData().getUserName());
            insertRc = insertStmt.executeUpdate();
            if (insertRc != 1) {
              // the insert wasn't successful
//              conn.rollback();

              SQLException exc = new SQLException("Error inserting.  Return Code: " + insertRc);

              // Call ErrorHandler
              errorHandler(exc, doc);

              throw exc;
            }
            else {
              logger.info("Successfully inserted Message into T_SYNC_ERROR.");
              //successOnInsert = true;          insertStmt = conn.prepareStatement(insertString2);
            }
          }
        }

        insertStmt.close();

//        conn.commit();
      }
    }
    catch (SQLException se) {  // Handle sql exeptions(s)
      errorHandler(se, doc);
      while (se != null) {
        String errMsg = "";
        errMsg ="SQLState: " + se.getSQLState() + " Message:  " + se.getMessage()+
                " Vendor:   " + se.getErrorCode();
        logger.fatal(errMsg + " " +se.getMessage(), se);
        se = se.getNextException();
      }
    }
    catch (Exception e) {
      //if (successOnInsert == false) {
      errorHandler(e, doc)// write message to a file
      //}
      logger.error(e.getMessage());
    }
    finally {
      try {
        insertStmt.close();
      }
      catch (SQLException see) {
        logger.error(see.getMessage());
      }
      //m_connPool.releaseConnectierrorElement.getName()on(conn);
    }
  }

  private void errorHandler(Exception exc, Document doc) {
    exc.printStackTrace();
    logger.error(exc.toString());
    String datedDirectoryName = getDatedDirectoryName(m_xmlFileSpec);
    boolean directoryChecker = this.isDirectoryFound(datedDirectoryName);
    if (directoryChecker == false) {
      directoryChecker = this.createDirectory(datedDirectoryName);
      if (directoryChecker == false) {
        logger.error("Error: Unable to write message to message-store. Now writing message to log.");
        logger.error(doc.toString());
        return;
      }
    }
    // If you get to here, write out message to the directory
    try {
      // Write message out to directory specified in config xml doc
      this.writeMessageToFile("", doc, datedDirectoryName);
    }
    catch (java.io.IOException ioe) {
      logger.error("Error: Unable to write message to message-store directory: " + datedDirectoryName + " Now writing message to log.");
      logger.error(doc.toString());
    }
  }

  private String getDatedDirectoryName(String xmlFileSpec) {
    int year, dayOfMonth, month;

    Calendar today = new GregorianCalendar();

    year = today.get(today.YEAR);
    month = today.get(today.MONTH) + 1;
    dayOfMonth = today.get(today.DAY_OF_MONTH);

    String today_string = String.valueOf(year) + "-" +
                          String.valueOf(month) + "-" +
                          String.valueOf(dayOfMonth);
    String datedDirectoryName = xmlFileSpec+"/"+today_string;
    return datedDirectoryName;
  }

  private boolean isDirectoryFound(String xmlFileSpec) {
    File messageStore = new File(xmlFileSpec);
    return messageStore.exists();
  }

  private boolean createDirectory(String xmlFileSpec) {
    File messageStore = new File(xmlFileSpec);
    return messageStore.mkdirs();
  }

  public void sendEmail(String emailBody) {
    // send email
    try {
      StringBuffer buf = new StringBuffer();
      buf.append("Error in EnterpriseSyncErrorLogger. ");
      buf.append("\n");
      buf.append(emailBody);
      buf.append("\n");
      MailService mailService = new MailService(this.getFromAddr(), this.getToAddr() , "Error in EnterpriseSyncErrorLogger", buf.toString());
      mailService.setMailHost(this.getMailHost());
      mailService.sendMessage();
    }
    catch (Exception exc) {
      logger.info("Error sending email message - " + exc);
    }
  }
}
TOP

Related Classes of org.openeai.implementations.services.els.commands.EnterpriseSyncErrorLogger

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.