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

@@ -120,6 +120,20 @@
</property> </property>
</bean> </bean>
<!-- Workflow Deployment -->
<bean id="workflowBootstrap" parent="workflowDeployer">
<property name="workflowDefinitions">
<list>
<props>
<prop key="engineId">jbpm</prop>
<prop key="location">org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml</prop>
<prop key="mimetype">text/xml</prop>
</props>
</list>
</property>
</bean>
<!-- Descriptor Service --> <!-- Descriptor Service -->
<bean id="descriptorComponent" class="org.alfresco.repo.descriptor.DescriptorServiceImpl"> <bean id="descriptorComponent" class="org.alfresco.repo.descriptor.DescriptorServiceImpl">

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<model name="wf:workflowsmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Content-oriented Workflows Model</description>
<author>Alfresco</author>
<version>0.1</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/workflow/1.0" prefix="wf"/>
</namespaces>
<types>
<!-- -->
<!-- Basic Review & Approve Tasks -->
<!-- -->
<type name="wf:submitReviewTask">
<title>Submit Review Task</title>
<parent>bpm:workflowTask</parent>
<properties>
<property name="wf:reviewDueDate">
<title>Review Due Date</title>
<type>d:date</type>
</property>
</properties>
<associations>
<association name="wf:reviewers">
<title>Reviewers</title>
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:person</class>
<mandatory>true</mandatory>
<many>false</many>
</target>
</association>
</associations>
</type>
</types>
</model>

View File

@@ -4,17 +4,24 @@
<beans> <beans>
<!-- --> <!-- -->
<!-- Workflow Model --> <!-- Workflow Definitions -->
<!-- --> <!-- -->
<bean id="workflow.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap"> <bean id="workflow.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models"> <property name="models">
<list> <list>
<value>alfresco/model/bpmModel.xml</value> <value>alfresco/model/bpmModel.xml</value>
<value>alfresco/model/workflowModel.xml</value>
</list> </list>
</property> </property>
</bean> </bean>
<bean id="workflowDeployer" class="org.alfresco.repo.workflow.WorkflowDeployer" abstract="true">
<property name="transactionService" ref="transactionComponent"/>
<property name="authenticationComponent" ref="authenticationComponent" />
<property name="workflowService" ref="WorkflowService" />
</bean>
<!-- --> <!-- -->
<!-- Workflow Service Implementation --> <!-- Workflow Service Implementation -->
<!-- --> <!-- -->
@@ -41,11 +48,6 @@
<bean id="jbpm_configuration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean"> <bean id="jbpm_configuration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/> <property name="sessionFactory" ref="sessionFactory"/>
<property name="configuration" value="classpath:org/jbpm/default.jbpm.cfg.xml"/> <property name="configuration" value="classpath:org/jbpm/default.jbpm.cfg.xml"/>
<property name="processDefinitions">
<list>
<ref local="jbpm_testWorkflow"/>
</list>
</property>
</bean> </bean>
<bean id="jbpm_template" class="org.springmodules.workflow.jbpm31.JbpmTemplate"> <bean id="jbpm_template" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
@@ -57,11 +59,8 @@
<property name="JBPMTemplate" ref="jbpm_template"/> <property name="JBPMTemplate" ref="jbpm_template"/>
<property name="dictionaryService" ref="DictionaryService"/> <property name="dictionaryService" ref="DictionaryService"/>
<property name="namespaceService" ref="NamespaceService"/> <property name="namespaceService" ref="NamespaceService"/>
</bean> <property name="nodeService" ref="nodeService"/>
<property name="personService" ref="personService"/>
<!-- TODO: Remove this - for short-term testing only -->
<bean id="jbpm_testWorkflow" class="org.springmodules.workflow.jbpm31.definition.ProcessDefinitionFactoryBean">
<property name="definitionLocation" value="classpath:org/alfresco/repo/workflow/jbpm/test_processdefinition.xml"/>
</bean> </bean>
</beans> </beans>

View File

@@ -57,6 +57,7 @@ public class MimetypeMap implements MimetypeService
public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg"; public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg";
public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb"; public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb";
public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript"; public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript";
public static final String MIMETYPE_ZIP = "application/zip";
// Open Document // Open Document
public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text"; public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template"; public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template";

View File

@@ -34,9 +34,22 @@ public interface WorkflowDefinitionComponent
* Deploy a Workflow Definition * Deploy a Workflow Definition
* *
* @param workflowDefinition the content object containing the definition * @param workflowDefinition the content object containing the definition
* @param mimetype (optional) the mime type of the workflow definition
* @return 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 * Undeploy an exisiting Workflow Definition

View 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();
}
}
}

View File

@@ -16,6 +16,7 @@
*/ */
package org.alfresco.repo.workflow; package org.alfresco.repo.workflow;
import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; 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) /* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(org.alfresco.service.cmr.repository.NodeRef) * @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) /* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#undeployDefinition(java.lang.String) * @see org.alfresco.service.cmr.workflow.WorkflowService#undeployDefinition(java.lang.String)
*/ */
public void undeployDefinition(String processDefinitionId) public void undeployDefinition(String workflowDefinitionId)
{ {
// TODO String engineId = BPMEngineRegistry.getEngineId(workflowDefinitionId);
throw new UnsupportedOperationException(); WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
component.undeployDefinition(workflowDefinitionId);
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@@ -16,6 +16,7 @@
*/ */
package org.alfresco.repo.workflow.jbpm; package org.alfresco.repo.workflow.jbpm;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
@@ -25,8 +26,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.zip.ZipInputStream;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.BPMEngine; import org.alfresco.repo.workflow.BPMEngine;
import org.alfresco.repo.workflow.TaskComponent; import org.alfresco.repo.workflow.TaskComponent;
@@ -144,19 +147,90 @@ public class JBPMEngine extends BPMEngine
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#deployDefinition(java.io.InputStream) * @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 try
throw new UnsupportedOperationException(); {
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) /* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#undeployDefinition(java.lang.String) * @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#undeployDefinition(java.lang.String)
*/ */
public void undeployDefinition(String workflowDefinitionId) public void undeployDefinition(final String workflowDefinitionId)
{ {
// TODO try
throw new UnsupportedOperationException(); {
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) /* (non-Javadoc)
@@ -674,6 +748,58 @@ public class JBPMEngine extends BPMEngine
// Helpers... // 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 * Gets the Task definition of the specified Task
* *
@@ -1013,12 +1139,15 @@ public class JBPMEngine extends BPMEngine
// TODO: Is there a formal way of determing if task node? // TODO: Is there a formal way of determing if task node?
workflowNode.isTaskNode = workflowNode.type.equals("TaskNode"); workflowNode.isTaskNode = workflowNode.type.equals("TaskNode");
List transitions = node.getLeavingTransitions(); List transitions = node.getLeavingTransitions();
workflowNode.transitions = new String[transitions.size()]; workflowNode.transitions = new String[(transitions == null) ? 0 : transitions.size()];
if (transitions != null)
{
int i = 0; int i = 0;
for (Transition transition : (List<Transition>)transitions) for (Transition transition : (List<Transition>)transitions)
{ {
workflowNode.transitions[i++] = transition.getName(); workflowNode.transitions[i++] = transition.getName();
} }
}
return workflowNode; return workflowNode;
} }
@@ -1047,6 +1176,7 @@ public class JBPMEngine extends BPMEngine
{ {
WorkflowDefinition workflowDef = new WorkflowDefinition(); WorkflowDefinition workflowDef = new WorkflowDefinition();
workflowDef.id = createGlobalId(new Long(definition.getId()).toString()); workflowDef.id = createGlobalId(new Long(definition.getId()).toString());
workflowDef.version = new Integer(definition.getVersion()).toString();
workflowDef.name = definition.getName(); workflowDef.name = definition.getName();
Task startTask = definition.getTaskMgmtDefinition().getStartTask(); Task startTask = definition.getTaskMgmtDefinition().getStartTask();
if (startTask != null) if (startTask != null)

View File

@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.workflow.BPMEngineRegistry; import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.alfresco.repo.workflow.TaskComponent; import org.alfresco.repo.workflow.TaskComponent;
import org.alfresco.repo.workflow.WorkflowComponent; 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.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest; import org.alfresco.util.BaseSpringTest;
import org.springframework.core.io.ClassPathResource;
/** /**
@@ -51,6 +53,7 @@ public class JBPMEngineTest extends BaseSpringTest
WorkflowDefinitionComponent workflowDefinitionComponent; WorkflowDefinitionComponent workflowDefinitionComponent;
WorkflowComponent workflowComponent; WorkflowComponent workflowComponent;
TaskComponent taskComponent; TaskComponent taskComponent;
WorkflowDefinition testWorkflowDef;
//@Override //@Override
@@ -60,6 +63,15 @@ public class JBPMEngineTest extends BaseSpringTest
workflowDefinitionComponent = registry.getWorkflowDefinitionComponent("jbpm"); workflowDefinitionComponent = registry.getWorkflowDefinitionComponent("jbpm");
workflowComponent = registry.getWorkflowComponent("jbpm"); workflowComponent = registry.getWorkflowComponent("jbpm");
taskComponent = registry.getTaskComponent("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() public void testStartWorkflow()
{ {
try try
@@ -321,16 +343,7 @@ public class JBPMEngineTest extends BaseSpringTest
*/ */
private WorkflowDefinition getTestDefinition() private WorkflowDefinition getTestDefinition()
{ {
List<WorkflowDefinition> workflowDefs = workflowDefinitionComponent.getDefinitions(); return testWorkflowDef;
for (WorkflowDefinition workflowDef : workflowDefs)
{
if (workflowDef.name.equals("Review and Approve"))
{
return workflowDef;
}
}
fail("Test Workflow Definition not found");
return null;
} }
} }

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"?> <?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> <swimlane name="Initiator"></swimlane>
<start-state name="start"> <start-state name="start">
<task name="Submit" swimlane="Initiator" blocking="true"> <task name="Submit" swimlane="Initiator">
<controller> <controller>
<variable name="reviewer" access="write,required" /> <variable name="reviewer" access="write,required" />
</controller> </controller>

View File

@@ -27,6 +27,9 @@ public class WorkflowDefinition
/** Workflow Definition unique id */ /** Workflow Definition unique id */
public String id; public String id;
/** Workflow Definition version */
public String version;
/** Workflow Definition name */ /** Workflow Definition name */
public String name; public String name;
@@ -39,6 +42,6 @@ public class WorkflowDefinition
*/ */
public String toString() public String toString()
{ {
return "WorkflowDefinition[id=" + id + ",name=" + name + ",startTask=" + startTaskDefinition.toString() + "]"; return "WorkflowDefinition[id=" + id + ",version=" + version + ",name=" + name + ",startTask=" + startTaskDefinition.toString() + "]";
} }
} }

View File

@@ -16,6 +16,7 @@
*/ */
package org.alfresco.service.cmr.workflow; package org.alfresco.service.cmr.workflow;
import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -37,6 +38,29 @@ public interface WorkflowService
// Workflow Definition Management // Workflow Definition Management
// //
/**
* Deploy a Workflow Definition to the Alfresco Repository
*
* @param engineId the bpm engine id
* @param workflowDefinition the workflow definition
* @param overwrite true => redeploy, if process definition already exists
* @return mimetype the mimetype of the workflow definition
*/
public WorkflowDefinition deployDefinition(String engineId, 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 engineId the bpm engine id
* @param workflowDefinition the definition to check
* @param mimetype the mimetype of the definition
* @return true => already deployed
*/
public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype);
/** /**
* Deploy a Workflow Definition to the Alfresco Repository * Deploy a Workflow Definition to the Alfresco Repository
* *