/*
* 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: InvocationHelperEJB.java 2992 2009-03-12 14:19:12Z drmlipp $
*
* $Log$
* Revision 1.8 2007/01/18 09:57:15 drmlipp
* Fixed problem with J2EE 1.4 allowing only one session per JMS connection.
*
* Revision 1.7 2006/10/11 09:05:54 drmlipp
* Fixed EJB naming.
*
* Revision 1.6 2006/10/10 09:23:58 drmlipp
* Made queue and topic names "generic".
*
* Revision 1.5 2006/09/29 12:32:12 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.4 2005/04/08 11:28:05 drmlipp
* Merged changes from 1.3 branch up to 1.3p6.
*
* Revision 1.3.2.2 2005/04/07 15:54:23 drmlipp
* Fixed problem with process not being started. Removed fix that handled
* special case of subprocess only.
*
* Revision 1.3.2.1 2005/04/04 20:09:20 drmlipp
* Changed WLS transaction isolation.
*
* Revision 1.3 2005/01/07 14:58:59 drmlipp
* Made Queuer EJB a local EJB. Not expecting significant performance
* gains from this ;-), but it is somehow makes sense.
*
* Revision 1.2 2004/09/10 12:44:30 drmlipp
* Enabled call by reference for weblogic by default.
*
* Revision 1.1.1.3 2004/08/18 15:17:38 drmlipp
* Update to 1.2
*
* Revision 1.15 2004/07/04 17:36:03 lipp
* Added JOnAS support.
*
* Revision 1.14 2004/07/02 15:10:24 lipp
* Workaround for JBoss 3.2.3/3.2.5 incompatibility.
*
* Revision 1.13 2004/07/02 13:43:37 lipp
* Fixed JMS usage.
*
* Revision 1.12 2004/02/13 08:25:29 lipp
* Changed channel message data type to Map which is more appropriate.
*
* Revision 1.11 2004/02/06 13:37:35 lipp
* Added channel close notification.
*
* Revision 1.10 2004/02/06 10:25:46 lipp
* Finshed Receiver.
*
* Revision 1.9 2004/01/14 07:59:45 lipp
* Added transaction isolation attribute for WLS.
*
* Revision 1.8 2003/11/21 14:56:21 lipp
* Adapted wls queue names.
*
* Revision 1.7 2003/11/20 14:40:36 lipp
* Using JmsXA now.
*
* Revision 1.6 2003/11/14 10:42:51 lipp
* Using WLS default connection factory name.
*
* Revision 1.5 2003/11/06 16:30:00 lipp
* Using proper JMS connection factory now.
*
* Revision 1.4 2003/11/04 10:08:22 lipp
* Removed queuing optimization.
*
* Revision 1.3 2003/11/03 16:32:52 lipp
* Fixed event saving.
*
* Revision 1.2 2003/10/25 22:20:46 lipp
* Using in JVM connection factory whereever possible.
*
* Revision 1.1 2003/10/25 20:59:32 lipp
* Made AuditEventQueuer the general queuer.
*
* Revision 1.1 2003/10/24 11:08:49 lipp
* Made AuditEventQueuer an EJB.
*
*/
package de.danet.an.workflow.ejbs.client;
import java.util.Map;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.ActivityUniqueKey;
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.internalapi.ExtApplication;
import de.danet.an.workflow.internalapi.ToolInvocationException;
import de.danet.an.workflow.internalapi.ExtApplication.InvocationResult;
import de.danet.an.workflow.omgcore.CannotCompleteException;
import de.danet.an.workflow.omgcore.InvalidDataException;
import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
import de.danet.an.workflow.omgcore.WfActivity;
import de.danet.an.workflow.spis.aii.ToolAgentContext;
import de.danet.an.workflow.spis.aii.ResultProvider.ExceptionResult;
/**
* This class provides a method for running a tool agent invocation
* in its own transaction.
*
* @author <a href="mailto:lipp@danet.de">Michael Lipp</a>
* @ejb.bean name="InvocationHelper" display-name="Invocation Helper EJB"
* jndi-name="ejb/@@@_JNDI_Callback_Name_Prefix_@@@InvocationHelper"
* local-jndi-name="ejb/@@@_JNDI_Callback_Name_Prefix_@@@InvocationHelperLocal"
* type="Stateless" transaction-type="Container" view-type="local"
* @jonas.bean ejb-name="InvocationHelper"
* @ejb.transaction type="Required"
* @weblogic.enable-call-by-reference True
* @ejb.permission role-name="WfMOpenAdmin"
* @ejb.resource-ref res-ref-name="toolagents/mailtool/Mail"
* res-type="javax.mail.Session" res-auth="Container"
* @jonas.resource res-ref-name="toolagents/mailtool/Mail" jndi-name="WfMOpenMail"
* @weblogic.resource-description res-ref-name="toolagents/mailtool/Mail"
* jndi-name="WfMOpenMail"
*/
public class InvocationHelperEJB implements SessionBean {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory
.getLog(InvocationHelperEJB.class);
/** The SessionContext interface of the instance. */
private SessionContext ctx;
private WorkflowEngine engineCache;
/**
* Set the associated session context. The container calls this method
* after the instance creation.
* @see javax.ejb.SessionBean
* @param context a SessionContext interface for the instance
*/
public void setSessionContext(SessionContext context) {
ctx = context;
}
/**
* Create an new instance of the EJB.
* @throws CreateException if the EJB can not be create.
* @ejb.create-method view-type="local"
*/
public void ejbCreate () throws CreateException {
logger.debug ("Created.");
}
/**
* The activate method is called when the instance is activated from its
* "passive" state. The instance should acquire any resource that it has
* released earlier in the ejbPassivate() method.
* @see javax.ejb.SessionBean
*/
public void ejbActivate() {
// nothing to do
}
/**
* The passivate method is called before the instance enters the
* "passive" state. The instance should release any resources that it
* can re-acquire later in the ejbActivate() method.
* @see javax.ejb.SessionBean
*/
public void ejbPassivate() {
// nothing to do
}
private WorkflowEngine engine (WorkflowEngine toTest) {
if (toTest != null) {
return toTest;
}
if (engineCache == null) {
engineCache = ((StandardWorkflowService)WorkflowServiceFactory
.newInstance().newWorkflowService()).engine();
}
return engineCache;
}
/**
* A container invokes this method before it ends the life of the session
* object. This happens as a result of a client's invoking a remove
* operation, or when a container decides to terminate the session object
* after a timeout.
* @see javax.ejb.SessionBean
*/
public void ejbRemove() {
logger.debug ("Removed.");
}
/**
* Invoke a tool in a new transaction, i.e. the transaction
* attribute of this method is set to <code>RequiresNew</code>.<P>
*
* The implementation simply calls <code>appl.invoke(act,
* params)</code>.
*
* @param engine the workflow engine for callbacks during invocation
* @param appl the application description of the tool
* @param act the <code>WfActivity</code>
* @param params the invocation parameters
* @return the invocation result
* @throws ToolInvocationException if execution is not possible
* @ejb.interface-method view-type="local"
* @ejb.transaction type="RequiresNew"
*/
public InvocationResult doInvoke
(WorkflowEngine engine, ExtApplication appl, Activity act, Map params)
throws ToolInvocationException {
engine = engine(engine);
try {
ToolAgentContext tac
= new DefaultToolAgentContext (engine, act, appl.id());
return appl.invoke(tac, act, params);
} catch (NoSuchObjectException e) {
logger.warn
("NoSuchObjectException invoking " + appl + " on " + act
+ " (mapped to ToolInvocationException): " + e.getMessage(),e);
throw new ToolInvocationException (appl + ": " + e.getMessage());
} catch (RemoteException e) {
throw new EJBException (e);
} catch (EJBException e) {
// Handled like RemoteException
throw e;
} catch (RuntimeException e) {
logger.warn
("RuntimeException invoking " + appl + " on " + act
+ "(mapped to ToolInvocationException): " + e.getMessage(), e);
// WLS seems to have problems with invoking setRollbackOnly twice
if (!ctx.getRollbackOnly()) {
ctx.setRollbackOnly();
}
throw new ToolInvocationException (appl + ": " + e.getMessage());
}
}
/**
* Set a result and complete an activity in a new transaction,
* i.e. the transaction attribute of this method is set to
* <code>RequiresNew</code>.<P>
*
* @param engine the workflow engine for callbacks during invocation
* @param act the <code>WfActivity</code>
* @param result the tool's result data. If <code>null</code> do
* not call <code>setResult</code>.
* @throws InvalidDataException see {@link
* de.danet.an.workflow.omgcore.WfActivity#setResult
* <code>WfActivity.setResult(...)</code>}
* @throws CannotCompleteException see {@link
* de.danet.an.workflow.omgcore.WfActivity#complete
* <code>WfActivity.complete()</code>}
* @ejb.interface-method view-type="local"
* @ejb.transaction type="Required"
*/
public void doFinish (WorkflowEngine engine, WfActivity act, Map result)
throws InvalidDataException, CannotCompleteException {
engine = engine(engine);
try {
engine.doFinish(act, result);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
/**
* Abandon an activity in a new transaction,
* i.e. the transaction attribute of this method is set to
* <code>RequiresNew</code>.<P>
*
* @param engine the workflow engine for callbacks during invocation
* @param act the <code>WfActivity</code>
* @param result the exception result to signal
* @throws TransitionNotAllowedException see {@link
* de.danet.an.workflow.api.Activity#abandon(String)
* <code>Activity.abandon()</code>}
* @ejb.interface-method view-type="local"
* @ejb.transaction type="Required"
*/
public void doAbandon
(WorkflowEngine engine, Activity act, ExceptionResult result)
throws TransitionNotAllowedException {
engine = engine(engine);
try {
engine.doAbandon((ExtActivity)act, result);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
/**
* Register the failure of a tool invocation.<P>
*
* @param act the <code>ActivityUniqueKey</code>
* @ejb.interface-method view-type="local"
* @ejb.transaction type="Required"
*/
public void handleToolInvocationFailed
(WorkflowEngine engine, ActivityUniqueKey act) {
try {
engine(engine).handleToolInvocationFailed(act);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
}