Diagrammatically representing the steps in a workflow
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-23-2009 03:10 AM
Hi,
We have a requirement where in say we have a workflow which has five steps to it. Each of the steps of the workflow needs to be represented diagrammatically. Say we at the start of the workflow there should be some pointer which indicates we are in the first step and as we move on the pointer would indicate which step we are at.
Has anyone come across such thing or implemented one/
Thanks.
We have a requirement where in say we have a workflow which has five steps to it. Each of the steps of the workflow needs to be represented diagrammatically. Say we at the start of the workflow there should be some pointer which indicates we are in the first step and as we move on the pointer would indicate which step we are at.
Has anyone come across such thing or implemented one/
Thanks.
Labels:
- Labels:
-
Archive
8 REPLIES 8

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-23-2009 07:41 AM
There is such a feature in Alfresco, but I think it's not effective.
Easiest way to do this, is for you to create 5 image files, representing each state of the diagram you want to display, and bind each image file to each task Type as a property (in your workflowModel). Then, edit the web-client-config-custom.xml so that each task form will display the image file in the format you need.
Easiest way to do this, is for you to create 5 image files, representing each state of the diagram you want to display, and bind each image file to each task Type as a property (in your workflowModel). Then, edit the web-client-config-custom.xml so that each task form will display the image file in the format you need.
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-29-2009 04:33 AM
I'm currently following the Alfresco 3 Enterprise Content Management Implementation by Munwar Sheriff. It contans a sample workflow model as follows:
Now say if wanted to add an image as a property here what would the type that i would have to use. I checked the Data Dictionary and could find the type any only suitable, which corresponds to java.lang.object.
Could you please help out as to how i could bind the image here as a property?
<type name="global:reviewTask"> <parent>bpm:startTask</parent> <properties> <property name="global:nurse_id"> <title>Nurse No.</title> <type>d:int</type> </property>….
Now say if wanted to add an image as a property here what would the type that i would have to use. I checked the Data Dictionary and could find the type any only suitable, which corresponds to java.lang.object.
Could you please help out as to how i could bind the image here as a property?

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-29-2009 05:45 AM
you could indeed choose the d:any datatype.
when you enter this task of the workflow, run a java action that will populate this property with the suitable file.
In the java class WorkflowActionManageFiles execute() method, find your image file (either in the repository , like in the data dictionary,… or in the file system etc …), and assign it to the property, using :
executionContext.setVariable("global:nurse_id", File);
when you enter this task of the workflow, run a java action that will populate this property with the suitable file.
<task-node name="ReviewTask"> <task name="global:reviewTask" swimlane="toto"> <event type="task-create"> <action class="org.alfresco.yourpackage.bpm.actions.WorkflowActionManageFiles" /> </event> </task> <transition name="" to="next_task" /> </task-node>
In the java class WorkflowActionManageFiles execute() method, find your image file (either in the repository , like in the data dictionary,… or in the file system etc …), and assign it to the property, using :
executionContext.setVariable("global:nurse_id", File);
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-30-2009 03:42 AM
Is it actually possible to do that in the Serve Side Javascript code.
Something like this:
where my workflowcontentmodel file looks like
and part of the web-client-custom-config.xml looks like:
I've tried using this but it just displays me the label "Workflow Status Image" and a text box besides it.
If this way is not correct could you plet me know which class i should extend to create my custom action. Also if you have any links for the same that would be great.
I get this error log:
Thanks.
Something like this:
<task-node name="review"> <event type="node-enter"> <script>System.out.println("———- Node Enter of Content review Task ————");</script> </event> <task name="ppdwf:contentReviewerTask" swimlane="content_reviewer" /> <event type="task-create"> <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <script> System.out.println("———-Inside task create of ppdwf:contentReviewerTask ————"); var imageFile=companyhome.childByNamePath("WorkflowImage/Step1.png"); executionContext.setVariable("ppdwf_wfstatusimage",imageFile); </script> </action> </event>…
where my workflowcontentmodel file looks like
<types> <type name="ppdwf:baseTask"> <parent>bpm:workflowTask</parent> <properties> <property name="ppdwf:wfstatusimage"> <title>WorkFlow Status Image</title> <type>d:any</type> <mandatory>true</mandatory> </property> </properties> </type> <type name="ppdwf:privilegedBaseTask"> <parent>ppdwf:baseTask</parent> </type> <type name="ppdwf:contentAuthorTask"> <parent>ppdwf:privilegedBaseTask</parent> </type>…
and part of the web-client-custom-config.xml looks like:
<config evaluator="node-type" condition="ppdwf:contentAuthorTask" replace="true">- <property-sheet> <show-property name="bpm:taskId" /> <show-property name="bpm:description" component-generator="TextAreaGenerator" read-only="true" /> <show-property name="bpm:dueDate" read-only="true" /> <show-property name="bpm:priority" read-only="true" /> <show-property name="bpm:status" /> <show-property name="ppdwf:wfstatusimage" display-label="Workflow Status Image" /> <show-property name="bpm:comment" component-generator="TextAreaGenerator" /> </property-sheet> </config>
I've tried using this but it just displays me the label "Workflow Status Image" and a text box besides it.
If this way is not correct could you plet me know which class i should extend to create my custom action. Also if you have any links for the same that would be great.
I get this error log:
Caused by: org.alfresco.scripts.ScriptException: Failed to execute supplied script: couldn't serialize 'Node Type: {http://www.alfresco.org/model/content/1.0
}content, Node Aspects: [{http://www.alfresco.org/model/content/1.0}author, {http://www.alfresco.org/model/content/1.0}titled, {http://www.alfresco.org/model
/system/1.0}referenceable, {http://www.alfresco.org/model/content/1.0}auditable]'
at org.alfresco.repo.jscript.RhinoScriptProcessor.executeString(RhinoScriptProcessor.java:254)
at org.alfresco.repo.processor.ScriptServiceImpl.executeScriptString(ScriptServiceImpl.java:314)
at org.alfresco.repo.processor.ScriptServiceImpl.executeScriptString(ScriptServiceImpl.java:292)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor.invoke(AlwaysProceedMethodInterceptor.java:40)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:49)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.alfresco.repo.audit.AuditComponentImpl.audit(AuditComponentImpl.java:275)
at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:69)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy152.executeScriptString(Unknown Source)
at org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript.executeScript(AlfrescoJavaScript.java:178)
at org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript.execute(AlfrescoJavaScript.java:132)
at org.jbpm.graph.def.Action.execute(Action.java:122)
at org.jbpm.graph.def.GraphElement.executeAction(GraphElement.java:264)
… 101 more
Caused by: org.jbpm.JbpmException: couldn't serialize 'Node Type: {http://www.alfresco.org/model/content/1.0}content, Node Aspects: [{http://www.alfresco.org
/model/content/1.0}author, {http://www.alfresco.org/model/content/1.0}titled, {http://www.alfresco.org/model/system/1.0}referenceable, {http://www.alfresco.o
rg/model/content/1.0}auditable]'
at org.jbpm.context.exe.converter.SerializableToByteArrayConverter.convert(SerializableToByteArrayConverter.java:53)
at org.jbpm.context.exe.VariableInstance.setValue(VariableInstance.java:131)
at org.jbpm.context.exe.VariableInstance.create(VariableInstance.java:74)
at org.jbpm.context.exe.VariableContainer.setVariableLocally(VariableContainer.java:173)
at org.jbpm.context.exe.VariableContainer.setVariable(VariableContainer.java:45)
at org.jbpm.context.exe.VariableContainer.setVariable(VariableContainer.java:49)
at org.jbpm.graph.exe.ExecutionContext.setVariable(ExecutionContext.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:155)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:243)
at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3237)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2394)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:162)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:393)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:2834)
at org.mozilla.javascript.InterpretedFunction.exec(InterpretedFunction.java:173)
at org.alfresco.repo.jscript.RhinoScriptProcessor.executeScriptImpl(RhinoScriptProcessor.java:449)
at org.alfresco.repo.jscript.RhinoScriptProcessor.executeString(RhinoScriptProcessor.java:250)
… 125 more
Caused by: java.io.NotSerializableException: org.springframework.beans.factory.support.DefaultListableBeanFactory
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1108)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:324)
at org.springframework.transaction.interceptor.TransactionInterceptor.writeObject(TransactionInterceptor.java:186)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:972)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1426)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1338)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1102)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1462)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1377)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:324)
at org.jbpm.context.exe.converter.SerializableToByteArrayConverter.convert(SerializableToByteArrayConverter.java:49)
… 145 more
Thanks.

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-30-2009 04:25 AM
1/ in your web-client-config-custom.xml, you would have to specify a "component-generator". Indeed, the way you did things, Alfresco just knows that the property is of type "any", but then it does not know how to display it.
2/ By the way, I don't think I gave you the best way to do it. The error you have makes me think that you cannot provide a File object to the execution context, because it is not serializable.
So, I think we have to be tricky there. Instead of storing the file, let's store its location.
then :
- the property type becomes => d:text
- if the various image files are on the file server, provide the location to the property via the executionContext, if they are in Alfresco (for example, in the Data dictionary), provide their nodeRef.
- at last, in your web-client-config-custom.xml, you'll have to specify a custom component-generator to tell Alfresco not to simply display the text, but to fine the image file thanks to its location (or Noderef), and display it.
Look for "component generators" in the wiki.
As for the display, you'll have plenty of choices (just display the image in a div, convert it to swf and user the swf viewer etc…)
Hope this helps
2/ By the way, I don't think I gave you the best way to do it. The error you have makes me think that you cannot provide a File object to the execution context, because it is not serializable.
So, I think we have to be tricky there. Instead of storing the file, let's store its location.
then :
- the property type becomes => d:text
- if the various image files are on the file server, provide the location to the property via the executionContext, if they are in Alfresco (for example, in the Data dictionary), provide their nodeRef.
- at last, in your web-client-config-custom.xml, you'll have to specify a custom component-generator to tell Alfresco not to simply display the text, but to fine the image file thanks to its location (or Noderef), and display it.
Look for "component generators" in the wiki.
As for the display, you'll have plenty of choices (just display the image in a div, convert it to swf and user the swf viewer etc…)
Hope this helps
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-30-2009 10:42 AM
Thanks a lot for the steps. I'm able to get the workflow images in my tasks now. I'm writing the code here for anyone who might want a similar thing.
Actually The Alfresco Developer Guide book has an example of creating custom generators which was really helpful. Page 170 "Step-by-Step: Changing the Status Field on the Details Page to Display as a Stoplight Indicator" has the details for anyone whos interested.
part of the processdefinition file:
faces-config-custom
WorkflowImageDisplayRenderer.java
WorkFlowImageGenerator
WorkflowModel
web-client-custom-config
Now coming to my question, rt now i am taking my images from file system and referencing that in my renderer code. Say if i want to refer the images from some DataDictionary | WorkFlowImages space how should i give that.
Would something like work :
Thanks.
Actually The Alfresco Developer Guide book has an example of creating custom generators which was really helpful. Page 170 "Step-by-Step: Changing the Status Field on the Details Page to Display as a Stoplight Indicator" has the details for anyone whos interested.
part of the processdefinition file:
<task-node name="review"> <event type="node-enter"> <script>System.out.println("———- Node Enter of Content review Task ————");</script> </event> <task name="ppdwf:contentReviewerTask" swimlane="content_reviewer" /> <event type="task-create"> <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <script> executionContext.setVariable("ppdwf_wfstatusimage","/alfresco/images/workflowimages/Step1.png"); </script> </action> </event>
faces-config-custom
<managed-bean> <description>Bean that generates a stoplight control to display status</description> <managed-bean-name>WorkFlowImageGenerator</managed-bean-name> <managed-bean-class> org.alfresco.web.bean.generator.WorkFlowImageGenerator </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <render-kit> <renderer> <component-family>javax.faces.Output</component-family> <renderer-type>org.alfresco.faces.WorkflowImageDisplayRenderer</renderer-type> <renderer-class>org.alfresco.web.ui.extension.renderer.WorkflowImageDisplayRenderer</renderer-class> </renderer> </render-kit>
WorkflowImageDisplayRenderer.java
package org.alfresco.web.ui.extension.renderer;import java.io.IOException;import javax.faces.component.UIComponent;import javax.faces.component.ValueHolder;import javax.faces.context.FacesContext;import javax.faces.context.ResponseWriter;import org.alfresco.web.ui.common.Utils;import org.alfresco.web.ui.common.renderer.BaseRenderer;public class WorkflowImageDisplayRenderer extends BaseRenderer { public boolean isMultiple(UIComponent component) { return false; } public boolean getRendersChildren() { return false; } public void encodeEnd(FacesContext context, UIComponent component) throws IOException { if (component.isRendered() == false) return; ResponseWriter out = context.getResponseWriter(); // render the field if(isMultiple(component)) { out.write(Utils.encode("Multiple value property fields are not supported.")); } else { //Get the image URL present in the property. String workflowImageRef = (String)((ValueHolder)component).getValue(); // display workflow status image tag out.write("<div>"); out.write("<img src=\"" + workflowImageRef + "\" alt=\"" + workflowImageRef + "\"/>"); out.write("</div>"); } } public void decode(FacesContext context, UIComponent component) { if (Utils.isComponentDisabledOrReadOnly(component)) { return; } }}
WorkFlowImageGenerator
package org.alfresco.web.bean.generator;import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import org.alfresco.web.app.servlet.FacesHelper;import org.alfresco.web.ui.common.ComponentConstants;import org.alfresco.web.ui.repo.component.property.PropertySheetItem;import org.alfresco.web.ui.repo.component.property.UIProperty;import org.alfresco.web.ui.repo.component.property.UIPropertySheet;public class WorkFlowImageGenerator extends TextFieldGenerator { public static final String WORKFLOW_IMAGE_STATUS_RENDERER = "org.alfresco.faces.WorkflowImageDisplayRenderer"; @Override public UIComponent generate(FacesContext context, String id) { UIComponent component = context.getApplication().createComponent(ComponentConstants.JAVAX_FACES_OUTPUT); component.setRendererType(WORKFLOW_IMAGE_STATUS_RENDERER); FacesHelper.setupComponentId(context, component, id); return component; } @Override @SuppressWarnings("unchecked") protected UIComponent createComponent(FacesContext context, UIPropertySheet propertySheet, PropertySheetItem item) { UIComponent component = null; if (item instanceof UIProperty) { //Call the generate method to invoke the renderer to paint the workflow image. component = generate(context, item.getName()); } return component; }}
WorkflowModel
<type name="ppdwf:baseTask"> <parent>bpm:workflowTask</parent> <properties> <property name="ppdwf:wfstatusimage"> <title>WorkFlow Status Image</title> <type>d:text</type> </property> </properties> </type>
web-client-custom-config
<config evaluator="node-type" condition="ppdwf:contentReviewerTask" replace="true"> <property-sheet> <show-property name="bpm:status" /> <show-property name="bpm:comment" component-generator="TextAreaGenerator" /> <show-property name="ppdwf:wfstatusimage" display-label="Workflow Status Image" component-generator="WorkFlowImageGenerator" /> </property-sheet> </config>
Now coming to my question, rt now i am taking my images from file system and referencing that in my renderer code. Say if i want to refer the images from some DataDictionary | WorkFlowImages space how should i give that.
Would something like work :
executionContext.setVariable("ppdwf_wfstatusimage",companyhome.childByNamePath("DataDictionary/WorkFlowImages/Step1.png"););
Thanks.

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-30-2009 12:15 PM
I think you'd rather deal with the nodeRef of the file.
Then, push the Noderef in the executionContext (it might need to be serialized into a String), and adapt your java classes to use the Noderef instead of the location.
Glad it worked for you !
var imageFile = companyhome.childByNamePath("/Data Dictionary/WorkflowImages/yourImage.png");var nodeRef = imageFile.nodeRef;
Then, push the Noderef in the executionContext (it might need to be serialized into a String), and adapt your java classes to use the Noderef instead of the location.
Glad it worked for you !

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-02-2009 05:07 AM
I tried with the nodeRef however i'm not sure how can i link the nodeRef to the image src. I got nodeRef something like: workspace://SpacesStore/a460d52b-3111-47d4-b007-e0b4bf909979
So for the time being i got the value from url property:
and in the java code:
Thanks.
So for the time being i got the value from url property:
var workflowImageNode = companyhome.childByNamePath("WokflowImage/Step3.PNG");var workflowImageNodeURL = workflowImageNode.url;executionContext.setVariable("ppdwf_wfstatusimage",workflowImageNodeURL);
and in the java code:
/Get the image URL present in the property.String workflowImageRefFromComp = (String)((ValueHolder)component).getValue();//Append the host and context.String workflowImageRef = "http://" + context.getExternalContext().getRequestHeaderMap().get("host") + context.getExternalContext().getRequestContextPath() + workflowImageRefFromComp;// display workflow status image tagout.write("<div>");out.write("<img src=\"" + workflowImageRef + "\" alt=\"" + workflowImageRef + "\"/>");out.write("</div>");
Thanks.
