Package org.jboss.soa.esb.services.jbpm.integration.command

Source Code of org.jboss.soa.esb.services.jbpm.integration.command.AbstractMessageListener

package org.jboss.soa.esb.services.jbpm.integration.command;

import java.io.Serializable;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.log4j.Logger;
import org.hibernate.StaleStateException;
import org.jboss.soa.esb.common.TransactionStrategy;
import org.jboss.soa.esb.common.TransactionStrategyException;
import org.jboss.soa.esb.services.jbpm.integration.msg.JmsMessageService;
import org.jboss.soa.esb.services.jbpm.integration.msg.JmsMessageServiceFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.command.Command;
import org.jbpm.persistence.JbpmPersistenceException;
import org.jbpm.persistence.db.DbPersistenceService;
import org.jbpm.svc.Services;
import org.jbpm.tx.TxService;

/**
* Based on the jBPM enterprise code, this abstract base class handles most of the
* processing required by job/command executors.
*
* @author <a href='kevin.conner@jboss.com'>Kevin Conner</a>
*/
abstract class AbstractMessageListener implements MessageListener
{
    /**
     * The logger for this class.
     */
    protected final Logger log = Logger.getLogger(getClass()) ;
   
    /**
     * Handle the delivery of a job message.
     * @param message the JMS message containing the job.
     */
    public void onMessage(final Message message)
    {
        if (log.isDebugEnabled())
        {
            log.debug("Processing message " + message) ;
        }
        try
        {
            final JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
            try
            {
                // extract command from message
                Command command = extractCommand(message);
                if (log.isDebugEnabled())
                {
                    log.debug("Extracted command " + command) ;
                }
                if (command == null)
                {
                    discard(jbpmContext, message);
                    return;
                }
                final Object result = command.execute(jbpmContext);
                // send a response back if a "reply to" destination is set
                final Destination replyTo = message.getJMSReplyTo();
                if (replyTo != null && (result instanceof Serializable || result == null))
                {
                    sendResult(jbpmContext, (Serializable)result, replyTo, message.getJMSMessageID());
                }
                if (log.isDebugEnabled())
                {
                    log.debug("Executed command " + command) ;
                }
                jbpmContext.getSession().flush() ;
            }
            finally
            {
                final TxService txService = jbpmContext.getServices().getTxService() ;
                final boolean exceptionExpected = txService.isRollbackOnly() ;
                try
                {
                    jbpmContext.close() ;
                }
                catch (final JbpmException je)
                {
                    if (exceptionExpected)
                    {
                        rollback(je) ;
                    }
                    else
                    {
                        throw je ;
                    }
                }
            }
        }
        catch (final StaleStateException sse)
        {
            if (log.isDebugEnabled())
            {
                log.debug("Stale state raised, rolling back transaction") ;
            }
            rollback(sse) ;
        }
        catch (final JbpmPersistenceException jpe)
        {
            if (!DbPersistenceService.isLockingException(jpe))
            {
                throw jpe ;
            }
            if (log.isDebugEnabled())
            {
                log.debug("Stale state raised, rolling back transaction") ;
            }
            rollback(jpe) ;
        }
        catch (final JbpmException je)
        {
            throw je ;
        }
        catch (final Exception ex)
        {
            throw new JbpmException("could not process message " + message, ex);
        }
    }

    /**
     * Extract a jBPM command from the message.
     * @param message The JMS message.
     * @return The jBPM command.
     * @throws JMSException for errors during extraction.
     */
    protected abstract Command extractCommand(Message message)
        throws JMSException ;

    /**
     * Discard the message by sending to a specified DLQ.
     * @param jbpmContext The current jBPM context.
     * @param message The message to discard.
     * @throws JMSException For errors during JMS delivery.
     */
    private void discard(final JbpmContext jbpmContext, final Message message)
        throws JMSException
    {
        final Services services = jbpmContext.getServices();
        final JmsMessageServiceFactory messageServiceFactory = (JmsMessageServiceFactory) services.getServiceFactory(Services.SERVICENAME_MESSAGE);
        final Destination destination = messageServiceFactory.getDLQDestination();

        final JmsMessageService messageService = (JmsMessageService)services.getMessageService();
        final Session session = messageService.getSession();
        final MessageProducer producer = session.createProducer(destination);
        try {
          producer.send(message);
        }
        finally {
          producer.close();
        }
    }

    /**
     * Send a result to a specified destination.
     * @param jbpmContext The current jBPM context.
     * @param result The serializable result.
     * @param destination The destination for the message.
     * @param correlationId The associated correlation ID.
     * @throws JMSException For errors during JMS delivery.
     */
    private void sendResult(final JbpmContext jbpmContext, final Serializable result, final Destination destination, final String correlationId)
        throws JMSException
    {
        if (log.isDebugEnabled())
        {
            log.debug("sending result " + result + " to " + destination);
        }
        final Services services = jbpmContext.getServices();

        final JmsMessageService messageService = (JmsMessageService) services.getMessageService();
        final Session session = messageService.getSession();
        final MessageProducer producer = session.createProducer(destination);
        try
        {
          Message resultMessage = session.createObjectMessage(result);
          resultMessage.setJMSCorrelationID(correlationId);
          producer.send(resultMessage);
        } finally {
          producer.close();
        }
    }
   
    /**
     * Rollback the encompassing JTA transaction.
     * @param re The original exception prompting the rollback, thrown should rollback fail.
     */
    private void rollback(final RuntimeException re)
    {
        try
        {
            TransactionStrategy.getTransactionStrategy(true).rollbackOnly() ;
        }
        catch (final TransactionStrategyException tse)
        {
            if (log.isDebugEnabled())
            {
                log.debug("Failed to rollback transaction, throwing original", tse) ;
            }
            throw re ;
        }
    }
}
TOP

Related Classes of org.jboss.soa.esb.services.jbpm.integration.command.AbstractMessageListener

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.