/*
* 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: WfActivityEJB.java 3205 2009-09-27 17:13:47Z mlipp $
*
* $Log$
* Revision 1.23 2007/09/21 06:19:35 mlipp
* Fixed problem with NamingException during process deletion.
*
* Revision 1.22 2007/07/08 20:35:01 mlipp
* Even more usage of local EJB interfaces.
*
* Revision 1.21 2007/06/10 05:55:30 drmlipp
* Using local interface for optimization.
*
* Revision 1.20 2007/05/03 21:58:16 mlipp
* Internal refactoring for making better use of local EJBs.
*
*/
package de.danet.an.workflow.ejbs.core;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.NoSuchEntityException;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.naming.NamingException;
import javax.sql.DataSource;
import de.danet.an.util.EJBUtil;
import de.danet.an.util.JDBCUtil;
import de.danet.an.util.ResourceNotAvailableException;
import de.danet.an.util.UniversalPrepStmt;
import de.danet.an.workflow.internalapi.ExtActivityLocal;
import de.danet.an.workflow.internalapi.ExtExecutionObjectLocal;
import de.danet.an.workflow.internalapi.ExtProcessLocal;
import de.danet.an.workflow.internalapi.ThreadInfo;
import de.danet.an.workflow.localapi.ProcessLocal;
import de.danet.an.workflow.localapi.TransitionLocal;
import de.danet.an.workflow.localcoreapi.WfActivityLocal;
import de.danet.an.workflow.localcoreapi.WfProcessLocal;
import de.danet.an.workflow.omgcore.HistoryNotAvailableException;
import de.danet.an.workflow.omgcore.InvalidPriorityException;
import de.danet.an.workflow.omgcore.InvalidStateException;
import de.danet.an.workflow.omgcore.WfAssignment;
import de.danet.an.workflow.omgcore.WfAuditEvent;
import de.danet.an.workflow.omgcore.WfProcess;
import de.danet.an.workflow.omgcore.WfExecutionObject.NotRunningState;
import de.danet.an.workflow.omgcore.WfExecutionObject.State;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.Activity.Implementation;
import de.danet.an.workflow.api.Activity.JoinAndSplitMode;
import de.danet.an.workflow.api.Activity.StartFinishMode;
import de.danet.an.workflow.apix.ExtActivity;
import de.danet.an.workflow.domain.AbstractActivity;
import de.danet.an.workflow.domain.DefaultAuditEvent;
import de.danet.an.workflow.domain.RASInvocationHandler;
import de.danet.an.workflow.domain.ToolInvocationHandler;
import de.danet.an.workflow.ejbs.WorkflowEngine;
import de.danet.an.workflow.ejbs.WorkflowEngineHome;
import de.danet.an.workflow.ejbs.admin.WorkflowEngineLocal;
import de.danet.an.workflow.ejbs.admin.WorkflowEngineLocalHome;
import de.danet.an.workflow.ejbs.client.InvocationHelperLocal;
import de.danet.an.workflow.ejbs.client.InvocationHelperLocalHome;
import de.danet.an.workflow.ejbs.util.QueuerUtils;
import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
import de.danet.an.workflow.spis.ras.ActivityFinder;
import de.danet.an.workflow.spis.ras.ResourceAssignmentService;
/**
* The entity bean <code>WfActivityEJB</code> represent a activity.
* <code>AbstractActivity</code> represents a simple implementation
* of the interface {@link ActivityLocal <code>Activity</code>}.
* It has the following additional features:
* <ul>
* <li>Support for transition restrictions of type SPLIT or JOIN.</li>
* </ul>
*
* @ejb.bean name="ActivityBean" display-name="ActivityBean"
* jndi-name="ejb/@@@_JNDI_Name_Prefix_@@@ActivityBean"
* type="BMP" reentrant="true" view-type="both"
* @jonas.bean ejb-name="ActivityBean"
* @ejb.pk class="java.lang.Long" generate="false"
* @ejb.home remote-class="de.danet.an.workflow.ejbs.core.WfActivityHome"
* local-class="de.danet.an.workflow.ejbs.core.WfActivityLocalHome"
* @ejb.interface
* extends="javax.ejb.EJBObject, de.danet.an.workflow.apix.ExtActivity"
* remote-class="de.danet.an.workflow.ejbs.core.WfActivity"
* local-extends="javax.ejb.EJBLocalObject,
* de.danet.an.workflow.internalapi.ExtActivityLocal"
* local-class="de.danet.an.workflow.ejbs.core.WfActivityLocal"
* @ejb.transaction type="Required"
* @ejb.security-identity run-as="WfMOpenAdmin"
* sunone-principal="WfMCorePrincipalForAdmin"
* @weblogic.run-as-identity-principal WfMCorePrincipalForAdmin
* @ejb.ejb-ref ejb-name="WorkflowEngine" view-type="remote"
* @ejb.ejb-ref ejb-name="WorkflowEngine" view-type="local"
* @ejb.ejb-ref ejb-name="ProcessBean" view-type="remote"
* @ejb.ejb-ref ejb-name="ProcessBean" view-type="local"
* @ejb.ejb-ref ejb-name="ConfigurationBean" view-type="remote"
* ref-name="ejb/Configuration"
* @ejb.ejb-external-ref ref-name="ejb/InvocationHelperLocal"
* link="InvocationHelper" type="Session" view-type="local"
* home="de.danet.an.workflow.ejbs.client.InvocationHelperLocalHome"
* business="de.danet.an.workflow.ejbs.client.InvocationHelperLocal"
* @ejb.ejb-external-ref ref-name="ejb/JdbcKeyGenLocal" link="KeyGen"
* type="Session" view-type="local" home="de.danet.an.util.KeyGenLocalHome"
* business="de.danet.an.util.KeyGenLocal"
* @ejb.resource-ref res-ref-name="jdbc/WfEngine"
* res-type="javax.sql.DataSource" res-auth="Container"
* @jonas.resource res-ref-name="jdbc/WfEngine" jndi-name="jdbc_1"
* @weblogic.enable-call-by-reference True
* @weblogic.resource-description
* res-ref-name="jdbc/WfEngine" jndi-name="DefaultDS"
* @ejb.permission role-name="WfMOpenAdmin"
* @weblogic.transaction-isolation TRANSACTION_READ_COMMITTED
* @weblogic.cache concurrency-strategy="Exclusive"
* @ejb.resource-ref res-ref-name="jms/QCF"
* res-type="javax.jms.QueueConnectionFactory" res-auth="Container"
* @jboss.resource-ref res-ref-name="jms/QCF" jndi-name="java:/JmsXA"
* @jonas.resource res-ref-name="jms/QCF" jndi-name="QCF"
* @weblogic.resource-description res-ref-name="jms/QCF"
* jndi-name="weblogic.jms.XAConnectionFactory"
* @ejb.resource-ref res-ref-name="jms/InternalEventQueue"
* res-type="javax.jms.Queue" res-auth="Container"
* @jboss.resource-ref res-ref-name="jms/InternalEventQueue"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @jonas.resource res-ref-name="jms/InternalEventQueue"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @weblogic.resource-description res-ref-name="jms/InternalEventQueue"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @ejb.resource-ref res-ref-name="jms/ApplicationInvocations"
* res-type="javax.jms.Queue" res-auth="Container"
* @jboss.resource-ref res-ref-name="jms/ApplicationInvocations"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
* @jonas.resource res-ref-name="jms/ApplicationInvocations"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
* @weblogic.resource-description res-ref-name="jms/ApplicationInvocations"
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations"
*/
public class WfActivityEJB extends AbstractActivity
implements EntityBean, TimedObject {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(WfActivityEJB.class);
private EntityContext ctx;
/** The primary key of the process. */
private Long processPk = null;
/** The name of the process. */
private String processName = null;
/** The manager of the process. */
private String processMgr = null;
/** The version of the process (manager). */
private String processMgrVers = null;
/**
* The data source of the database.
* @see javax.sql.DataSource
*/
private DataSource ds = null;
/** Indicates if the database supports select for update. */
private Boolean haveSelForUp = null;
/** Database name. */
private static final String DB_NAME = "java:comp/env/jdbc/WfEngine";
/** The cached home interface of WfProcess. */
private WfProcessHome processHomeCache = null;
private WfProcessLocalHome processLocalHomeCache = null;
/** Cache for QueueConnectionFactory. */
private QueueConnectionFactory qcfCache = null;
/** Cache for event queue. */
private Queue eventQueueCache = null;
/** Cache for application invocation queue. */
private Queue aiQueueCache = null;
/** The owning process of this activity. */
private WfProcess containerCache = null;
private WfProcessLocal containerLocalCache = null;
/**
* The list of activities that may follow this activity,
* i.e. to which transitions exist.
*/
private List nextActivitiesCache = null;
/**
* The activity finder used in {@link #activityFinderAndKey
* <code>activityFinderAndKey</code>}.
*/
private ActivityFinder activityFinderCache = null;
/** The resource assignment service. */
private RASInvocationHandler rasCache = null;
/** The workflow engine. */
private WorkflowEngine engineCache = null;
private WorkflowEngineLocal engineLocalCache = null;
private ToolInvocationHandler toolInvocationHandlerCache = null;
private InvocationHelperLocal invocationHelperCache = null;
/** This, as delivered to a client. */
private Activity thisRemoteCache = null;
//
// Provide the persistent attributes
//
/** Indicates change of a persistent attribute. */
private boolean persistentAttributeModified = false;
/** Indicates change of a slowly changing persistent attribute. */
private boolean slowlyChangingPaModified = false;
/** Indicates change of thread info persistent attribute. */
private boolean threadInfoModified = false;
/** Indicates change of exec info attributes. */
private boolean execTimesModified = false;
/** Indicates change of deadline attribute. */
private boolean deadlinesModified = false;
/** Indicates change of waiting on attribute. */
private boolean waitingOnModified = false;
/** Persistent attribute <code>name</code>. */
private String paName;
/** Persistent attribute <code>description</code>. */
private String paDescription;
/** Persistent attribute <code>priority</code>. */
private Priority paPriority;
/** Persistent attribute <code>typedState</code>. */
private State paTypedState;
/** Persistent attribute <code>lastStateTime</code>. */
private Date paLastStateTime;
/** Persistent attribute <code>startMode</code>. */
private StartFinishMode paStartMode;
/** Persistent attribute <code>finishMode</code>. */
private StartFinishMode paFinishMode;
/** Persistent attribute <code>joinMode</code>. */
private JoinAndSplitMode paJoinMode;
/** Persistent attribute <code>splitMode</code>. */
private JoinAndSplitMode paSplitMode;
/** Persistent attribute <code>performer</code>. */
private String paPerformer;
/** Persistent attribute <code>executor</code>. */
private Integer paExecStat;
/** Persistent attribute <code>actImpl</code>. */
private Implementation[] paActImpl;
/** Persistent attribute <code>threadInfo</code>. */
private ThreadInfo paThreadInfo;
/** Persistent attribute <code>Subflow</code>. */
private String paSubflow;
/** Persistent attribute <code>deadlines</code>. */
private List paDeadlines = null;
/** Persistent attribute <code>startTime</code>. */
private Date paStartTime;
/** Persistent attribute <code>suspendStart</code>. */
private Date paSuspendStart;
/** Persistent attribute <code>suspendAccum</code>. */
private long paSuspendAccum;
/** Persistent attribute <code>pendingException</code>. */
private String paPendingException;
/** Persistent attribute <code>waitOnProc</code>. */
private Long paWaitOnProc;
/** Persistent attribute <code>waitOnChan</code>. */
private String paWaitOnChan;
/**
* Persistent attribute <code>flags</code>. This attribute is not
* exposed, it serves as space efficient storage for various
* attributes that are exposed.
*/
private int paFlags;
private static final int FLAGS_DEBUG = 1;
private static final int FLAGS_AUDIT_SELECTION_SHIFT = 1;
private static final int FLAGS_AUDIT_SELECTION_MASK = 7 << 1;
private static final int FLAGS_STORE_AUDIT_EVENTS = 16;
private static final int FLAGS_SUB_STATE_SHIFT = 28;
private static final int FLAGS_SUB_STATE_MASK
= 0x7 << FLAGS_SUB_STATE_SHIFT;
private static final int FLAGS_DEFERRED_CHOICE = 1 << 27;
private static final int FLAGS_PRELIMINARILY_CHOSEN = 1 << 26;
private static final int FLAGS_NO_ASSIGNMENTS = 1 << 25;
private static final int FLAGS_PENDING_EXCEPTION_IS_FROM_BLOCK = 1 <<24;
//
// Accessor methods for cached attributes
//
private QueueConnectionFactory queueConnectionFactory ()
throws ResourceNotAvailableException {
if (qcfCache == null) {
qcfCache = ((QueueConnectionFactory)EJBUtil
.retrieveJNDIEntry ("java:comp/env/jms/QCF"));
}
return qcfCache;
}
private Queue eventQueue ()
throws ResourceNotAvailableException {
if (eventQueueCache == null) {
eventQueueCache = (Queue)EJBUtil.retrieveJNDIEntry
("java:comp/env/jms/InternalEventQueue");
}
return eventQueueCache;
}
private Queue applicationInvocationQueue ()
throws ResourceNotAvailableException {
if (aiQueueCache == null) {
aiQueueCache = (Queue)EJBUtil.retrieveJNDIEntry
("java:comp/env/jms/ApplicationInvocations");
}
return aiQueueCache;
}
/**
* The home interface of the WfProcessBean.
* @return home interface of the WfProcessBean.
*/
private WfProcessHome processHome()
throws ResourceNotAvailableException {
if (processHomeCache == null) {
processHomeCache = (WfProcessHome)EJBUtil.retrieveEJBHome
(WfProcessHome.class, "java:comp/env/ejb/ProcessBean");
}
return processHomeCache;
}
/**
* The local home interface of the WfProcessBean.
* @return local home interface of the WfProcessBean.
*/
private WfProcessLocalHome processLocalHome()
throws ResourceNotAvailableException {
if (processLocalHomeCache == null) {
processLocalHomeCache = (WfProcessLocalHome)
EJBUtil.retrieveEJBLocalHome
(WfProcessLocalHome.class,
"java:comp/env/ejb/ProcessBeanLocal");
}
return processLocalHomeCache;
}
/**
* The workflow engine.
* @return the workflow engine
*/
private WorkflowEngine engine()
throws ResourceNotAvailableException {
if (engineCache == null) {
engineCache = (WorkflowEngine)EJBUtil.createSession
(WorkflowEngineHome.class, "java:comp/env/ejb/WorkflowEngine");
}
return engineCache;
}
/**
* The workflow engine.
* @return the workflow engine
*/
private WorkflowEngineLocal engineLocal()
throws ResourceNotAvailableException {
if (engineLocalCache == null) {
engineLocalCache = (WorkflowEngineLocal)EJBUtil.createSession
(WorkflowEngineLocalHome.class,
"java:comp/env/ejb/WorkflowEngineLocal");
}
return engineLocalCache;
}
/**
* 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/InvocationHelperLocal");
} catch (RemoteException e) {
throw new EJBException (e);
}
}
return invocationHelperCache;
}
/**
* Get the resource assignment invocation handler.
* @return the configured resource assignment invocation handler.
*/
protected RASInvocationHandler rasInvocationHandler() {
if (rasCache == null) {
WorkflowEngine engine = null;
try {
ResourceAssignmentService ras
= engineLocal().resourceAssignmentService ();
if (ras == null) {
return null;
}
rasCache = new DefaultRASInvocationHandler (ras);
} catch (RemoteException rex) {
throw new EJBException (rex);
}
}
return rasCache;
}
//
// EJB container contract
//
/**
* Set the associated session context. The container calls this method
* after the instance creation.
* @see javax.ejb.EntityBean
* @param context - A SessionContext interface for the instance
*/
public void setEntityContext(EntityContext context) {
try {
ctx = context;
// getting new data source
ds = JDBCUtil.refreshDS(null, DB_NAME);
} catch (NamingException ex) {
throw new EJBException(ex);
}
}
/**
* Unset the associated session context.
* @see javax.ejb.EntityBean
*/
public void unsetEntityContext() {
qcfCache = null;
processHomeCache = null;
engineCache = null;
engineLocalCache = null;
activityFinderCache = null;
rasCache = null;
ds = null;
ctx = null;
}
/**
* 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.
* This method gets the primary key from container.
* @see javax.ejb.EntityBean
*/
public void ejbActivate() {
containerCache = null;
containerLocalCache = null;
nextActivitiesCache = null;
thisRemoteCache = null;
}
/**
* 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.EntityBean
*/
public void ejbPassivate() {
containerCache = null;
containerLocalCache = null;
nextActivitiesCache = null;
thisRemoteCache = null;
paDeadlines = null;
dispose();
}
/**
* This method checks if the activity exists.
* If it is ok, it returns the activity-primary-key.
* EJBException is thrown on any error except finder exception.
* @param primaryKey The activity primary key.
* @return The activity-key
* @throws FinderException (<code>ObjectNotFoundException</code>)
* if no activity found.
*/
public Long ejbFindByPrimaryKey(Long primaryKey)
throws FinderException {
boolean result = false;
try {
result = selectByPrimaryKey(primaryKey);
} catch (SQLException ex) {
throw new EJBException(ex);
}
if (!result) {
throw new ObjectNotFoundException
("Row for id " + primaryKey + " not found.");
}
return primaryKey;
}
/**
* This method retrieve the activities of a process.
* @param primaryKey The process primary key.
* @return Collection with whe activity-keys
* @throws FinderException will not be thrown.
* If no activities found, return a empty collection.
*/
public Collection ejbFindByProcess(Long primaryKey)
throws FinderException {
Collection col = null;
try {
col = selectByProcess(primaryKey);
} catch (SQLException ex) {
throw new EJBException(ex);
}
return col;
}
/**
* This method looks up an activity by its
* {@link de.danet.an.workflow.localcoreapi.WfActivityLocal#key key}.
* @param key the activity key
* @return the activity EJB's primary key
* @throws FinderException if no activity found
*/
public Long ejbFindByActivityKey(String key)
throws FinderException {
Long pk = null;
try {
pk = Long.valueOf (key);
} catch (NumberFormatException nex) {
throw new ObjectNotFoundException
("Invalid key format for key = " + key);
}
return ejbFindByPrimaryKey (pk);
}
/**
* This method looks up an activity by its
* its container and waiting on attribute.
* @param processId the containing process' id
* @param channel the channel the activity is waiting on
* @return the activity EJB's primary key
* @throws FinderException if no activity found.
*/
public Long ejbFindByWaitingOn(Long processId, String channel)
throws FinderException {
try {
Long res = selectByWaitingOn(processId, channel);
if (res == null) {
throw new ObjectNotFoundException
("No activity of process " + processId
+ " waiting on " + channel);
}
return res;
} catch (SQLException ex) {
throw new EJBException(ex);
}
}
/**
* Create a new activity and save it into database.
* @param process the containing process
* @param procPk pk of process.
* @param evtBase the base data for an audit event.
* @param blockActId if the activity is part of a block activity,
* else <code>null</code>
* @param priority a <code>Priority</code> value
* @param name the activity's name
* @param description activity description
* @param startMode the start mode
* @param finishMode the finish mode
* @param joinMode the join mode
* @param splitMode the split mode
* @param implementation the implementation description
* @param performer the performer
* @param deadlines the deadlines
* @param deferChoiceOnSplit if the eventual choice of the
* subsequent activity is to be deferred
* @param auditEventSelection the audit event selection
* @param storeAuditEvents if true, audit events are stored in the
* database
* @return primary key of the activity.
* @throws CreateException if the activity can not be create.
* @ejb.create-method view-type="local"
*/
public Long ejbCreate
(WfProcessLocal process, Long procPk, WfAuditEvent evtBase,
Long blockActId, ExtExecutionObjectLocal.Priority priority,
String name, String description,
StartFinishMode startMode, StartFinishMode finishMode,
JoinAndSplitMode joinMode, JoinAndSplitMode splitMode,
Implementation[] implementation, String performer,
List deadlines, boolean deferChoiceOnSplit,
int auditEventSelection, boolean storeAuditEvents)
throws CreateException {
Long activityPk = null;
try {
containerLocalCache = process;
nextActivitiesCache = null;
thisRemoteCache = null;
// create new activityPk
activityPk = new Long(EJBUtil.newPrimaryKey("activity"));
// Process id etc.
processPk = procPk;
processMgr = evtBase.processMgrName();
processName = evtBase.processName();
processMgrVers = evtBase.processMgrVersion();
// assign default to deadlines to avoid loading on access
paDeadlines = new ArrayList ();
// initialize underlying domain object
init(blockActId, priority, name, description, startMode, finishMode,
joinMode, splitMode, implementation, performer, deadlines,
deferChoiceOnSplit, auditEventSelection, storeAuditEvents);
} catch (RemoteException ex) {
throw new EJBException(ex);
}
return activityPk;
}
/**
* Create a new activity with activity modes, join modes
* and save it into database.
* @param process the containing process
* @param procPk pk of process
* @param evtBase the base data for an audit event.
* @param blockActId if the activity is part of a block activity,
* else <code>null</code>
* @param priority a <code>Priority</code> value
* @param name the activity's name
* @param description activity description
* @param startMode the start mode
* @param finishMode the finish mode
* @param joinMode the join mode
* @param splitMode the split mode
* @param implementation the implementation description
* @param performer the performer
* @param deadlines the deadlines
* @param deferChoiceOnSplit if the eventual choice of the
* subsequent activity is to be deferred
* @param auditEventSelection the audit event selection
* @param storeAuditEvents if true, audit events are stored in the
* database
* @throws CreateException if the activity can not be create.
*/
public void ejbPostCreate
(WfProcessLocal process, Long procPk, WfAuditEvent evtBase,
Long blockActId, ExtExecutionObjectLocal.Priority priority,
String name, String description,
StartFinishMode startMode, StartFinishMode finishMode,
JoinAndSplitMode joinMode, JoinAndSplitMode splitMode,
Implementation[] implementation, String performer,
List deadlines, boolean deferChoiceOnSplit,
int auditEventSelection, boolean storeAuditEvents)
throws CreateException {
try {
// notify underlying domain object now (may throw exceptions)
refresh ();
// save the new activity into database
insertActivity();
persistentAttributeModified = false;
slowlyChangingPaModified = false;
threadInfoModified = false;
execTimesModified = false;
deadlinesModified = false;
waitingOnModified = false;
} catch (SQLException e) {
throw new EJBException(e);
}
}
/**
* A container invokes this method to synchronize the state of the
* entity object in the database with the state of the enterprise bean
* instancee.
* @see javax.ejb.EntityBean
*/
public void ejbStore() {
try {
if (persistentAttributeModified) {
storeActivity();
persistentAttributeModified = false;
slowlyChangingPaModified = false;
threadInfoModified = false;
execTimesModified = false;
deadlinesModified = false;
waitingOnModified = false;
}
} catch (SQLException ex) {
throw new EJBException(ex);
}
}
/**
* A container invokes this method to synchronize the state of an
* enterprise bean instance with the entity object's state in the database.
* @see javax.ejb.EntityBean
*/
public void ejbLoad() {
try {
// load activity attributes from persistent store
loadActivity();
// notify underlying domain object
refresh ();
} catch (SQLException ex) {
throw new EJBException(ex);
}
}
/**
* 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.
* @throws RemoveException if the activity is not closed.
* @see javax.ejb.EntityBean
*/
public void ejbRemove() throws RemoveException {
try {
if (getPaTypedState().workflowState() != State.CLOSED
&& (!getPaTypedState().isSameOrSubState
(NotRunningState.NOT_STARTED))) {
throw new RemoveException
("Cannot remove " + toString() + ": still running.");
}
dispose();
removeActivity();
containerCache = null;
containerLocalCache = null;
nextActivitiesCache = null;
thisRemoteCache = null;
paDeadlines = null;
} catch (RemoteException ex) {
throw new EJBException(ex);
} catch (SQLException ex) {
throw new EJBException(ex);
}
}
/**
* This method retrieve the activities of a process.
* @param primaryKey key to looked for
* @return A Collection with primary keys from the found activities.
*/
private Collection selectByProcess(Long primaryKey) throws SQLException {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
Collection activities = new ArrayList();
con = ds.getConnection();
String selectStatement
= "SELECT DBId FROM activity WHERE ProcessDBId = ? "
+ " ORDER BY DBId ";
prepStmt = con.prepareStatement(selectStatement);
prepStmt.setLong(1, primaryKey.longValue());
rs = prepStmt.executeQuery();
while (rs.next()) {
activities.add(new Long(rs.getLong(1)));
}
return activities;
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
}
/**
* This method checks if the activity exists.
* @param primaryKey key to check
* @return If it is ok, it returns true.
*/
private boolean selectByPrimaryKey(Long primaryKey) throws SQLException {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
String selectStatement
= "SELECT DBId FROM activity WHERE DBId = ? ";
prepStmt = con.prepareStatement(selectStatement);
prepStmt.setLong(1, primaryKey.longValue());
rs = prepStmt.executeQuery();
boolean result = rs.next();
return result;
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
}
/**
* This method finds an activity waiting on a channel.
* @param processId the containing process' id
* @param channel the channel
* @return the primary key
*/
private Long selectByWaitingOn(Long processId, String channel)
throws SQLException {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
prepStmt = con.prepareStatement
("SELECT DBId FROM Activity "
+ "WHERE WaitOnProc = ? AND WaitOnChan = ?");
prepStmt.setLong(1, processId.longValue());
prepStmt.setString(2, channel);
rs = prepStmt.executeQuery();
if (rs.next()) {
return new Long (rs.getLong (1));
}
return null;
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
}
/**
* Insert a new activity info into database.
*/
private void insertActivity()
throws SQLException {
Connection con = null;
UniversalPrepStmt prepStmt = null;
try {
con = ds.getConnection();
prepStmt = new UniversalPrepStmt
(ds, con, "INSERT INTO activity (DBId, "
+ "ProcessMgr, ProcessMgrVersion, ProcessName, ProcessDBId, "
+ "Name, Description, BlockActivity, "
+ "Implementation, Performer, Priority, Executor, StartMode, "
+ "FinishMode, State, StateTime, JoinMode, SplitMode, "
+ "ThreadInfo, Subflow, SuspendAccum, PendingException, "
+ "WaitOnProc, WaitOnChan, Flags) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?, ?, ?)");
int offset = 1;
prepStmt.setLong(offset++,
((Long)ctx.getPrimaryKey()).longValue());
prepStmt.setString (offset++, processMgr);
prepStmt.setString (offset++, processMgrVers);
prepStmt.setString (offset++, processName);
prepStmt.setLong(offset++, processPk.longValue());
prepStmt.setString (offset++, paName);
prepStmt.setString (offset++, paDescription);
prepStmt.setLong (offset++, paBlockActivity);
prepStmt.setBinary (offset++, paActImpl);
prepStmt.setString (offset++, paPerformer);
prepStmt.setInt(offset++, paPriority.toInt ());
prepStmt.setInt (offset++, paExecStat);
prepStmt.setString (offset++, paStartMode.toString());
prepStmt.setString (offset++, paFinishMode.toString());
prepStmt.setString (offset++, paTypedState.toString ());
prepStmt.setTimestamp
(offset++, new Timestamp (paLastStateTime.getTime()));
prepStmt.setString (offset++, paJoinMode.toString ());
prepStmt.setString (offset++, paSplitMode.toString ());
prepStmt.setBinary (offset++, paThreadInfo);
prepStmt.setLong
(offset++, paSubflow == null ? null : new Long(paSubflow));
prepStmt.setLong(offset++, new Long (0)); // SuspendAccum
prepStmt.setString(offset++, null); // PendingException
prepStmt.setLong(offset++, null); // WaitOnProc
prepStmt.setString(offset++, null); // WaitOnChan
prepStmt.setInt(offset++, paFlags); // Flags
// now execute
prepStmt.executeUpdate();
WfProcessEJB.updateDeadlines
(ds, con, processPk, (Long)ctx.getPrimaryKey(),
paDeadlines, false);
} catch (IOException ioe) {
logger.error (ioe.getMessage(), ioe);
} finally {
JDBCUtil.closeAll (null, prepStmt, con);
}
}
/**
* Store activity info in the database.
*/
private void storeActivity() throws SQLException {
Connection con = null;
UniversalPrepStmt prepStmt = null;
try {
con = ds.getConnection();
prepStmt = new UniversalPrepStmt
(ds, con, "UPDATE activity "
+ "SET State = ?, StateTime = ?, Executor = ?, Subflow = ?, "
+ "Flags = ?"
+ (execTimesModified
? ", StartTime = ?, SuspendStart = ?, SuspendAccum = ? "
: "")
+ (threadInfoModified ? ", ThreadInfo = ? " : "")
+ (waitingOnModified ? ", WaitOnProc = ?, WaitOnChan = ? ":"")
+ (slowlyChangingPaModified
? (", ProcessName = ?, Name = ?, Description = ?, "
+ "Implementation = ?, Performer = ?, "
+ "Priority = ?, StartMode = ?, "
+ "FinishMode = ?, JoinMode = ?, SplitMode = ?, "
+ "PendingException = ?")
: "")
+ " WHERE DBId = ?");
int offset = 1;
prepStmt.setString (offset++, paTypedState.toString());
prepStmt.setTimestamp
(offset++, new Timestamp (paLastStateTime.getTime()));
prepStmt.setInt (offset++, paExecStat);
prepStmt.setLong
(offset++, paSubflow==null ? null : new Long(paSubflow));
prepStmt.setInt (offset++, paFlags);
if (execTimesModified) {
prepStmt.setTimestamp
(offset++, (paStartTime == null ? null
: new Timestamp (paStartTime.getTime())));
prepStmt.setTimestamp
(offset++, (paSuspendStart == null ? null
: new Timestamp (paSuspendStart.getTime())));
prepStmt.setLong
(offset++, new Long(paSuspendAccum));
}
if (threadInfoModified) {
prepStmt.setBinary (offset++, paThreadInfo);
}
if (waitingOnModified) {
prepStmt.setLong (offset++, paWaitOnProc);
prepStmt.setString (offset++, paWaitOnChan);
}
if (slowlyChangingPaModified) {
prepStmt.setString (offset++, processName);
prepStmt.setString (offset++, paName);
prepStmt.setString (offset++, paDescription);
prepStmt.setBinary (offset++, paActImpl);
prepStmt.setString (offset++, paPerformer);
prepStmt.setInt(offset++, paPriority.toInt());
prepStmt.setString (offset++, paStartMode.toString());
prepStmt.setString (offset++, paFinishMode.toString());
prepStmt.setString (offset++, paJoinMode.toString());
prepStmt.setString (offset++, paSplitMode.toString());
prepStmt.setString (offset++, paPendingException);
}
// for where statement
prepStmt.setLong(offset++,
((Long)ctx.getPrimaryKey()).longValue());
int rowCount = prepStmt.executeUpdate();
if (rowCount == 0) {
throw new NoSuchEntityException
("Storing row for DBId "
+ (Long)ctx.getPrimaryKey() + " failed.");
}
if (deadlinesModified) {
WfProcessEJB.updateDeadlines
(ds, con, processPk, (Long)ctx.getPrimaryKey(),
paDeadlines, true);
}
} catch (IOException ioe) {
logger.error (ioe.getMessage(), ioe);
} finally {
JDBCUtil.closeAll (null, prepStmt, con);
}
}
/**
* Load activity info from the database.
* After sucessful loading, the process attribute structure
* is set with the values just loaded.
*/
private void loadActivity()
throws SQLException {
Connection con = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
if (haveSelForUp == null) {
haveSelForUp = new Boolean(JDBCUtil.dbProperties(ds, con)
.supportsSelectForUpdate ());
}
prepStmt = con.prepareStatement
("SELECT "
+ "ProcessMgr, ProcessMgrVersion, ProcessName, ProcessDBId, "
+ "Name, Description, BlockActivity, Implementation, "
+ "Performer, Priority, executor, StartMode, FinishMode, "
+ "State, StateTime, JoinMode, SplitMode, ThreadInfo, "
+ "Subflow, StartTime, SuspendStart, SuspendAccum, "
+ "PendingException, WaitOnProc, WaitOnChan, Flags "
+ "FROM activity WHERE DBId = ? "
+ (haveSelForUp.booleanValue() ? " FOR UPDATE" : ""));
prepStmt.setLong(1, ((Long)ctx.getPrimaryKey()).longValue());
rs = prepStmt.executeQuery();
if (!rs.next()) {
throw new NoSuchEntityException
("Row for id " + (Long)ctx.getPrimaryKey()
+ " not found in database.");
}
// read activity from db
int offset = 1;
processMgr = rs.getString(offset++);
processMgrVers = rs.getString(offset++);
processName = rs.getString(offset++);
processPk = new Long(rs.getLong(offset++));
paName = rs.getString(offset++);
paDescription = rs.getString(offset++);
paBlockActivity = JDBCUtil.getLong(rs, offset++);
paActImpl = (Implementation[])JDBCUtil.getBinary(rs, offset++);
paPerformer = rs.getString(offset++);
paPriority = Priority.fromInt(rs.getInt(offset++));
paExecStat = JDBCUtil.getInteger(rs, offset++);
paStartMode = StartFinishMode.fromString(rs.getString(offset++));
paFinishMode = StartFinishMode.fromString(rs.getString(offset++));
paTypedState = State.fromString(rs.getString(offset++));
paLastStateTime = rs.getTimestamp(offset++);
paJoinMode = JoinAndSplitMode.fromString(rs.getString(offset++));
paSplitMode = JoinAndSplitMode.fromString(rs.getString(offset++));
paThreadInfo = (ThreadInfo)JDBCUtil.getBinary(rs, offset++);
Long sf = JDBCUtil.getLong (rs, offset++);
paSubflow = (sf == null ? null : sf.toString());
paStartTime = rs.getTimestamp(offset++);
paSuspendStart = rs.getTimestamp(offset++);
paSuspendAccum = rs.getLong(offset++);
paPendingException = rs.getString(offset++);
paWaitOnProc = JDBCUtil.getLong(rs, offset++);
paWaitOnChan = rs.getString(offset++);
paFlags = rs.getInt(offset++);
} catch (IOException ioe) {
logger.error (ioe.getMessage(), ioe);
throw new SQLException(ioe.getMessage());
} catch (ClassNotFoundException cnfe) {
logger.error (cnfe.getMessage(), cnfe);
throw new SQLException(cnfe.getMessage());
} catch (InvalidStateException ise) {
logger.error (ise.getMessage(), ise);
throw new SQLException(ise.getMessage());
} catch (InvalidPriorityException ipe) {
logger.error (ipe.getMessage(), ipe);
throw new SQLException(ipe.getMessage());
} finally {
JDBCUtil.closeAll (rs, prepStmt, con);
}
}
/**
* Remove activity info from the database.
*/
private void removeActivity() throws SQLException, RemoteException {
Connection con = null;
PreparedStatement prepStmt = null;
try {
if (!typedState().isSameOrSubState (State.CLOSED)
&& !(typedState().isSameOrSubState
(NotRunningState.NOT_STARTED))) {
releaseResources ();
try {
terminateImpl();
} catch (ApplicationNotStoppedException ans) {
logger.warn ("Removing activity " + toString()
+ " while tool still running.");
}
}
con = ds.getConnection();
String deleteStatement = "DELETE FROM activity WHERE DBId = ? ";
prepStmt = con.prepareStatement(deleteStatement);
prepStmt.setLong(1, ((Long)ctx.getPrimaryKey()).longValue());
prepStmt.executeUpdate();
// deadlines are removed with the process
} finally {
JDBCUtil.closeAll (null, prepStmt, con);
}
}
//
// Domain methods and helpers
//
/**
* Indicates if some other object is equal to this one. <P>
*
* Note that <code>obj</code> must implement the activity's
* remote interface. Comparing a domain object usually
* indicates some violation of the constraints of our
* implementation environment.
*
* @param obj the object to compare with.
* @return <code>true</code> if the other object is equal.
*/
public boolean equals (Object obj) {
return ctx.getPrimaryKey().toString()
.equals (((WfActivityLocal)obj).key());
}
/**
* Return the hash code.<P>
* @return the result.
*/
public int hashCode () {
return ctx.getPrimaryKey().toString().hashCode();
}
/**
* Check if the given assignment is among the assignments of this
* activity.
* @param member the assignment in question.
* @return true if the assignment is among the assignments of this
* activity.
* @ejb.interface-method view-type="remote"
*/
public boolean isMemberOfAssignments (WfAssignment member) {
throw new UnsupportedOperationException();
}
/**
* Return the remote version of this object. This is the client side
* implementation of the remote interface (i.e. the EJB object).
*
* @return the remote stub.
*/
public Activity toActivity () {
if (thisRemoteCache == null) {
try {
thisRemoteCache = ActivityProxy
.wrap ((ExtActivity)ctx.getEJBObject(),
container (), uniqueKey());
} catch (RemoteException e) {
// actually, uniqueKey never throws a remote exception in
// this context (and getEJBObject never does)
logger.error (e.getMessage (), e);
throw new IllegalStateException (e.getMessage());
}
}
return thisRemoteCache;
}
/* (non-Javadoc)
* Comment copied from interface or superclass.
*/
public ExtActivityLocal toActivityLocal() {
ExtActivityLocal actLocal = (ExtActivityLocal)ctx.getEJBLocalObject();
return actLocal;
}
/**
* Returns the <code>WfProcess</code> that this activity is a part of.
* @return the process.
* @ejb.interface-method view-type="remote"
*/
public WfProcess container() {
if (containerCache == null) {
try {
containerCache = processHome().findByPrimaryKey(processPk);
} catch (FinderException fe) {
throw new EJBException(fe);
} catch (RemoteException re) {
throw new EJBException(re);
}
}
return containerCache;
}
/**
* Returns the <code>WfProcessLocal</code> that this activity is a part of.
* @return the process.
* @ejb.interface-method view-type="local"
*/
public WfProcessLocal containerLocal() {
if (containerLocalCache == null) {
try {
containerLocalCache
= processLocalHome().findByPrimaryKey(processPk);
} catch (FinderException fe) {
throw new EJBException(fe);
} catch (RemoteException re) {
throw new EJBException(re);
}
}
return containerLocalCache;
}
/**
* Lookup a process by its key.
* @param key the primary key
* @return the process
* @throws RemoteException if a system-level error occurs
* @throws InvalidKeyException if no process with the given key
* exists
*/
protected ExtProcessLocal lookupProcessLocal (String key)
throws InvalidKeyException {
try {
return processLocalHome().findByPrimaryKey(new Long(key));
} catch (FinderException fe) {
logger.debug (fe.getMessage (), fe);
throw new InvalidKeyException(fe.getMessage ());
} catch (ResourceNotAvailableException e) {
throw new EJBException (e);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
/**
* Returns an {@link de.danet.an.workflow.spis.ras.ActivityFinder
* <code>ActivityFinder</code>} that identifies this activity
* against a resource assignment service as defined by
* {@link de.danet.an.workflow.spis.ras the ras package}.
*
* @return the activity finder.
*/
public ActivityFinder activityFinder () {
if (activityFinderCache == null) {
activityFinderCache
= new de.danet.an.workflow.ejbs.admin.ActivityFinder
("java:comp/env/ejb/Configuration");
}
return activityFinderCache;
}
/**
* Returns an <code>WfAuditEvent</code> containing container-related
* information.
* @return the audit event
*/
protected WfAuditEvent containerAuditEventBase () {
return new DefaultAuditEvent
(null, null, processPk.toString(), processName,
processMgr, processMgrVers, getPaAuditEventSelection(),
getPaStoreAuditEvents());
}
/**
* Returns a <code>WfAuditEvent</code> containing information about the
* activity and its container, only.
* @return the event containing the required information.
* @ejb.interface-method view-type="remote"
*/
public WfAuditEvent auditEventBase () {
return auditEventBase (null);
}
/**
* Returns the list of activities that may follow this activity,
* i.e. to which transitions exist.
* The list follows the order of transitions as returend by the
* container.
* @return the list of {@link de.danet.an.workflow.domain Activity
* <code>Activity</code>} objects.
* @ejb.interface-method view-type="remote"
*/
public List nextActivities () {
// cached result?
if (nextActivitiesCache != null) {
return nextActivitiesCache;
}
// new evaluation needed
nextActivitiesCache = new ArrayList();
List allTrans = ((ProcessLocal)containerLocal()).transitionsLocal();
for (Iterator tri = allTrans.iterator(); tri.hasNext();) {
TransitionLocal trans = (TransitionLocal)tri.next();
if (key().equals (trans.from().key())) {
nextActivitiesCache.add
(((ExtActivityLocal)trans.to()).toActivity());
}
}
return nextActivitiesCache;
}
/**
* Return a <code>ToolInvocationHandler</code>.
* @return a handler.
*/
protected ToolInvocationHandler toolInvocationHandler () {
if (toolInvocationHandlerCache == null) {
try {
toolInvocationHandlerCache
= new DefaultToolInvocationHandler
(engine(), engineLocal(),
queueConnectionFactory(), applicationInvocationQueue(),
invocationHelper());
} catch (ResourceNotAvailableException e) {
throw new EJBException (e);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
return toolInvocationHandlerCache;
}
/**
* Process newly generated event.
* @param evt Event
*/
protected void fireAuditEvent(WfAuditEvent evt) {
try {
QueuerUtils.queue (queueConnectionFactory(), eventQueue(),
(DefaultAuditEvent)evt);
} catch (RemoteException e) {
throw new EJBException (e);
}
}
/**
* Returns a collection of <code>WfAuditEvent</code>s associated with
* this process describing its history.
* @return the collection of audit events
* @throws HistoryNotAvailableException in case the history is not
* available for any reason
* @ejb.interface-method view-type="remote"
*/
public Collection history()
throws HistoryNotAvailableException {
WorkflowEngine engine = null;
try {
return engineLocal().history (toActivity());
} catch (RemoteException rex){
throw new EJBException (rex);
}
}
/**
* Updates the process name (which is cached by the activity EJB)
* if the process name changes.
* @param newName the new process name.
* @ejb.interface-method view-type="remote"
*/
public void updateProcessName (String newName) {
processName = newName;
slowlyChangingPaModified = true;
}
/**
* Check if the given process is among the performers of this requester.
*
* @param member the process in question.
* @return <code>true</code> if the <code>process</code> is among
* the performers of this requester.
*/
public boolean isMemberOfPerformers(WfProcess member) {
for (Iterator ps = performers().iterator(); ps.hasNext();) {
WfProcess p = (WfProcess)ps.next();
try {
if (p.key().equals (member.key())) {
return true;
}
} catch (RemoteException e) {
throw new EJBException (e);
}
}
return false;
}
//
// Timers
//
/**
* Start a timer that will call <code>handleTimeout</code> at the
* given date with the given info.
* @param due target date
* @param info the context
*/
public void startTimer (Date due, Serializable info) {
if (logger.isDebugEnabled()) {
logger.debug("Starting timer for " + toString()
+ ", due at " + due);
}
// Adjust duration
long duration = due.getTime() - System.currentTimeMillis();
if (duration <= 0) {
logger.warn("Deadline with zero or negative duration ("
+ ((double)duration / 1000) + "s) for "
+ toString() + " will be triggered immediately.");
duration = 1;
}
if (ctx.getClass().getName().startsWith("org.jboss.ejb.")) {
// create a timer with interval to circumvent JBoss bug JBAS-2274
ctx.getTimerService().createTimer (duration, 3600 * 1000, info);
} else {
ctx.getTimerService().createTimer (duration, info);
}
}
/**
* Stop all timers that this object has created.
*/
public void stopTimers () {
for (Iterator i = ctx.getTimerService().getTimers().iterator ();
i.hasNext ();) {
Timer timer = (Timer)i.next();
timer.cancel ();
}
}
/**
* Handle the timeout of a timer.
* @param timer the timer that has expired.
*/
public void ejbTimeout (Timer timer) {
try {
if (logger.isDebugEnabled()) {
logger.debug ("Received timeout from " + timer
+ " for " + toString());
}
try {
handleTimeout (timer.getInfo());
if (ctx.getClass().getName().startsWith("org.jboss.ejb.")) {
// Because of JBoss bug JBAS-2274 we have an interval and
// must therefore cancel the timer
timer.cancel();
}
} catch (NoSuchObjectLocalException e) {
// JBoss may call this method with a canceled timer
if (timer.getClass().getName()
.equals("org.jboss.ejb.txtimer.TimerImpl")) {
logger.debug("Exception \"" + e.getMessage()
+ "\" ignored, caused by JBoss bug.");
return;
}
throw e;
}
} catch (EJBException e) {
throw e;
} catch (Throwable e) {
logger.error ("Problem handling timer event " + timer
+ "(discarded): " + e.getMessage(), e);
}
}
//
// Implement accessor methods for the persistent attributes
//
/**
* The getter method implementation for the persistent
* attribute <code>key</code>.
*
* @return the value of key.
*/
protected String getPaKey() {
return ((Long)ctx.getPrimaryKey()).toString();
}
/**
* The getter method implementation for the persistent
* attribute <code>name</code>.
*
* @see #setPaName
* @return the value of name.
*/
protected String getPaName() {
return paName;
}
/**
* The setter method implementation for the persistent
* attribute <code>name</code>.
*
* @param newName the new value of name.
* @see #getPaName
*/
protected void setPaName(String newName) {
paName = newName;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>description</code>.
*
* @see #setPaDescription
* @return the value of description.
*/
protected String getPaDescription() {
return paDescription;
}
/**
* The setter method implementation for the persistent
* attribute <code>description</code>.
*
* @param newDescription the new value of description.
* @see #getPaDescription
*/
protected void setPaDescription(String newDescription) {
paDescription = newDescription;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>priority</code>.
*
* @see #setPaPriority
* @return the value of priority.
*/
protected Priority getPaPriority() {
return paPriority;
}
/**
* The setter method implementation for the persistent
* attribute <code>priority</code>.
*
* @param newPriority the new value of priority.
* @see #getPaPriority
*/
protected void setPaPriority(Priority newPriority) {
paPriority = newPriority;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>typedState</code>.
*
* @see #setPaTypedState
* @return the value of typedState.
*/
protected State getPaTypedState() {
return paTypedState;
}
/**
* The getter method implementation for the persistent
* attribute <code>lastStateTime</code>.
*
* @see #setPaLastStateTime
* @return the value of lastStateTime.
*/
protected Date getPaLastStateTime() {
return paLastStateTime;
}
/**
* The setter method implementation for the persistent
* attribute <code>lastStateTime</code>.
*
* @param newLastStateTime the new value of lastStateTime.
* @see #getPaLastStateTime
*/
protected void setPaLastStateTime(Date newLastStateTime) {
paLastStateTime = newLastStateTime;
persistentAttributeModified = true;
}
/**
* The setter method implementation for the persistent
* attribute <code>typedState</code>.
*
* @param newTypedState the new value of typedState.
* @see #getPaTypedState
*/
protected void setPaTypedState(State newTypedState) {
paTypedState = newTypedState;
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>startMode</code>.
*
* @see #setPaStartMode
* @return the value of startMode.
*/
protected StartFinishMode getPaStartMode() {
return paStartMode;
}
/**
* The setter method implementation for the persistent
* attribute <code>startMode</code>.
*
* @param newStartMode the new value of startMode.
* @see #getPaStartMode
*/
protected void setPaStartMode(StartFinishMode newStartMode) {
paStartMode = newStartMode;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>finishMode</code>.
*
* @see #setPaFinishMode
* @return the value of finishMode.
*/
protected StartFinishMode getPaFinishMode() {
return paFinishMode;
}
/**
* The setter method implementation for the persistent
* attribute <code>finishMode</code>.
*
* @param newFinishMode the new value of finishMode.
* @see #getPaFinishMode
*/
protected void setPaFinishMode(StartFinishMode newFinishMode) {
paFinishMode = newFinishMode;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>joinMode</code>.
*
* @see #setPaJoinMode
* @return the value of joinMode.
*/
protected JoinAndSplitMode getPaJoinMode() {
return paJoinMode;
}
/**
* The setter method implementation for the persistent
* attribute <code>joinMode</code>.
*
* @param newJoinMode the new value of joinMode.
* @see #getPaJoinMode
*/
protected void setPaJoinMode(JoinAndSplitMode newJoinMode) {
paJoinMode = newJoinMode;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>splitMode</code>.
*
* @see #setPaSplitMode
* @return the value of splitMode.
*/
protected JoinAndSplitMode getPaSplitMode() {
return paSplitMode;
}
/**
* The setter method implementation for the persistent
* attribute <code>splitMode</code>.
*
* @param newSplitMode the new value of splitMode.
* @see #getPaSplitMode
*/
protected void setPaSplitMode(JoinAndSplitMode newSplitMode) {
paSplitMode = newSplitMode;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>executor</code>.
*
* @see #setPaExecStat
* @return the value of executor.
*/
protected Integer getPaExecStat() {
return paExecStat;
}
/**
* The getter method implementation for the persistent
* attribute <code>performer</code>.
*
* @see #setPaPerformer
* @return the value of performer.
*/
protected String getPaPerformer() {
return paPerformer;
}
/**
* The setter method implementation for the persistent
* attribute <code>performer</code>.
*
* @param newPerformer the new value of performer.
* @see #getPaPerformer
*/
protected void setPaPerformer(String newPerformer) {
paPerformer = newPerformer;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The setter method implementation for the persistent
* attribute <code>executor</code>.
*
* @param newExecutor the new value of executor.
* @see #getPaExecStat
*/
protected void setPaExecStat(Integer newExecutor) {
paExecStat = newExecutor;
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>actImpl</code>.
*
* @see #setPaActImpl
* @return the value of actImpl.
*/
protected Implementation[] getPaActImpl() {
return paActImpl;
}
/**
* The setter method implementation for the persistent
* attribute <code>actImpl</code>.
*
* @param newActImpl the new value of actImpl.
* @see #getPaActImpl
*/
protected void setPaActImpl(Implementation[] newActImpl) {
paActImpl = newActImpl;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/**
* The getter method implementation for the persistent
* read-only attribute <code>processKey</code>.
*
* @return the value of processKey.
*/
protected String getPaProcessKey() {
return processPk.toString();
}
/**
* The getter method implementation for the persistent
* read-only attribute <code>processName</code>.
*
* @return the value of processName.
*/
protected String getPaProcessName() {
return processName;
}
/**
* The getter method implementation for the persistent
* read-only attribute <code>processMgrName</code>.
*
* @return the value of processMgrName.
*/
protected String getPaProcessMgrName() {
return processMgr;
}
/**
* The getter method implementation for the persistent
* read-only attribute <code>processMgrVersion</code>.
*
* @return the value of processMgrVersion.
*/
protected String getPaProcessMgrVersion() {
return processMgrVers;
}
/**
* The getter method implementation for the persistent
* attribute <code>threadInfo</code>.
*
* @see #setPaThreadInfo
* @return the value of threadInfo.
*/
protected ThreadInfo getPaThreadInfo() {
return paThreadInfo;
}
/**
* The setter method implementation for the persistent
* attribute <code>threadInfo</code>.
*
* @param newThreadInfo the new value of threadInfo.
* @see #getPaThreadInfo
*/
protected void setPaThreadInfo(ThreadInfo newThreadInfo) {
paThreadInfo = newThreadInfo;
persistentAttributeModified = true;
threadInfoModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>Subflow</code>.
*
* @see #setPaSubflow
* @return the value of Subflow.
*/
protected String getPaSubflow() {
return paSubflow;
}
/**
* The setter method implementation for the persistent
* attribute <code>Subflow</code>.
*
* @param newSubflow the new value of Subflow.
* @see #getPaSubflow
*/
protected void setPaSubflow(String newSubflow) {
paSubflow = newSubflow;
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>deadlines</code>.
*
* @see #setPaDeadlines
* @return the value of deadlines.
*/
protected List getPaDeadlines() {
if (paDeadlines == null) {
try {
paDeadlines = WfProcessEJB.loadDeadlines
(ds, (Long)ctx.getPrimaryKey());
} catch (SQLException e) {
throw new EJBException (e);
} catch (IOException e) {
throw new EJBException (e);
}
}
return paDeadlines;
}
/**
* The setter method implementation for the persistent
* attribute <code>deadlines</code>.
*
* @param newDeadlines the new value of deadlines.
* @see #getPaDeadlines
*/
protected void setPaDeadlines(List newDeadlines) {
paDeadlines = newDeadlines;
persistentAttributeModified = true;
deadlinesModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>startTime</code>.
*
* @see #setPaStartTime
* @return the value of startTime.
*/
protected Date getPaStartTime() {
return paStartTime;
}
/**
* The setter method implementation for the persistent
* attribute <code>startTime</code>.
*
* @param newStartTime the new value of startTime.
* @see #getPaStartTime
*/
protected void setPaStartTime(Date newStartTime) {
paStartTime = newStartTime;
execTimesModified = true;
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>suspendStart</code>.
*
* @see #setPaSuspendStart
* @return the value of suspendStart.
*/
protected Date getPaSuspendStart() {
return paSuspendStart;
}
/**
* The setter method implementation for the persistent
* attribute <code>suspendStart</code>.
*
* @param newSuspendStart the new value of suspendStart.
* @see #getPaSuspendStart
*/
protected void setPaSuspendStart(Date newSuspendStart) {
paSuspendStart = newSuspendStart;
persistentAttributeModified = true;
execTimesModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>suspendAccum</code>.
*
* @see #setPaSuspendAccum
* @return the value of suspendAccum.
*/
protected long getPaSuspendAccum() {
return paSuspendAccum;
}
/**
* The setter method implementation for the persistent
* attribute <code>suspendAccum</code>.
*
* @param newSuspendAccum the new value of suspendAccum.
* @see #getPaSuspendAccum
*/
protected void setPaSuspendAccum(long newSuspendAccum) {
paSuspendAccum = newSuspendAccum;
persistentAttributeModified = true;
execTimesModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>pendingException</code>.
*
* @see #setPaPendingException
* @return the value of pendingException.
*/
protected String getPaPendingException() {
return paPendingException;
}
/**
* The setter method implementation for the persistent
* attribute <code>pendingException</code>.
*
* @param newPendingException the new value of pendingException.
* @see #getPaPendingException
*/
protected void setPaPendingException(String newPendingException) {
paPendingException = newPendingException;
persistentAttributeModified = true;
slowlyChangingPaModified = true;
}
/** Persistent attribute <code>blockActivity</code>. */
private Long paBlockActivity;
/**
* The getter method implementation for the persistent
* attribute <code>blockActivity</code>.
*
* @see #setPaBlockActivity
* @return the value of blockActivity.
*/
protected Long getPaBlockActivity() {
return paBlockActivity;
}
/**
* The setter method implementation for the persistent attribute
* <code>blockActivity</code>. May only be used in base class'
* init.
*
* @param newBlockActivity the new value of blockActivity.
* @see #getPaBlockActivity
*/
protected void setPaBlockActivity(Long newBlockActivity) {
paBlockActivity = newBlockActivity;
}
/**
* The getter method implementation for the persistent
* attribute <code>waitOnProc</code>.
*
* @see #setPaWaitOnProc
* @return the value of waitOnProc.
*/
protected Long getPaWaitOnProc() {
return paWaitOnProc;
}
/**
* The setter method implementation for the persistent
* attribute <code>waitOnProc</code>.
*
* @param newWaitOnProc the new value of waitingOn.
* @see #getPaWaitOnProc
*/
protected void setPaWaitOnProc(Long newWaitOnProc) {
if (newWaitOnProc == null && paWaitOnProc == null
|| (newWaitOnProc != null && paWaitOnProc != null
&& newWaitOnProc.equals (paWaitOnProc))) {
return;
}
paWaitOnProc = newWaitOnProc;
persistentAttributeModified = true;
waitingOnModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>waitOnChan</code>.
*
* @see #setPaWaitOnChan
* @return the value of waitOnChan.
*/
protected String getPaWaitOnChan() {
return paWaitOnChan;
}
/**
* The setter method implementation for the persistent
* attribute <code>waitOnChan</code>.
*
* @param newWaitOnChan the new value of waitingOn.
* @see #getPaWaitOnChan
*/
protected void setPaWaitOnChan(String newWaitOnChan) {
if (newWaitOnChan == null && paWaitOnChan == null
|| (newWaitOnChan != null && paWaitOnChan != null
&& newWaitOnChan.equals (paWaitOnChan))) {
return;
}
paWaitOnChan = newWaitOnChan;
persistentAttributeModified = true;
waitingOnModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>debug</code>.
*
* @see #setPaDebug
* @return the value of debug.
*/
protected boolean getPaDebug() {
return (paFlags & FLAGS_DEBUG) != 0;
}
/**
* The setter method implementation for the persistent
* attribute <code>debug</code>.
*
* @param newDebug the new value of debug.
* @see #getPaDebug
*/
protected void setPaDebug(boolean newDebug) {
paFlags = (paFlags & ~FLAGS_DEBUG)
| (newDebug ? FLAGS_DEBUG : 0);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>subStateBackup</code>.
*
* @see #setPaSubStateBackup
* @return the value of subStateBackup.
*/
protected int getPaSubStateBackup() {
return (paFlags & FLAGS_SUB_STATE_MASK) >> FLAGS_SUB_STATE_SHIFT;
}
/**
* The setter method implementation for the persistent
* attribute <code>subStateBackup</code>.
*
* @param newSubStateBackup the new value of subStateBackup.
* @see #getPaSubStateBackup
*/
protected void setPaSubStateBackup(int newSubStateBackup) {
paFlags = (paFlags & ~FLAGS_SUB_STATE_MASK)
| (newSubStateBackup << FLAGS_SUB_STATE_SHIFT);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>deferChoiceOnSplit</code>.
*
* @see #setPaDeferChoiceOnSplit
* @return the value of deferChoiceOnSplit.
*/
protected boolean getPaDeferChoiceOnSplit() {
return (paFlags & FLAGS_DEFERRED_CHOICE) != 0;
}
/**
* The setter method implementation for the persistent
* attribute <code>deferChoiceOnSplit</code>.
*
* @param newDeferChoiceOnSplit the new value of deferChoiceOnSplit.
* @see #getPaDeferChoiceOnSplit
*/
protected void setPaDeferChoiceOnSplit(boolean newDeferChoiceOnSplit) {
paFlags = (paFlags & ~FLAGS_DEFERRED_CHOICE)
| (newDeferChoiceOnSplit ? FLAGS_DEFERRED_CHOICE : 0);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>preliminaryChosen</code>.
*
* @see #setPaPreliminarilyChosen
* @return the value of preliminarilyChosen.
*/
protected boolean getPaPreliminarilyChosen() {
return (paFlags & FLAGS_PRELIMINARILY_CHOSEN) != 0;
}
/**
* The setter method implementation for the persistent
* attribute <code>preliminaryChosen</code>.
*
* @param newPreliminarilyChosen the new value of preliminarilyChosen.
* @see #getPaPreliminarilyChosen
*/
protected void setPaPreliminarilyChosen(boolean newPreliminarilyChosen) {
paFlags = (paFlags & ~FLAGS_PRELIMINARILY_CHOSEN)
| (newPreliminarilyChosen ? FLAGS_PRELIMINARILY_CHOSEN : 0);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>noAssignments</code>.
*
* @see #setPaNoAssignments
* @return the value of noAssignments.
*/
protected boolean getPaNoAssignments() {
return (paFlags & FLAGS_NO_ASSIGNMENTS) != 0;
}
/**
* The setter method implementation for the persistent
* attribute <code>noAssignments</code>.
*
* @param newNoAssignments the new value of noAssignments.
* @see #getPaNoAssignments
*/
protected void setPaNoAssignments(boolean newNoAssignments) {
paFlags = (paFlags & ~FLAGS_NO_ASSIGNMENTS)
| (newNoAssignments ? FLAGS_NO_ASSIGNMENTS : 0);
persistentAttributeModified = true;
}
/**
* The getter method for the persistent flag
* <code>pendingExceptionIsFromBlock</code>.
*
* @return the value of the flag.
* @see #setPaPendingExceptionIsFromBlock
*/
protected boolean getPaPendingExceptionIsFromBlock() {
return (paFlags & FLAGS_PENDING_EXCEPTION_IS_FROM_BLOCK) != 0;
}
/**
* The setter method for the persistent flags
* <code>pendingExceptionIsFromBlock</code>.
*
* @param newValue the new value of the flag.
* @see #getPaPendingExceptionIsFromBlock
*/
protected void setPaPendingExceptionIsFromBlock (boolean newValue) {
paFlags = (paFlags & ~FLAGS_PENDING_EXCEPTION_IS_FROM_BLOCK)
| (newValue ? FLAGS_PENDING_EXCEPTION_IS_FROM_BLOCK : 0);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>auditEventSelection</code>.
*
* @see #setPaAuditEventSelection
* @return the value of auditEventSelection.
*/
protected int getPaAuditEventSelection() {
return (paFlags & FLAGS_AUDIT_SELECTION_MASK)
>> FLAGS_AUDIT_SELECTION_SHIFT;
}
/**
* The setter method implementation for the persistent
* attribute <code>auditEventSelection</code>.
*
* @param newValue the new value of auditEventSelection.
* @see #getPaAuditEventSelection
*/
protected void setPaAuditEventSelection (int newValue) {
paFlags = (paFlags & ~FLAGS_AUDIT_SELECTION_MASK)
| (newValue << FLAGS_AUDIT_SELECTION_SHIFT);
persistentAttributeModified = true;
}
/**
* The getter method implementation for the persistent
* attribute <code>storeAuditEvents</code>.
*
* @see #setPaStoreAuditEvents
* @return the value of storeAuditEvents.
*/
protected boolean getPaStoreAuditEvents() {
return (paFlags & FLAGS_STORE_AUDIT_EVENTS) != 0;
}
/**
* The setter method implementation for the persistent
* attribute <code>storeAuditEvents</code>.
*
* @param newValue the new value of storeAuditEvents.
* @see #getPaStoreAuditEvents
*/
protected void setPaStoreAuditEvents(boolean newValue) {
paFlags = (paFlags & ~FLAGS_STORE_AUDIT_EVENTS)
| (newValue ? FLAGS_STORE_AUDIT_EVENTS : 0);
persistentAttributeModified = true;
}
}