Package org.jboss.soa.esb.listeners.gateway

Source Code of org.jboss.soa.esb.listeners.gateway.SqlTableGatewayListener

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.soa.esb.listeners.gateway;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.util.StreamUtils;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.eprs.JDBCEpr;
import org.jboss.soa.esb.client.ServiceInvoker;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.common.TransactionStrategy;
import org.jboss.soa.esb.common.TransactionStrategyException;
import org.jboss.soa.esb.couriers.CourierException;
import org.jboss.soa.esb.filter.FilterManager;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.helpers.persist.JdbcCleanConn;
import org.jboss.soa.esb.helpers.persist.SimpleDataSource;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.listeners.ListenerUtil;
import org.jboss.soa.esb.listeners.RegistryUtil;
import org.jboss.soa.esb.listeners.lifecycle.AbstractThreadedManagedLifecycle;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleException;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleThreadState;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.services.registry.RegistryException;
import org.jboss.soa.esb.services.registry.ServiceNotFoundException;
import org.jboss.soa.esb.util.ClassUtil;
import org.jboss.soa.esb.util.Util;

/**
* Polls an SQL table for rows that satisfy conditions defined in the xml
* runtime configuration
* <p/>
* <p/>When a row that matches conditions is retrieved, it's contents are packed
* into an ESB Message and
* <p/>
* <p/> The following fields are mandatory (see checkMyParms()): <br/> <br/>SQL
* table name <br/>list of fields to retrieve <br/>list of key fields to use in
* the update statement <br/>a field that will be used to mark a row as
* 'P' (pending), 'W' (in process), 'D' (done) or 'E' (error).      When adding
* a pending row, make sure that the status_col value if an upper-cased 'P', as
* upper-cased characters are used as a convention.
*
* @author <a
*         href="mailto:schifest@heuristica.com.ar">schifest@heuristica.com.ar</a>
* @author <a href="mailto:tcunning@redhat.com">tcunning@redhat.com</a>
* @since Version 4.0
*/
public class SqlTableGatewayListener extends AbstractThreadedManagedLifecycle {

    /**
     * The current transaction strategy
     */
    private TransactionStrategy transactionStrategy ;

  private boolean transacted;
   
    public SqlTableGatewayListener(ConfigTree config)
            throws ConfigurationException {
        super(config);
        _config = config;
        _sleepBetweenPolls = 10000;
        checkMyParms();
    } // __________________________________

    /**
     * Handle the initialisation of the managed instance.
     *
     * @throws ManagedLifecycleException for errors while initialisation.
     */
    protected void doInitialise() throws ManagedLifecycleException {
      // Needed to retain prior semantics of fail-on-initialise if service lookup fails
        try {
            Collection<EPR> _targetEprs = RegistryUtil.getEprs(_targetServiceCategory,
                    _targetServiceName);
            if (null == _targetEprs || _targetEprs.size() < 1)
                throw new ManagedLifecycleException("EPR <"
                        + _targetServiceName + "> not found in registry");
       
        } catch (ServiceNotFoundException snfe) {
            throw new ManagedLifecycleException("EPR <" + _targetServiceName + " "
                + _targetServiceName + "> not found in registry");
        }
        catch (final RegistryException re) {
          throw new ManagedLifecycleException("Unexpected registry exception", re);
        }
       
        try {
          _serviceInvoker = new ServiceInvoker(_targetServiceCategory, _targetServiceName);
          _serviceInvoker.loadServiceClusterInfo();
        } catch (MessageDeliverException mde) {
          throw new ManagedLifecycleException(mde);       
        }

        boolean failure = true;
        try {
          _dbConn = getDbConn();
            failure = false;
        }
        finally {
            if (failure) {
                releaseDBConnection();
            }
        }
    }

    /**
     * Execute on the thread.
     */
    protected void doRun() {
        if (_logger.isDebugEnabled()) {
            _logger.debug("doRun() method of "
                    + this.getClass().getSimpleName() + " started on thread "
                    + Thread.currentThread().getName());
        }

        try {
            do {
                transactionStrategy.begin() ;
                boolean rollbackOnly = true ;
                try {
                    for (Map<String, Object> row : pollForCandidates()) {
                        _currentRow = row;
                        // Try to mark as 'in process' - if unsuccessful, somebody else
                        // got it first
                        if (!changeStatusToWorking())
                            continue;
       
                        Throwable thrown = null;
                        String text = null;
                        try {
                            Object obj = _processMethod.invoke(_composer, new Object[]
                                    {_currentRow});
                            if (null == obj) {
                                _logger.warn("Action class method <"
                                        + _processMethod.getName()
                                        + "> returned a null object");
                                continue;
                            }
                            Message message = (Message) obj;
                            Map<String, Object> params = new HashMap<String, Object>();
       
                            params.put(Environment.GATEWAY_CONFIG, _config);
       
                            message = FilterManager.getInstance().doOutputWork(message, params);
                           
                            _serviceInvoker.deliverAsync(message);
                        } catch (MessageDeliverException e) {
                          thrown = e;
                          text = "Target service <" + _targetServiceCategory
                            + "," + _targetServiceName
                            + "> is not registered";
                      } catch (InvocationTargetException e) {
                            thrown = e;
                            text = "Problems invoking method <"
                                    + _processMethod.getName() + ">";
                        }
                        catch (IllegalAccessException e) {
                            thrown = e;
                            text = "Problems invoking method <"
                                    + _processMethod.getName() + ">";
                        }
                        catch (ClassCastException e) {
                            thrown = e;
                            text = "Action class method <" + _processMethod.getName()
                                    + "> returned a non Message object";
                        }
                        catch (CourierException e) {
                            thrown = e;
                            text = "Message filter FAILED";
                        }

                       
                        if (null == thrown) {
                            if (_deleteAfterOK)
                                deleteCurrentRow();
                            else
                                changeStatusToDone();
                        } else {
                            _logger.error(text);
                            _logger.debug(text, thrown);
                            changeStatusToError();
                        }
                    }
                    rollbackOnly = false ;
                } finally {
                    if (rollbackOnly) {
                        transactionStrategy.rollbackOnly() ;
                    }
                    transactionStrategy.terminate() ;
                }
            }
            while (!waitForRunningStateChange(ManagedLifecycleThreadState.STOPPING,
                    _sleepBetweenPolls));
        } catch (final TransactionStrategyException tse) {
            _logger.warn("Unexpected transaction strategy exception", tse) ;
        }

        if (_logger.isDebugEnabled()) {
            _logger
                    .debug("run() method of " + this.getClass().getSimpleName()
                            + " finished on thread "
                            + Thread.currentThread().getName());
        }
    } // ________________________________

    /**
     * Handle the threaded destroy of the managed instance.
     *
     * @throws ManagedLifecycleException for errors while destroying.
     */
    protected void doThreadedDestroy() throws ManagedLifecycleException {
        if (_dbConn != null) {
            _dbConn.release();
        }
    }

    /**
     * Check for mandatory and optional attributes in parameter tree
     *
     * @throws ConfigurationException -
     *                                if mandatory atts are not right or actionClass not in
     *                                classpath
     */
    private void checkMyParms() throws ConfigurationException {
        _targetServiceCategory = ListenerUtil.getValue(_config,
                ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG, null);
        _targetServiceName = ListenerUtil.getValue(_config,
                ListenerTagNames.TARGET_SERVICE_NAME_TAG, null);

        if (_targetServiceCategory == null)
          throw new ConfigurationException("No service category defined!");
       
        if (_targetServiceName == null)
          throw new ConfigurationException("No service name defined!");
       
        // Polling interval
        String sAux = _config
                .getAttribute(ListenerTagNames.POLL_LATENCY_SECS_TAG);

        if (!Util.isNullString(sAux)) {
            try {
                _sleepBetweenPolls = 1000 * Long.parseLong(sAux);
            }
            catch (NumberFormatException e) {
                _logger.warn("Invalid poll latency - keeping default of "
                        + (_sleepBetweenPolls / 1000));
            }
        } else {
            _logger.warn("No value specified for: "
                    + ListenerTagNames.POLL_LATENCY_SECS_TAG
                    + " -  Using default of " + (_sleepBetweenPolls / 1000));
        }

        resolveComposerClass();

        _driver = ListenerUtil.getValue(_config, JDBCEpr.DRIVER_TAG, null);
        _url = ListenerUtil.getValue(_config, JDBCEpr.URL_TAG, null);
        _user = ListenerUtil.getValue(_config, JDBCEpr.USERNAME_TAG, null);
        _password = ListenerUtil.getValue(_config, JDBCEpr.PASSWORD_TAG, "");
        _datasource = ListenerUtil.getValue(_config, JDBCEpr.DATASOURCE_TAG, null);
       
        _tableName = _config.getAttribute(ListenerTagNames.SQL_TABLE_NAME_TAG);
        if (null == _tableName)
            _tableName = _config.getRequiredAttribute(JDBCEpr.TABLE_NAME_TAG);
        if (Util.isNullString(_tableName))
            throw new ConfigurationException("Empty or invalid table name");

        _selectFields = ListenerUtil.getValue(_config,
                ListenerTagNames.SQL_SELECT_FIELDS_TAG, "*");
        if (Util.isNullString(_selectFields))
            throw new ConfigurationException(
                    "Empty or invalid list of select fields");
        _keyFields = _config.getAttribute(ListenerTagNames.SQL_KEY_FIELDS_TAG);
        if (null == _keyFields)
            _keyFields = _config
                    .getRequiredAttribute(JDBCEpr.MESSAGE_ID_COLUMN_TAG);
        if (Util.isNullString(_keyFields))
            throw new ConfigurationException(
                    "Empty or invalid list of key fields");
        _inProcessField = _config
                .getAttribute(ListenerTagNames.SQL_IN_PROCESS_FIELD_TAG);
        if (null == _inProcessField)
            _inProcessField = _config.getAttribute(JDBCEpr.STATUS_COLUMN_TAG);
        if (Util.isNullString(_inProcessField))
            throw new ConfigurationException(
                    "A valid inProcessField attribute must be specified");
        _timestamp = ListenerUtil.getValue(_config,
            JDBCEpr.TIMESTAMP_COLUMN_TAG);
        if ((_timestamp == null|| (_timestamp.trim().length() == 0))
        {
            _logger.debug("No value specified for: "
                    + ListenerTagNames.SQL_TIMESTAMP_TAG);
            _timestamp = null ;
        }
       
        _where = ListenerUtil.getValue(_config,
                ListenerTagNames.SQL_WHERE_CONDITION_TAG, "");
        if (_where.trim().length() < 1)
            _logger.debug("No value specified for: "
                    + ListenerTagNames.SQL_WHERE_CONDITION_TAG);
        _orderBy = ListenerUtil.getValue(_config,
                ListenerTagNames.SQL_ORDER_BY_TAG, "");
        if (_orderBy.trim().length() < 1)
            _logger.debug("No value specified for: "
                    + ListenerTagNames.SQL_ORDER_BY_TAG);
        _inProcessVals = ListenerUtil.getValue(_config,
                ListenerTagNames.SQL_IN_PROCESS_VALUES_TAG,
                DEFAULT_IN_PROCESS_STATES);

        _deleteAfterOK = Boolean.parseBoolean(ListenerUtil.getValue(_config,
                ListenerTagNames.SQL_POST_DEL_TAG, "false"));
        if (null == _config.getAttribute(ListenerTagNames.SQL_POST_DEL_TAG))
            _logger
                    .debug("No value specified for: "
                            + ListenerTagNames.SQL_POST_DEL_TAG
                            + " - trigger row will not be deleted - 'in process field' will be used to show processing status");

        if (_inProcessVals.length() < 4)
            throw new ConfigurationException("Parameter <"
                    + ListenerTagNames.SQL_IN_PROCESS_VALUES_TAG
                    + "> must be at least 4 characters long (PWED)");

        _columns = _selectFields.split(",");
        if (_columns.length < 1)
            throw new ConfigurationException("Empty list of select fields");

        _keys = _keyFields.split(",");
        if (!"*".equals(_selectFields)) {
            Set<String> colSet = new HashSet<String>(Arrays.asList(_columns));
            if (_keys.length < 1)
                throw new ConfigurationException("Empty list of keyFields");
            for (String currKey : _keys) {
                if (colSet.contains(currKey))
                    continue;
                else {
                    StringBuilder sb = new StringBuilder().append(
                            "All key field names in the <").append(
                            ListenerTagNames.SQL_KEY_FIELDS_TAG).append(
                            "> attribute must be in the ").append(
                            ListenerTagNames.SQL_SELECT_FIELDS_TAG).append(
                            "list - '").append(currKey)
                            .append("' is not there");
                    throw new ConfigurationException(sb.toString());
                }
            }
        }
       
        transacted = _config.getBooleanAttribute(ListenerTagNames.TRANSACTED_TAG, false);
        transactionStrategy = TransactionStrategy.getTransactionStrategy(transacted) ;
    } // ________________________________

    protected void prepareStatements() throws SQLException {
        _PSscan = _dbConn.prepareStatement(scanStatement());
        _PSupdate = _dbConn.prepareStatement(updateStatement());
        _PSdeleteRow = _dbConn.prepareStatement(deleteStatement());
    } // ________________________________

    /*
         * Throw ConfigurationException for anything to do with setup.
         * Ultimately could do with finer grained error handling. Probably need
         * different types of setup exceptions.
         */

    protected void resolveComposerClass() throws ConfigurationException {
        try {
            String sProcessMethod = null;
            _composerName = _config
                    .getAttribute(ListenerTagNames.GATEWAY_COMPOSER_CLASS_TAG);
            if (null != _composerName) { // class attribute
                _composerClass = ClassUtil.forName(_composerName, getClass());
                Constructor oConst = _composerClass.getConstructor(new Class[]
                        {ConfigTree.class});
                _composer = oConst.newInstance(_config);
                sProcessMethod = _config
                        .getAttribute(
                                ListenerTagNames.GATEWAY_COMPOSER_METHOD_TAG,
                                "process");
            } else {
                _composerName = PackageRowContents.class.getName();
                _composerClass = PackageRowContents.class;
                _composer = new PackageRowContents(PackageRowContents.createPayloadProxy(_config));
                sProcessMethod = "process";
                _logger
                        .debug("No <" + ListenerTagNames.ACTION_ELEMENT_TAG
                                + "> element found in configuration"
                                + " -  Using default composer class : "
                                + _composerName);
            }

            _processMethod = _composerClass.getMethod(sProcessMethod,
                    new Class[]
                            {Object.class});
        }
        catch (InvocationTargetException ex) {
            _logger.debug(ex);

            throw new ConfigurationException(ex);
        }
        catch (IllegalAccessException ex) {
            _logger.debug(ex);

            throw new ConfigurationException(ex);
        }
        catch (InstantiationException ex) {
            _logger.debug(ex);

            throw new ConfigurationException(ex);
        }
        catch (ClassNotFoundException ex) {
            _logger.debug(ex);

            throw new ConfigurationException(ex);
        }
        catch (NoSuchMethodException ex) {
            _logger.debug(ex);

            throw new ConfigurationException(ex);
        }
    } // ________________________________

    protected List<Map<String, Object>> pollForCandidates() {
        List<Map<String, Object>> oResults = new ArrayList<Map<String, Object>>();
        final JdbcCleanConn oConn = getDbConn();
       
        ResultSet RS = null;
       
        try {
            RS = oConn.execQueryWait(_PSscan, 1);
            ResultSetMetaData meta = RS.getMetaData();
            while (RS.next()) {
                Map<String, Object> row = new HashMap<String, Object>();
                for (int iCurr = 1; iCurr <= meta.getColumnCount(); iCurr++) {
                    String sCol = meta.getColumnName(iCurr);
                    if (!_inProcessField.equalsIgnoreCase(sCol)) {
                        final int type = meta.getColumnType(iCurr) ;
                        if (type == Types.BLOB) {
                            final Blob blob = RS.getBlob(iCurr) ;
                            row.put(sCol, ((blob != null) ? StreamUtils.readStreamString(blob.getBinaryStream(), "UTF-8") : null));
                        } else if (type == Types.CLOB) {
                            final Clob clob = RS.getClob(iCurr) ;
                            row.put(sCol, ((clob != null) ? StreamUtils.readReader(clob.getCharacterStream()) : null));
                        } else {
                            row.put(sCol, RS.getObject(iCurr));
                        }
                    }
                }

                oResults.add(row);
            }
        }
        catch (Exception e) {
            _logger.debug("Some triggers might not have been returned", e);
        }
        finally {
            try {
          if (RS != null)
              RS.close();
         
                oConn.rollback();
            } catch (final SQLException sqle) {
              refreshDatasource();
            }
        }
        if (_logger.isDebugEnabled()) {
            _logger.debug("Returning " + oResults.size() + " rows.\n");
        }
        return oResults;
    } // ________________________________

    public void refreshDatasource() {
      releaseDBConnection();     
      if (_datasource != null) {
        getDbConn();
      }
    }

  private void releaseDBConnection() {
    if(_dbConn != null) {
      try {
        _dbConn.release();
      } finally {
        _dbConn = null;
      }
      }
  }
   
    /**
     * Obtain a new database connection with parameter info
     *
     * @return A new connection
     * @throws ConfigurationException -
     *                                if problems are encountered
     */
    protected JdbcCleanConn getDbConn() {
      DataSource oDS = null;
        if (null == _dbConn) {
          if (_datasource == null) {
            oDS = new SimpleDataSource(_driver, _url, _user,
                    _password);
          } else {
        InitialContext initContext;
        try {
          initContext = new InitialContext();
          oDS = (DataSource) initContext.lookup(_datasource);
        } catch (NamingException e) {
          _logger.error("SqlTableGatewayListener.getDbConn failed to lookup datasource.", e);
        }
          }
         
          /*
           * Create JdbcCleanConn even if oDS is null because that will
           * manage the error handling for us by throwing SQLExceptions
           * at the appropriate time.
           */
         
          _dbConn = new JdbcCleanConn(oDS, transacted);
        }
     
        if ((null != _dbConn) && (_dbConn.getStatements().size() == 0)) {
          try {
        prepareStatements();       
      } catch (SQLException e) {
        releaseDBConnection();
        _logger.warn("Exception preparing statements", e);
      }
        }
         
        return _dbConn;
    } // ________________________________

    /**
     * Assemble the SQL statement to scan (poll) the table
     *
     * @return - The resulting SQL statement
     */
    protected String scanStatement() {
        StringBuilder sb = new StringBuilder().append("select ").append(
                _selectFields).append(" from ").append(_tableName);

        boolean bWhere = !Util.isNullString(_where);
        if (bWhere)
            sb.append(" where ").append(_where);
        sb.append((bWhere) ? " and " : " where ");

        String sLike = _inProcessVals.substring(0, 1).toUpperCase();
        sb.append(" upper(").append(_inProcessField).append(") like '").append(
                sLike).append("%'");

        if (!Util.isNullString(_orderBy))
            sb.append(" order by ").append(_orderBy);
        return sb.toString();
    } // ________________________________

    /**
     * Assemble the SQL statement to update the field in the
     * "inProcessField" parameter
     * <p/>
     * in the table row uniquely identified by the list of fields in the
     * "keyFields" parameter
     *
     * @return - The resulting SQL statement
     */
    protected String updateStatement() {
        StringBuilder sb = new StringBuilder().append("update ").append(
                _tableName).append(" set ").append(_inProcessField).append(" = ? ");
        if (_timestamp != null) {
          sb.append(", " + _timestamp + " = ? ");
        }
        sb.append("where ").append(_inProcessField).append(" = ?");
        for (String sCurr : _keys) {
            sb.append(" and ").append(sCurr).append(" = ?");
        }
        return sb.toString();
    } // ________________________________

    /**
     * Assemble the SQL statement to delete the current row in the table row
     * uniquely identified by the list of fields in the "keyFields"
     * parameter
     *
     * @return - The resulting SQL statement
     */
    protected String deleteStatement() {
        StringBuilder sb = new StringBuilder().append("delete from ").append(
                _tableName).append(" where ");
        int iCurr = 0;
        for (String sCurr : _keys) {
            if (iCurr++ > 0)
                sb.append(" and ");
            sb.append(sCurr).append(" = ?");
        }
        return sb.toString();
    } // ________________________________

    /**
     * Try to delete 'current row' from polled table
     *
     * @return true if row deletion was successful - false otherwise
     */
    protected boolean deleteCurrentRow() {
        try {
            int iParm = 1;
            for (String sColName : _keys) {
              final Object val ;
              if (_currentRow.containsKey(sColName)) {
                    val = _currentRow.get(sColName);
              } else {
                    val = _upperCurrentRow.get(sColName.toUpperCase());
              }
                _PSdeleteRow.setObject(iParm++, val);
            }

            try {
                getDbConn().execUpdWait(_PSdeleteRow, 5);
                getDbConn().commit();
                return true;
            }
            catch (Exception e) {
                _logger.debug("Delete row has failed.  Rolling back!!", e);
            }

            try {
                getDbConn().rollback();
            }
            catch (Exception e) {
                _logger.debug("Unable to rollback delete row", e);
            }
        }
        catch (Exception e) {
            _logger.debug("Unexpected exception.", e);
        }
        return false;
    } // ________________________________

    protected String getStatus(ROW_STATE p_oState) {
        int iPos = p_oState.ordinal();
        return _inProcessVals.substring(iPos, ++iPos);
    } // ________________________________

    protected boolean changeStatusToWorking() {
        return changeStatus(ROW_STATE.Pending, ROW_STATE.Working);
    } // ________________________________

    protected boolean changeStatusToDone() {
        return changeStatus(ROW_STATE.Working, ROW_STATE.Done);
    } // ________________________________

    protected boolean changeStatusToError() {
        return changeStatus(ROW_STATE.Working, ROW_STATE.Error);
    } // ________________________________

    protected boolean changeStatus(ROW_STATE fromState, ROW_STATE toState) {
        try {
            getDbConn();
        }
        catch (Exception e) {
            _logger.debug("Unable to get DB connection.", e);
            throw new IllegalStateException("Unable to get DB connection.", e);
        }

        try {
            int iParm = 3;
            if (_timestamp != null) {
              iParm++;
            }
           
            List<String> tempKeys = new ArrayList<String>();
            for (String key : _currentRow.keySet()) {
              tempKeys.add(key);
            }
            if (_upperCurrentRow != null) {
              _upperCurrentRow.clear();
            } else {
              _upperCurrentRow = new HashMap<String, Object>();
            }
           
            for (String key : tempKeys) {
              Object value = _currentRow.get(key);
              _upperCurrentRow.put(key.toUpperCase(), value);
            }
           
            for (String sColName : _keys) {
              Object oVal = null;
              if (_currentRow.containsKey(sColName)) {
                oVal = _currentRow.get(sColName);
              } else {
                oVal = _upperCurrentRow.get(sColName.toUpperCase());
              }
             
                _PSupdate.setObject(iParm++, oVal);
            }

            try {
              int counter = 1;
                _PSupdate.setString(counter++, getStatus(toState));
                if (_timestamp != null) {
                  Date now = new Date();
                  _PSupdate.setString(counter++, now.toString());
                }
                _PSupdate.setString(counter++, getStatus(fromState));
                final int count = getDbConn().execUpdWait(_PSupdate, 5);
                if (count == 1) {
                    getDbConn().commit();

                    if (_logger.isDebugEnabled())
                        _logger.debug("Successfully changed row state from "
                                + fromState + " to " + toState + ".");

                    return true;
                } else {
                    _logger.warn("Cannot change row state from " + fromState
                            + " to " + toState + ".  Number of rows in state "
                            + fromState + " = " + count);
                   
                    if (count == 0// the execute affected zero rows!
                    {
                        // https://jira.jboss.org/jira/browse/SOA-642
                       
                        _logger.warn("No rows affected by update statement. Check listener/gateway/notifier table definitions are correct.");
                    }
                    else
                        _logger.warn("Curent implementation expected only one row to be applicable to update request.");
                   
                    return false;
                }
            }
            catch (Exception e) {
                final String message = "Row status change to " + toState
                        + " has failed.  Rolling back!!";
                _logger.error(message);
                _logger.debug(message, e);
            }

            try {
                getDbConn().rollback();
            }
            catch (Exception e) {
                final String message = "Unable to rollback row status change to "
                        + fromState;
                _logger.error(message);
                _logger.debug(message, e);
            }
        }
        catch (Exception e) {
            final String message = "Unexpected exception.";
            _logger.error(message);
            _logger.debug(message, e);
        }

        return false;
    } // ________________________________

    /**
     * Default gateway action for SQL table rows <p/>It will just drop the
     * result set contents into a Message
     *
     * @author <a
     *         href="mailto:schifest@heuristica.com.ar">schifest@heuristica.com.ar</a>
     * @since Version 4.0
     */
    public static class PackageRowContents {
        private MessagePayloadProxy payloadProxy;

        public PackageRowContents(MessagePayloadProxy payloadProxy) {
            this.payloadProxy = payloadProxy;
        }

        public Message process(Object obj) throws MessageDeliverException {
            if (!(obj instanceof Serializable))
                throw new IllegalArgumentException(
                        "Object must be instance of Map");

            Message message = MessageFactory.getInstance().getMessage();
            org.jboss.soa.esb.message.Properties props = message
                    .getProperties();

            if(MessagePayloadProxy.isUsingLegacyPatterns()) {
                props.setProperty(ListenerTagNames.SQL_ROW_DATA_TAG, obj);
            } else {
                payloadProxy.setPayload(message, obj);
            }

            return message;
        }

        public static MessagePayloadProxy createPayloadProxy(ConfigTree config) {
            return  new MessagePayloadProxy(config);
        }
    } // ____________________________________________________

    protected final static Logger _logger = Logger
            .getLogger(SqlTableGatewayListener.class);

    protected ConfigTree _config;

    protected long _sleepBetweenPolls; // milliseconds

    protected String _targetServiceCategory, _targetServiceName;

    protected String _composerName;
    protected ServiceInvoker _serviceInvoker;

    protected Class _composerClass;

    protected Object _composer;

    protected Method _processMethod;

    protected String _driver, _url, _user, _password, _datasource;

    protected String _tableName, _selectFields, _keyFields, _timestamp;

    protected String _where, _orderBy;

    protected String _inProcessField, _inProcessVals;

    protected boolean _deleteAfterOK;

    protected String[] _columns, _keys;

    protected PreparedStatement _PSscan, _PSupdate, _PSdeleteRow;

    protected JdbcCleanConn _dbConn;

    protected Map<String, Object> _currentRow, _upperCurrentRow;

    public static enum ROW_STATE {
        Pending, Working, Error, Done
    }

    public static final String DEFAULT_IN_PROCESS_STATES = "PWED";
} // ____________________________________________________________________________
TOP

Related Classes of org.jboss.soa.esb.listeners.gateway.SqlTableGatewayListener

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.