mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Workflow Checkpoint:
- Process deploy/isDeployed/undeploy implemented in Workflow Service - Servlet implemented to support jBPM Process Designer deployment (using above service) : mapped to /alfresco/jbpm/deployprocess URL - Workflow deployer bootstrap bean (for once- only loading of process definitions at bootstrap) - Initial cut of Review & Approve process definition & Task definitions (bootstrapped) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3477 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -34,10 +34,23 @@ public interface WorkflowDefinitionComponent
|
||||
* Deploy a Workflow Definition
|
||||
*
|
||||
* @param workflowDefinition the content object containing the definition
|
||||
* @param mimetype (optional) the mime type of the workflow definition
|
||||
* @return workflow definition
|
||||
*/
|
||||
public WorkflowDefinition deployDefinition(InputStream workflowDefinition);
|
||||
public WorkflowDefinition deployDefinition(InputStream workflowDefinition, String mimetype);
|
||||
|
||||
/**
|
||||
* Is the specified Workflow Definition already deployed?
|
||||
*
|
||||
* Note: the notion of "already deployed" may differ between bpm engines. For example,
|
||||
* different versions of the same process may be considered equal.
|
||||
*
|
||||
* @param workflowDefinition the definition to check
|
||||
* @param mimetype the mimetype of the definition
|
||||
* @return true => already deployed
|
||||
*/
|
||||
public boolean isDefinitionDeployed(InputStream workflowDefinition, String mimetype);
|
||||
|
||||
/**
|
||||
* Undeploy an exisiting Workflow Definition
|
||||
*
|
||||
|
194
source/java/org/alfresco/repo/workflow/WorkflowDeployer.java
Normal file
194
source/java/org/alfresco/repo/workflow/WorkflowDeployer.java
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco bootstrap Process deployment.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class WorkflowDeployer implements ApplicationListener
|
||||
{
|
||||
// Logging support
|
||||
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
|
||||
|
||||
// Workflow Definition Properties (used in setWorkflowDefinitions)
|
||||
public static final String ENGINE_ID = "engineId";
|
||||
public static final String LOCATION = "location";
|
||||
public static final String MIMETYPE = "mimetype";
|
||||
|
||||
// Dependencies
|
||||
private TransactionService transactionService;
|
||||
private WorkflowService workflowService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private List<Properties> workflowDefinitions;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the Transaction Service
|
||||
*
|
||||
* @param userTransaction the transaction service
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace service
|
||||
*
|
||||
* @param namespaceService the namespace service
|
||||
*/
|
||||
public void setWorkflowService(WorkflowService workflowService)
|
||||
{
|
||||
this.workflowService = workflowService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication component
|
||||
*
|
||||
* @param authenticationComponent
|
||||
*/
|
||||
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
|
||||
{
|
||||
this.authenticationComponent = authenticationComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Workflow Definitions
|
||||
*
|
||||
* @param workflowDefinitions
|
||||
*/
|
||||
public void setWorkflowDefinitions(List<Properties> workflowDefinitions)
|
||||
{
|
||||
this.workflowDefinitions = workflowDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy the Workflow Definitions
|
||||
*/
|
||||
public void deploy()
|
||||
{
|
||||
if (transactionService == null)
|
||||
{
|
||||
throw new ImporterException("Transaction Service must be provided");
|
||||
}
|
||||
if (authenticationComponent == null)
|
||||
{
|
||||
throw new ImporterException("Authentication Component must be provided");
|
||||
}
|
||||
if (workflowService == null)
|
||||
{
|
||||
throw new ImporterException("Workflow Service must be provided");
|
||||
}
|
||||
|
||||
UserTransaction userTransaction = transactionService.getUserTransaction();
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
try
|
||||
{
|
||||
userTransaction.begin();
|
||||
|
||||
// bootstrap the workflow definitions
|
||||
if (workflowDefinitions != null)
|
||||
{
|
||||
for (Properties workflowDefinition : workflowDefinitions)
|
||||
{
|
||||
// retrieve workflow specification
|
||||
String engineId = workflowDefinition.getProperty(ENGINE_ID);
|
||||
if (engineId == null || engineId.length() == 0)
|
||||
{
|
||||
throw new WorkflowException("Workflow Engine Id must be provided");
|
||||
}
|
||||
String location = workflowDefinition.getProperty(LOCATION);
|
||||
if (location == null || location.length() == 0)
|
||||
{
|
||||
throw new WorkflowException("Workflow definition location must be provided");
|
||||
}
|
||||
String mimetype = workflowDefinition.getProperty(MIMETYPE);
|
||||
|
||||
// retrieve input stream on workflow definition
|
||||
ClassPathResource workflowResource = new ClassPathResource(location);
|
||||
|
||||
// deploy workflow definition
|
||||
if (workflowService.isDefinitionDeployed(engineId, workflowResource.getInputStream(), mimetype))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Workflow deployer: Definition '" + location + "' already deployed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WorkflowDefinition def = workflowService.deployDefinition(engineId, workflowResource.getInputStream(), mimetype);
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("Workflow deployer: Deployed process definition '" + def.name + "' (version " + def.version + ") from '" + location + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userTransaction.commit();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {}
|
||||
try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {}
|
||||
throw new AlfrescoRuntimeException("Workflow deployment failed", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
deploy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -55,6 +56,24 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(java.lang.String, java.io.InputStream, java.lang.String)
|
||||
*/
|
||||
public WorkflowDefinition deployDefinition(String engineId, InputStream workflowDefinition, String mimetype)
|
||||
{
|
||||
WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
|
||||
return component.deployDefinition(workflowDefinition, mimetype);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#isDefinitionDeployed(java.lang.String, java.io.InputStream, java.lang.String)
|
||||
*/
|
||||
public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype)
|
||||
{
|
||||
WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
|
||||
return component.isDefinitionDeployed(workflowDefinition, mimetype);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@@ -67,10 +86,11 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.workflow.WorkflowService#undeployDefinition(java.lang.String)
|
||||
*/
|
||||
public void undeployDefinition(String processDefinitionId)
|
||||
public void undeployDefinition(String workflowDefinitionId)
|
||||
{
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
String engineId = BPMEngineRegistry.getEngineId(workflowDefinitionId);
|
||||
WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
|
||||
component.undeployDefinition(workflowDefinitionId);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -275,5 +295,5 @@ public class WorkflowServiceImpl implements WorkflowService
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -25,8 +26,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.BPMEngine;
|
||||
import org.alfresco.repo.workflow.TaskComponent;
|
||||
@@ -144,19 +147,90 @@ public class JBPMEngine extends BPMEngine
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#deployDefinition(java.io.InputStream)
|
||||
*/
|
||||
public WorkflowDefinition deployDefinition(InputStream workflowDefinition)
|
||||
public WorkflowDefinition deployDefinition(final InputStream workflowDefinition, final String mimetype)
|
||||
{
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
try
|
||||
{
|
||||
return (WorkflowDefinition)jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
// construct process definition
|
||||
ProcessDefinition def = createProcessDefinition(workflowDefinition, mimetype);
|
||||
|
||||
// deploy the parsed definition
|
||||
context.deployProcessDefinition(def);
|
||||
|
||||
// return deployed definition
|
||||
WorkflowDefinition workflowDef = createWorkflowDefinition(def);
|
||||
return workflowDef;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to deploy workflow definition", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#isDefinitionDeployed(java.io.InputStream, java.lang.String)
|
||||
*/
|
||||
public boolean isDefinitionDeployed(final InputStream workflowDefinition, final String mimetype)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Boolean) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Boolean doInJbpm(JbpmContext context)
|
||||
{
|
||||
// create process definition from input stream
|
||||
ProcessDefinition processDefinition = createProcessDefinition(workflowDefinition, mimetype);
|
||||
|
||||
// retrieve process definition from Alfresco Repository
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition existingDefinition = graphSession.findLatestProcessDefinition(processDefinition.getName());
|
||||
return (existingDefinition == null) ? false : true;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to determine if workflow definition is already deployed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#undeployDefinition(java.lang.String)
|
||||
*/
|
||||
public void undeployDefinition(String workflowDefinitionId)
|
||||
public void undeployDefinition(final String workflowDefinitionId)
|
||||
{
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
try
|
||||
{
|
||||
jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
// retrieve process definition
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDefinition = graphSession.loadProcessDefinition(getJbpmId(workflowDefinitionId));
|
||||
// NOTE: if not found, should throw an exception
|
||||
|
||||
// undeploy
|
||||
// NOTE: jBPM deletes all "in-flight" processes too
|
||||
// TODO: Determine if there's a safer undeploy we can expose via the WorkflowService contract
|
||||
graphSession.deleteProcessDefinition(processDefinition);
|
||||
|
||||
// we're done
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to deploy workflow definition", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -674,6 +748,58 @@ public class JBPMEngine extends BPMEngine
|
||||
// Helpers...
|
||||
//
|
||||
|
||||
/**
|
||||
* Construct a Process Definition from the provided Process Definition stream
|
||||
*
|
||||
* @param workflowDefinition stream to create process definition from
|
||||
* @param mimetype mimetype of stream
|
||||
* @return process definition
|
||||
*/
|
||||
protected ProcessDefinition createProcessDefinition(InputStream definitionStream, String mimetype)
|
||||
{
|
||||
String actualMimetype = (mimetype == null) ? MimetypeMap.MIMETYPE_ZIP : mimetype;
|
||||
ProcessDefinition def = null;
|
||||
|
||||
// parse process definition from jBPM process archive file
|
||||
|
||||
if (actualMimetype.equals(MimetypeMap.MIMETYPE_ZIP))
|
||||
{
|
||||
ZipInputStream zipInputStream = null;
|
||||
try
|
||||
{
|
||||
zipInputStream = new ZipInputStream(definitionStream);
|
||||
def = ProcessDefinition.parseParZipInputStream(zipInputStream);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new JbpmException("Failed to parse process definition from jBPM zip archive stream", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (zipInputStream != null)
|
||||
{
|
||||
try { zipInputStream.close(); } catch(IOException e) {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse process definition from jBPM xml file
|
||||
|
||||
else if (actualMimetype.equals(MimetypeMap.MIMETYPE_XML))
|
||||
{
|
||||
try
|
||||
{
|
||||
def = ProcessDefinition.parseXmlInputStream(definitionStream);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new JbpmException("Failed to parse process definition from jBPM xml stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Task definition of the specified Task
|
||||
*
|
||||
@@ -1013,11 +1139,14 @@ public class JBPMEngine extends BPMEngine
|
||||
// TODO: Is there a formal way of determing if task node?
|
||||
workflowNode.isTaskNode = workflowNode.type.equals("TaskNode");
|
||||
List transitions = node.getLeavingTransitions();
|
||||
workflowNode.transitions = new String[transitions.size()];
|
||||
int i = 0;
|
||||
for (Transition transition : (List<Transition>)transitions)
|
||||
workflowNode.transitions = new String[(transitions == null) ? 0 : transitions.size()];
|
||||
if (transitions != null)
|
||||
{
|
||||
workflowNode.transitions[i++] = transition.getName();
|
||||
int i = 0;
|
||||
for (Transition transition : (List<Transition>)transitions)
|
||||
{
|
||||
workflowNode.transitions[i++] = transition.getName();
|
||||
}
|
||||
}
|
||||
return workflowNode;
|
||||
}
|
||||
@@ -1047,6 +1176,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
WorkflowDefinition workflowDef = new WorkflowDefinition();
|
||||
workflowDef.id = createGlobalId(new Long(definition.getId()).toString());
|
||||
workflowDef.version = new Integer(definition.getVersion()).toString();
|
||||
workflowDef.name = definition.getName();
|
||||
Task startTask = definition.getTaskMgmtDefinition().getStartTask();
|
||||
if (startTask != null)
|
||||
|
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.repo.workflow.TaskComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowComponent;
|
||||
@@ -39,6 +40,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,6 +53,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
WorkflowDefinitionComponent workflowDefinitionComponent;
|
||||
WorkflowComponent workflowComponent;
|
||||
TaskComponent taskComponent;
|
||||
WorkflowDefinition testWorkflowDef;
|
||||
|
||||
|
||||
//@Override
|
||||
@@ -60,6 +63,15 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
workflowDefinitionComponent = registry.getWorkflowDefinitionComponent("jbpm");
|
||||
workflowComponent = registry.getWorkflowComponent("jbpm");
|
||||
taskComponent = registry.getTaskComponent("jbpm");
|
||||
|
||||
// deploy test process definition
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
|
||||
assertFalse(workflowDefinitionComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
testWorkflowDef = workflowDefinitionComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("Test", testWorkflowDef.name);
|
||||
assertEquals("1", testWorkflowDef.version);
|
||||
assertTrue(workflowDefinitionComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +83,16 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
|
||||
public void testDeployWorkflow() throws Exception
|
||||
{
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
|
||||
testWorkflowDef = workflowDefinitionComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("Test", testWorkflowDef.name);
|
||||
assertEquals("2", testWorkflowDef.version);
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflow()
|
||||
{
|
||||
try
|
||||
@@ -321,16 +343,7 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
*/
|
||||
private WorkflowDefinition getTestDefinition()
|
||||
{
|
||||
List<WorkflowDefinition> workflowDefs = workflowDefinitionComponent.getDefinitions();
|
||||
for (WorkflowDefinition workflowDef : workflowDefs)
|
||||
{
|
||||
if (workflowDef.name.equals("Review and Approve"))
|
||||
{
|
||||
return workflowDef;
|
||||
}
|
||||
}
|
||||
fail("Test Workflow Definition not found");
|
||||
return null;
|
||||
return testWorkflowDef;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="Review and Approve">
|
||||
<swimlane name="Initiator"></swimlane>
|
||||
<start-state name="start">
|
||||
<task name="Submit" swimlane="Initiator" blocking="true">
|
||||
<controller>
|
||||
<variable name="reviewer" access="write,required" />
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="Review"></transition>
|
||||
<transition name="end" to="end"></transition>
|
||||
</start-state>
|
||||
<swimlane name="Reviewer">
|
||||
<assignment actor-id="#{reviewer}"></assignment>
|
||||
</swimlane>
|
||||
<task-node name="Review">
|
||||
<task name="Review" duedate="1 business day" blocking="true" swimlane="Reviewer">
|
||||
<controller>
|
||||
<variable name="comment" access="read,write,required"></variable>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="reject" to="Rejected"></transition>
|
||||
<transition name="approve" to="Approved"></transition>
|
||||
</task-node>
|
||||
<task-node name="Rejected">
|
||||
<task name="Rejected" swimlane="Initiator">
|
||||
<controller>
|
||||
<variable name="comment" access="read"></variable>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"></transition>
|
||||
</task-node>
|
||||
<task-node name="Approved">
|
||||
<task name="Approved" swimlane="Initiator">
|
||||
<controller>
|
||||
<variable name="comment" access="read"></variable>
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="end"></transition>
|
||||
</task-node>
|
||||
<end-state name="end"></end-state>
|
||||
</process-definition>
|
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="Review and Approve">
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="Test">
|
||||
<swimlane name="Initiator"></swimlane>
|
||||
<start-state name="start">
|
||||
<task name="Submit" swimlane="Initiator" blocking="true">
|
||||
<task name="Submit" swimlane="Initiator">
|
||||
<controller>
|
||||
<variable name="reviewer" access="write,required" />
|
||||
</controller>
|
||||
|
Reference in New Issue
Block a user