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:
David Caruana
2006-08-09 23:37:06 +00:00
parent d24a815b79
commit 17a40c3e51
13 changed files with 552 additions and 39 deletions

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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>