Package de.danet.an.workflow.ejbs.client

Source Code of de.danet.an.workflow.ejbs.client.ApplInvokerEJB

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* 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
*
* $Id: ApplInvokerEJB.java 3205 2009-09-27 17:13:47Z mlipp $
*
* $Log$
* Revision 1.14  2007/05/03 21:58:25  mlipp
* Internal refactoring for making better use of local EJBs.
*
*/
package de.danet.an.workflow.ejbs.client;

import java.util.HashMap;
import java.util.Map;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

import de.danet.an.util.EJBUtil;
import de.danet.an.util.logging.RequestLog;
import de.danet.an.util.logging.RequestScope;

import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.ActivityUniqueKey;
import de.danet.an.workflow.api.DefaultProcessData;
import de.danet.an.workflow.api.WorkflowService;
import de.danet.an.workflow.api.WorkflowServiceFactory;

import de.danet.an.workflow.apix.ExtActivity;
import de.danet.an.workflow.ejbs.WorkflowEngine;
import de.danet.an.workflow.ejbs.core.ActivityProxy;
import de.danet.an.workflow.internalapi.ExtApplication;
import de.danet.an.workflow.internalapi.ToolInvocationException;
import de.danet.an.workflow.spis.aii.CannotExecuteException;
import de.danet.an.workflow.spis.aii.ResultProvider.ExceptionResult;

/**
* This class provides the message driven bean that handles tool
* invocations.<P>
* The following diagram provides an overview of the invocation.<br></br>
* <img src="doc-files/ApplicationInvocation.gif"/>
*
* Setting log level to <code>DEBUG</code> will additionally output
* the stack traces for the issued warning messages.
*
* @author <a href="mailto:lipp@danet.de">Michael N. Lipp</a>
* @version $Revision: 3205 $
*
* @ejb.bean name="ApplicationInvoker"
* transaction-type="Container" destination-type="javax.jms.Queue"
* message-selector="FALSE"
* @jonas.bean ejb-name="ApplicationInvoker"
* @ejb.security-identity run-as="WfMOpenAdmin"
* @weblogic.run-as-identity-principal WfMOpenPrincipalForAdmin
* @ejb.transaction type="Required"
* @ejb.permission role-name="WfMOpenAdmin"
* @jboss.destination-jndi-name
* name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
* @jonas.message-driven-destination
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
* @weblogic.enable-call-by-reference True
* @weblogic.message-driven
* destination-jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
* @jboss.container-configuration name="Standard Message Driven Bean"
* @ejb.ejb-ref ejb-name="InvocationHelper" view-type="local"
*/
public class ApplInvokerEJB implements MessageDrivenBean, MessageListener {

    private static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory.getLog (ApplInvokerEJB.class);
   
    private MessageDrivenContext ctx;
    private InvocationHelperLocal invocationHelperCache = null;

    /**
     * The invocation helper must be created lazily as we need permissions that
     * we have in onMessage only.
     */
    private InvocationHelperLocal invocationHelper() {
        if (invocationHelperCache == null) {
            try {
                invocationHelperCache = (InvocationHelperLocal)
                    EJBUtil.createSession
                        (InvocationHelperLocalHome.class,
                         "java:comp/env/ejb/InvocationHelper");
            } catch (RemoteException e) {
                throw new EJBException (e);
            }
        }
        return invocationHelperCache;
    }
   
    /**
     * Called by container to set context.
     * @param context the context.
     */
    public void setMessageDrivenContext(MessageDrivenContext context) {
  ctx = context;
    }

    /**
     * Called by container to create EJB.
     */
    public void ejbCreate() {
    }

    /**
     * Called by container to remove EJB.
     */
    public void ejbRemove() {
  // TODO: unsure if this is a JBoss bug, but ejbRemove is
  // called without a principal although run-as has been
  // specified.
  logger.debug ("Removed.");
    }
 
    /**
     * Called by container when a new message is to be processed.
     * @param message the message.
     */
    public void onMessage(Message message) {
        RequestScope scope = RequestLog.enterScope
            (this, "onMessage", new Object[] { message });
  try {
      if (logger.isDebugEnabled() && message.getJMSRedelivered()) {
    String msgId = "(unkown)";
    try {
        msgId = message.getJMSMessageID();
    } catch (JMSException ee) {
        logger.debug
      ("Cannot obtain message id: " + ee.getMessage ());
    }
    logger.debug ("Handling redelivered message " + msgId);
      }
      Map args = new HashMap((Map)((ObjectMessage)message).getObject());
            Activity act = ActivityProxy.wrap
                ((ActivityUniqueKey)args.get("activityUniqueKey"));
      args.put ("activity", act);
      args.remove("activityUniqueKey");
      ExtApplication appl = (ExtApplication)args.get("appl");
      Map params = (Map)args.get("params");
      doInvoke (null, invocationHelper(), act, appl, params, true);
  } catch (RemoteException e) {
      // a RemoteException should be a temporary condition,
      // i.e. message may be redelivered.
      String msgId = "(unkown)";
      try {
    msgId = message.getJMSMessageID();
      } catch (JMSException ee) {
    logger.debug ("Cannot obtain message id: " + ee.getMessage ());
      }
      logger.debug
    ("Temporary problem invoking application for message "
     + msgId + " (retrying): " + e.getMessage (), e);
            // WLS seems to have problems with invoking setRollbackOnly twice
            if (!ctx.getRollbackOnly()) {
                ctx.setRollbackOnly();
            }
  } catch (Throwable t) {
      // avoid redelivery of message.
      logger.error (t.getMessage(), t);
  } finally {
      scope.leave();
 
    }

    /**
     * Execute a tool invocation using the map retrieved from the
     * queue. Is also called from {@link EventHandlerEJB
     * <code>EventHandlerEJB</code>}.
     * @param wfe the workflow engine
     * @param act the activity
     * @param appl the application
     * @param params the invocation arguments
     * @param useNew if <code>true</code> new transactions are used to
     * set the activity result
     * @throws RemoteException if a system-level error occurs.
     */
    public static void doInvoke
  (WorkflowEngine wfe, InvocationHelperLocal invHlp, Activity act,
   ExtApplication appl, Map params, boolean useNew)
  throws RemoteException {
  ExtApplication.InvocationResult res = null;
  RequestScope scope = RequestLog.enterScope
      (ApplInvokerEJB.class, "doInvoke",
       new Object[] { wfe,invHlp,act,appl,params,new Boolean(useNew) });
  if (RequestLog.isEnabled()) {
      scope.logMessage
          ("Invoking " + appl.toString() + "from " + act.toString()
           + " with parameters " + params.toString());
  }
  try {
      // Invoke in separate transaction. Else all exceptions
      // thrown by EJB methods invoked from the application
      // cause a roll back of this transaction and no
      // ToolInvocationFailedAuditEvent will be recorded and
      // the invocation will be repeated (maybe endlessly)
      res = invHlp.doInvoke(wfe, appl, act, params);
      if (res != null) {
          Object resVal = res.result();
          if (useNew) {
        while (true) {
      try {
          if (resVal instanceof ExceptionResult) {
        invHlp.doAbandon
            (wfe, act, (ExceptionResult)resVal);
        break;
          }
          invHlp.doFinish (wfe, act, (Map)resVal);
          break;
                        } catch (EJBException e) {
                            // Probably deadlock
                            logger.warn ("Error while finishing, repeating: "
                                         + e.getMessage());
      }
        }
    } else {
        if (resVal instanceof ExceptionResult) {
      ((ExtActivity)act).abandon((ExceptionResult)resVal);
        } else {
            if (act instanceof ActivityProxy) {
                Activity aun = ((ActivityProxy)act).unwrap();
                aun.setResult(new DefaultProcessData ((Map)resVal));
                aun.complete ();
            }
        }
    }
      }
           if (RequestLog.isEnabled()) {
               scope.logMessage
                   ("Result is: " + (res == null ? "null" : res.toString()));
           }
        } catch (RemoteException e) {
            // Indicates that the invocation should be retried,
            // simply re-throw.
            logger.warn (appl + " has requested re-invocation: "
                         + e.getMessage());
            logger.debug ("Stack trace:", e);
            throw e;
        } catch (EJBException e) {
            // Indicates that the invocation should be retried,
            // simply re-throw.
            logger.warn (appl + " has requested re-invocation: "
                         + e.getMessage());
            logger.debug ("Stack trace:", e);
            throw (RemoteException)
                (new RemoteException (e.getMessage(), e));
  } catch (Throwable e) {
      if ((e instanceof ToolInvocationException)
          && e.getCause() != null
          && (e.getCause() instanceof CannotExecuteException)) {
          Throwable t = e.getCause();
          if (t.getCause() != null) {
              t = t.getCause();
          }
          logger.warn(appl + " reports " + t.getClass().getName()
                + " during invocation (" + act + " will be terminated): "
                + t.getMessage(), t);
      } else {
          logger.error
          ("Problem invoking " + appl
                  + " (" + act + " will be terminated): "
                  + e.getClass().getName() + ": " + e.getMessage(), e);
      }
      invHlp.handleToolInvocationFailed(wfe, act.uniqueKey());
      return;
  } finally {
      scope.leave();
  }
    }
}
TOP

Related Classes of de.danet.an.workflow.ejbs.client.ApplInvokerEJB

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.