Workflow:

1) Add access to process definition warnings in workflow service deploy method
2) Fix nasty little bug found by Gav where jBPM beanshell access to Alfresco Node failed as it expected slightly different object types to those expected by Alfresco Javascript access to Node.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3542 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2006-08-17 19:04:38 +00:00
parent 46acb964cc
commit c3875d0d36
10 changed files with 169 additions and 56 deletions

View File

@@ -5,7 +5,7 @@
wf_review.workflow.title=Review & Approve
wf_review.workflow.description=Send documents for approval
wf_review.node.start.title=Start
wf_review.node.start.transition.review.title=Review
wf_review.node.review.title=Review
wf_review.node.start.transition.review=Review
wf_review.task.wf_submitReviewTask.title=Review
wf_workflowmodel.type.wf_submitReviewTask.title=Review

View File

@@ -74,7 +74,7 @@ import org.springframework.util.StringUtils;
*
* @author Kevin Roast
*/
public final class Node implements Serializable, Scopeable
public class Node implements Serializable, Scopeable
{
private static Log logger = LogFactory.getLog(Node.class);
@@ -155,7 +155,6 @@ public final class Node implements Serializable, Scopeable
this.nodeService = services.getNodeService();
this.imageResolver = resolver;
this.scope = scope;
this.converter = new NodeValueConverter();
}
/**
@@ -405,7 +404,8 @@ public final class Node implements Serializable, Scopeable
Serializable propValue = props.get(qname);
// perform the conversion to a script safe value and store
this.properties.put(qname.toString(), converter.convertValueForScript(qname, propValue));
this.properties.put(qname.toString(), getValueConverter().convertValueForScript(qname, propValue));
}
}
@@ -898,7 +898,7 @@ public final class Node implements Serializable, Scopeable
Serializable value = (Serializable)this.properties.get(key);
// perform the conversion from script wrapper object to repo serializable values
value = converter.convertValueForRepo(value);
value = getValueConverter().convertValueForRepo(value);
props.put(createQName(key), value);
}
@@ -1209,7 +1209,7 @@ public final class Node implements Serializable, Scopeable
{
// get the value out for the specified key - make sure it is Serializable
Object value = props.get((String)propId, props);
value = converter.convertValueForRepo((Serializable)value);
value = getValueConverter().convertValueForRepo((Serializable)value);
aspectProps.put(createQName((String)propId), (Serializable)value);
}
}
@@ -1636,11 +1636,36 @@ public final class Node implements Serializable, Scopeable
// ------------------------------------------------------------------------------
// Value Conversion
/**
* Gets the node value converter
*
* @return the node value converter
*/
protected NodeValueConverter getValueConverter()
{
if (converter == null)
{
converter = createValueConverter();
}
return converter;
}
/**
* Constructs the node value converter
*
* @return the node value converter
*/
protected NodeValueConverter createValueConverter()
{
return new NodeValueConverter();
}
/**
* Value converter with knowledge of Node specific value types
*/
private final class NodeValueConverter extends ValueConverter
public class NodeValueConverter extends ValueConverter
{
/**
* Convert an object from any repository serialized value to a valid script object.

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowTask;
@@ -46,9 +47,9 @@ public interface WorkflowComponent
*
* @param workflowDefinition the content object containing the definition
* @param mimetype (optional) the mime type of the workflow definition
* @return workflow definition
* @return workflow deployment descriptor
*/
public WorkflowDefinition deployDefinition(InputStream workflowDefinition, String mimetype);
public WorkflowDeployment deployDefinition(InputStream workflowDefinition, String mimetype);
/**
* Is the specified Workflow Definition already deployed?

View File

@@ -24,7 +24,7 @@ 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.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.transaction.TransactionService;
@@ -148,17 +148,13 @@ public class WorkflowDeployer implements ApplicationListener
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);
WorkflowDeployment deployment = workflowService.deployDefinition(engineId, workflowResource.getInputStream(), mimetype);
if (logger.isInfoEnabled())
{
logger.info("Workflow deployer: Deployed process definition '" + def.title + "' (version " + def.version + ") from '" + location + "'");
}
logger.info("Workflow deployer: Deployed process definition '" + deployment.definition.title + "' (version " + deployment.definition.version + ") from '" + location + "' with " + deployment.problems.length + " problems");
}
}
}

View File

@@ -25,6 +25,7 @@ import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
@@ -32,6 +33,8 @@ import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
@@ -42,6 +45,10 @@ import org.alfresco.service.namespace.QName;
*/
public class WorkflowServiceImpl implements WorkflowService
{
// Logging support
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
// Dependent services
private BPMEngineRegistry registry;
private WorkflowPackageComponent workflowPackageComponent;
@@ -70,10 +77,20 @@ 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)
public WorkflowDeployment deployDefinition(String engineId, InputStream workflowDefinition, String mimetype)
{
WorkflowComponent component = getWorkflowComponent(engineId);
return component.deployDefinition(workflowDefinition, mimetype);
WorkflowDeployment deployment = component.deployDefinition(workflowDefinition, mimetype);
if (logger.isDebugEnabled() && deployment.problems.length > 0)
{
for (String problem : deployment.problems)
{
logger.debug("Workflow definition '" + deployment.definition.title + "' problem: " + problem);
}
}
return deployment;
}
/* (non-Javadoc)
@@ -88,7 +105,7 @@ public class WorkflowServiceImpl implements WorkflowService
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(org.alfresco.service.cmr.repository.NodeRef)
*/
public WorkflowDefinition deployDefinition(NodeRef definitionContent)
public WorkflowDeployment deployDefinition(NodeRef definitionContent)
{
// TODO
throw new UnsupportedOperationException();

View File

@@ -46,6 +46,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowNode;
@@ -68,11 +69,15 @@ import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.jpdl.par.ProcessArchive;
import org.jbpm.jpdl.xml.JpdlXmlReader;
import org.jbpm.jpdl.xml.Problem;
import org.jbpm.taskmgmt.def.Task;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.springframework.util.StringUtils;
import org.springmodules.workflow.jbpm31.JbpmCallback;
import org.springmodules.workflow.jbpm31.JbpmTemplate;
import org.xml.sax.InputSource;
/**
@@ -178,23 +183,23 @@ public class JBPMEngine extends BPMEngine
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#deployDefinition(java.io.InputStream)
*/
public WorkflowDefinition deployDefinition(final InputStream workflowDefinition, final String mimetype)
public WorkflowDeployment deployDefinition(final InputStream workflowDefinition, final String mimetype)
{
try
{
return (WorkflowDefinition)jbpmTemplate.execute(new JbpmCallback()
return (WorkflowDeployment)jbpmTemplate.execute(new JbpmCallback()
{
public Object doInJbpm(JbpmContext context)
{
// construct process definition
ProcessDefinition def = createProcessDefinition(workflowDefinition, mimetype);
CompiledProcessDefinition compiledDef = compileProcessDefinition(workflowDefinition, mimetype);
// deploy the parsed definition
context.deployProcessDefinition(def);
context.deployProcessDefinition(compiledDef.def);
// return deployed definition
WorkflowDefinition workflowDef = createWorkflowDefinition(def);
return workflowDef;
WorkflowDeployment workflowDeployment = createWorkflowDeployment(compiledDef);
return workflowDeployment;
}
});
}
@@ -217,11 +222,11 @@ public class JBPMEngine extends BPMEngine
public Boolean doInJbpm(JbpmContext context)
{
// create process definition from input stream
ProcessDefinition processDefinition = createProcessDefinition(workflowDefinition, mimetype);
CompiledProcessDefinition processDefinition = compileProcessDefinition(workflowDefinition, mimetype);
// retrieve process definition from Alfresco Repository
GraphSession graphSession = context.getGraphSession();
ProcessDefinition existingDefinition = graphSession.findLatestProcessDefinition(processDefinition.getName());
ProcessDefinition existingDefinition = graphSession.findLatestProcessDefinition(processDefinition.def.getName());
return (existingDefinition == null) ? false : true;
}
});
@@ -828,6 +833,53 @@ public class JBPMEngine extends BPMEngine
// Helpers...
//
/**
* Process Definition with accompanying problems
*/
private static class CompiledProcessDefinition
{
public CompiledProcessDefinition(ProcessDefinition def, List<Problem> problems)
{
this.def = def;
this.problems = new String[problems.size()];
int i = 0;
for (Problem problem : problems)
{
this.problems[i++] = problem.toString();
}
}
protected ProcessDefinition def;
protected String[] problems;
}
/**
* JpdlXmlReader with access to problems encountered during compile.
*
* @author davidc
*/
private static class JBPMEngineJpdlXmlReader extends JpdlXmlReader
{
private static final long serialVersionUID = -753730152120696221L;
public JBPMEngineJpdlXmlReader(InputStream inputStream)
{
super(new InputSource(inputStream));
}
/**
* Gets the problems
*
* @return problems
*/
public List getProblems()
{
return problems;
}
}
/**
* Construct a Process Definition from the provided Process Definition stream
*
@@ -835,10 +887,11 @@ public class JBPMEngine extends BPMEngine
* @param mimetype mimetype of stream
* @return process definition
*/
protected ProcessDefinition createProcessDefinition(InputStream definitionStream, String mimetype)
@SuppressWarnings("unchecked")
protected CompiledProcessDefinition compileProcessDefinition(InputStream definitionStream, String mimetype)
{
String actualMimetype = (mimetype == null) ? MimetypeMap.MIMETYPE_ZIP : mimetype;
ProcessDefinition def = null;
CompiledProcessDefinition compiledDef = null;
// parse process definition from jBPM process archive file
@@ -848,7 +901,9 @@ public class JBPMEngine extends BPMEngine
try
{
zipInputStream = new ZipInputStream(definitionStream);
def = ProcessDefinition.parseParZipInputStream(zipInputStream);
ProcessArchive reader = new ProcessArchive(zipInputStream);
ProcessDefinition def = reader.parseProcessDefinition();
compiledDef = new CompiledProcessDefinition(def, reader.getProblems());
}
catch(Exception e)
{
@@ -869,7 +924,9 @@ public class JBPMEngine extends BPMEngine
{
try
{
def = ProcessDefinition.parseXmlInputStream(definitionStream);
JBPMEngineJpdlXmlReader jpdlReader = new JBPMEngineJpdlXmlReader(definitionStream);
ProcessDefinition def = jpdlReader.readProcessDefinition();
compiledDef = new CompiledProcessDefinition(def, jpdlReader.getProblems());
}
catch(Exception e)
{
@@ -877,7 +934,7 @@ public class JBPMEngine extends BPMEngine
}
}
return def;
return compiledDef;
}
/**
@@ -1152,12 +1209,13 @@ public class JBPMEngine extends BPMEngine
String name = key.toPrefixString(this.namespaceService);
if (value instanceof NodeRef)
{
value = new org.alfresco.repo.jscript.Node((NodeRef)value, serviceRegistry, null);
value = new JBPMNode((NodeRef)value, serviceRegistry);
}
instance.setVariableLocally(name, value);
}
}
/**
* Convert a list of Alfresco Authorities to a list of authority Names
*
@@ -1391,6 +1449,20 @@ public class JBPMEngine extends BPMEngine
return taskDef;
}
/**
* Creates a Workflow Deployment
*
* @param compiledDef compiled JBPM process definition
* @return workflow deployment
*/
protected WorkflowDeployment createWorkflowDeployment(CompiledProcessDefinition compiledDef)
{
WorkflowDeployment deployment = new WorkflowDeployment();
deployment.definition = createWorkflowDefinition(compiledDef.def);
deployment.problems = compiledDef.problems;
return deployment;
}
/**
* Get the Workflow Task State for the specified JBoss JBPM Task
*

View File

@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
@@ -72,7 +73,8 @@ public class JBPMEngineTest extends BaseSpringTest
// deploy test process definition
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
testWorkflowDef = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
testWorkflowDef = deployment.definition;
assertNotNull(testWorkflowDef);
assertEquals("Test", testWorkflowDef.title);
assertEquals("1", testWorkflowDef.version);
@@ -95,7 +97,8 @@ public class JBPMEngineTest extends BaseSpringTest
public void testDeployWorkflow() throws Exception
{
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml");
testWorkflowDef = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
testWorkflowDef = deployment.definition;
assertNotNull(testWorkflowDef);
assertEquals("Test", testWorkflowDef.title);
assertEquals("2", testWorkflowDef.version);

View File

@@ -16,7 +16,6 @@
*/
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.jscript.Node;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.jbpm.context.exe.Converter;
@@ -46,7 +45,7 @@ public class NodeConverter implements Converter
{
return true;
}
return (value.getClass() == Node.class);
return (value.getClass() == JBPMNode.class);
}
/* (non-Javadoc)
@@ -57,7 +56,7 @@ public class NodeConverter implements Converter
Object converted = null;
if (o != null)
{
converted = ((Node)o).getNodeRef().toString();
converted = ((JBPMNode)o).getNodeRef().toString();
}
return converted;
}
@@ -72,7 +71,7 @@ public class NodeConverter implements Converter
{
BeanFactoryReference factory = jbpmFactoryLocator.useBeanFactory(null);
ServiceRegistry serviceRegistry = (ServiceRegistry)factory.getFactory().getBean(ServiceRegistry.SERVICE_REGISTRY);
reverted = new Node(new NodeRef((String)o), serviceRegistry, null);
reverted = new JBPMNode(new NodeRef((String)o), serviceRegistry);
}
return reverted;
}

View File

@@ -123,7 +123,7 @@
<jbpm-type>
<matcher>
<bean class="org.jbpm.context.exe.matcher.ClassNameMatcher">
<field name="className"><string value="org.alfresco.repo.jscript.Node" /></field>
<field name="className"><string value="org.alfresco.repo.workflow.jbpm.JBPMNode" /></field>
</bean>
</matcher>
<converter class="org.alfresco.repo.workflow.jbpm.NodeConverter" />

View File

@@ -43,10 +43,21 @@ public interface WorkflowService
*
* @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
* @param mimetype the mimetype of the workflow definition
* @return workflow deployment descriptor
*/
public WorkflowDefinition deployDefinition(String engineId, InputStream workflowDefinition, String mimetype);
public WorkflowDeployment deployDefinition(String engineId, InputStream workflowDefinition, String mimetype);
/**
* Deploy a Workflow Definition to the Alfresco Repository
*
* Note: The specified content object must be of type bpm:workflowdefinition.
* This type describes for which BPM engine the definition is appropriate.
*
* @param workflowDefinition the content object containing the definition
* @return workflow deployment descriptor
*/
public WorkflowDeployment deployDefinition(NodeRef workflowDefinition);
/**
* Is the specified Workflow Definition already deployed?
@@ -61,17 +72,6 @@ public interface WorkflowService
*/
public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype);
/**
* Deploy a Workflow Definition to the Alfresco Repository
*
* Note: The specified content object must be of type bpm:workflowdefinition.
* This type describes for which BPM engine the definition is appropriate.
*
* @param workflowDefinition the content object containing the definition
* @return workflow definition
*/
public WorkflowDefinition deployDefinition(NodeRef workflowDefinition);
/**
* Undeploy an exisiting Workflow Definition
*