11-15-2007 11:50 AM
var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "jbpm$wf:my_workflow";
workflow.parameters["bpm:workflowDescription"] = document.name;
workflow.parameters["bpm:assignee"] = person;
workflow.execute(document);
But I need to add many documents to the workflow task automatically, so I need to do this in Java (facility is not available in JavaScript API, see my post a few days ago http://forums.alfresco.com/viewtopic.php?t=9584). But I'm completely stuck. I've tried the above JavaScript and then running the SDK TaggingSample Java example, but this does nothing once the workflow is started. i.e. I can run either action but not both. Hence I think I need the one Java action to:12-10-2007 04:34 AM
package org.alfresco.sample;
import java.io.File;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
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.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
public class TagActionExecuter extends ActionExecuterAbstractBase {
/** The name of the action */
public static final String PARAM_ASPECT_NAME = "aspect-name";
public static final String PARAM_WORKFLOW_NAME = "workflowName";
public static final String PARAM_END_START_TASK = "endStartTask";
public static final String PARAM_START_TASK_TRANSITION = "startTaskTransition";
public static final String JBPM_WORKFLOW_NAME = "jbpm$mywf:my_digitalpostbox_workflow";
public static final String HOME_DIGITAL_POST_BOX = "Digital Post Box";
public static final String UPLOAD_FOLDER_NAME = "Upload Area";
public static final String UPLOAD_FOLDER_LOCATION = "C:\\alfresco-examples\\";
/** Length of a day in ms. */
public static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
/** Jobs will be due in 2 days. */
public static final Date DUE_HOURS = new Date(2 * DAY_IN_MILLIS);
/** The node service */
private NodeService nodeService;
/** The workflow service*/
private WorkflowService workflowService;
/** The content service*/
private ContentService contentService;
private static boolean DEBUG = true;
/**
* Saves typing System.out.println everywhere (I hate typing 😉
*/
private static void pl(String str) {
if (DEBUG) System.out.println(str);
}
/**
* Saves typing System.out.print everywhere (I hate typing 😉
*/
private static void p(String str) {
if (DEBUG) System.out.print(str);
}
/**
* On startup creates a NodeService handle.
* @param nodeService
*/
public void setNodeService(NodeService nodeService) {
pl("—– setNodeService");
this.nodeService = nodeService;
}
/**
* On startup creates a WorkflowService handle.
* @param workflowService
*/
public void setWorkflowService(WorkflowService workflowService) {
pl("—– setWorkflowService");
this.workflowService = workflowService;
}
/**
* On startup creates a ContentService handle.
* @param contentService
*/
public void setContentService(ContentService contentService) {
pl("—– setContentService");
this.contentService = contentService;
}
/*
* public void setContentService(FileFolderService fileFolderService) {
* System.out.output("—– setFileFolderService"); this.fileFolderService =
* fileFolderService; }
*/
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
pl("—– addParameterDefinitions");
// Specify the parameters
paramList.add(new ParameterDefinitionImpl(PARAM_WORKFLOW_NAME, DataTypeDefinition.TEXT, false,
getParamDisplayLabel(PARAM_WORKFLOW_NAME)));
paramList.add(new ParameterDefinitionImpl(PARAM_END_START_TASK, DataTypeDefinition.BOOLEAN, false,
getParamDisplayLabel(PARAM_END_START_TASK)));
paramList.add(new ParameterDefinitionImpl(PARAM_START_TASK_TRANSITION, DataTypeDefinition.TEXT, false,
getParamDisplayLabel(PARAM_START_TASK_TRANSITION)));
}
/**
* Convert fileName to a mime type.
* @param fileName extension is used to determine which mimetype to return.
* @return Mimetype, one of MimetypeMap.MIMETYPE_PDF etc.
*/
private String getMimeTypeFromStr(String fileName) {
String fileNameLC = fileName.toLowerCase();
if (fileNameLC.endsWith(".pdf")) {
return MimetypeMap.MIMETYPE_PDF;
} else if (fileNameLC.endsWith(".ai")) {
return MimetypeMap.MIMETYPE_BINARY;
} else if (fileNameLC.endsWith(".indd")) {
return MimetypeMap.MIMETYPE_BINARY;
} else if (fileNameLC.endsWith(".fh5")) {
return MimetypeMap.MIMETYPE_BINARY;
} else if (fileNameLC.endsWith(".gif")) {
return MimetypeMap.MIMETYPE_IMAGE_GIF;
} else if (fileNameLC.endsWith(".png")) {
return MimetypeMap.MIMETYPE_IMAGE_PNG;
} else if (fileNameLC.endsWith(".jpg")) {
return MimetypeMap.MIMETYPE_IMAGE_JPEG;
} else if (fileNameLC.endsWith(".eps")) {
return MimetypeMap.MIMETYPE_BINARY;
} else if (fileNameLC.endsWith(".txt")) {
return MimetypeMap.MIMETYPE_TEXT_PLAIN;
} else if (fileNameLC.endsWith(".xml")) {
return MimetypeMap.MIMETYPE_XML;
} else {
return MimetypeMap.MIMETYPE_BINARY;
}
}
/**
* Upload a file into the stores into Company Home|folderName|fileName
* @param storeRef ref of stores.
* @param fileName File to upload.
* @return NodeRef to the stored item.
*/
public NodeRef createFile(StoreRef storeRef, String fileName) {
// Get the Company Home node from which to hang the next level of nodes.
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
List<ChildAssociationRef> rootChildren = nodeService.getChildAssocs(rootNodeRef);
int nbRootChildren = rootChildren.size();
int iRootChild;
NodeRef rootChild = null;
NodeRef companyHomeNode = null;
String nodeId;
for (iRootChild = 0; iRootChild < nbRootChildren; iRootChild++) {
rootChild = rootChildren.get(iRootChild).getChildRef();
nodeId = rootChild.getId();
Serializable prop = nodeService.getProperty(rootChild, ContentModel.PROP_NAME);
pl(fileName + " : " + prop.toString() + " = " + nodeId);
if ("Company Home".equals(prop.toString()) || HOME_DIGITAL_POST_BOX.equals(prop.toString())) {
companyHomeNode = rootChild;
break;
}
}
if (companyHomeNode == null) {
pl(fileName + " : Company home is null");
return null;
}
pl(fileName + " : Company home = " + rootChild.toString());
// Search for filderName and create it if necessary.
String folderName = UPLOAD_FOLDER_NAME;
NodeRef folderRef = nodeService.getChildByName(companyHomeNode, ContentModel.ASSOC_CONTAINS, folderName);
Map<QName, Serializable> nodeProperties = new HashMap<QName, Serializable>(7);
if (folderRef == null) {
pl(fileName + " : Cannot find folder : " + folderName);
return null;
}
pl(fileName + " : Folder " + folderName + " = " + folderRef.toString());
// Create a file.
nodeProperties.clear();
nodeProperties.put(ContentModel.PROP_NAME, fileName);
ChildAssociationRef assocRef = nodeService.createNode(folderRef, ContentModel.ASSOC_CONTAINS, QName.createQName(
NamespaceService.CONTENT_MODEL_PREFIX, QName.createValidLocalName(fileName)),
ContentModel.TYPE_CONTENT, nodeProperties);
NodeRef fileRef = assocRef.getChildRef();
pl(fileName + " : Create a file " + fileName);
// Upload the files contents.
ContentWriter writer = contentService.getWriter(fileRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(getMimeTypeFromStr(fileName));
writer.setEncoding("UTF-8");
File iFile = new File(UPLOAD_FOLDER_LOCATION + fileName);
writer.putContent(iFile);
pl(fileName + " : Added content to " + fileName);
return fileRef;
}
@Override
protected void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
pl("————————————————————————");
pl("—– Starting Action");
pl("ruleAction.getId() = " + ruleAction.getId());
pl("ruleAction.toString() = " + ruleAction.toString());
pl("ruleAction.getCreator() = " + ruleAction.getCreator());
pl("ruleAction.getDesc() = " + ruleAction.getDescription());
pl("ruleAction.getTitle() = " + ruleAction.getTitle());
// List of the properties of the actionedUponNodeRef
Map<QName, Serializable> propmap = nodeService.getProperties(actionedUponNodeRef);
int mapsize = propmap.size();
Iterator<Entry<QName, Serializable>> keyValuePairs1 = propmap.entrySet().iterator();
for (int i = 0; i < mapsize; i++) {
Map.Entry<QName, Serializable> entry = keyValuePairs1.next();
pl("Prop key/val = " + entry.getKey().toString() + " : " + entry.getValue().toString());
}
pl("—– Get content of current node.");
ContentReader readerCurNode = this.contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
if (readerCurNode != null) {
String contentString = readerCurNode.getContentString();
pl("readerCurNode.toString() " + readerCurNode.toString());
String[] fileList = contentString.split("\\n");
for (int x = 0; x < fileList.length; x++) {
fileList[x] = fileList[x].trim();
pl("Line " + x + " = " + fileList[x]);
}
pl("—– Updating contents of the file.");
ContentWriter writer = contentService.getWriter(actionedUponNodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
String oString = "";
// Build up the contents to place in the file (cannot add a line at a time).
for (int x = 0; x < fileList.length; x++) {
oString += "Read file: " + fileList[x] + "\n";
}
p(oString);
writer.putContent(oString);
StoreRef storeRef = actionedUponNodeRef.getStoreRef();
NodeRef rootNode = this.nodeService.getRootNode(storeRef);
pl("—– Add all of the files to alfresco.");
pl("storeRef.toString = " + storeRef.toString());
pl("storeRef.getIdentifier = " + storeRef.getIdentifier());
pl("Root node String = " + rootNode.toString());
pl("Root node Id = " + rootNode.getId());
pl("Adding " + fileList.length + " files to alfresco");
NodeRef[] fileRefs = new NodeRef[fileList.length];
for (int x = 0; x < fileList.length; x++) {
fileRefs[x] = createFile(storeRef, fileList[x]);
}
pl("—– Create workflow.");
// Get a list of workflow definitions and search through them for the one we want.
List<WorkflowDefinition> workflowDefs = workflowService.getDefinitions();
Iterator<WorkflowDefinition> workflowDefsIterator = workflowDefs.iterator();
WorkflowDefinition workflowDef = null;
// Get a handle to the required workflow.
while (workflowDefsIterator.hasNext()) {
workflowDef = workflowDefsIterator.next();
if (workflowDef.name.equals(JBPM_WORKFLOW_NAME)) {
break;
}
}
// If we did not find the workflow error.
if (!workflowDef.name.equals(JBPM_WORKFLOW_NAME)) {
pl("Unable to find jBPM workflow : " + JBPM_WORKFLOW_NAME);
return;
}
// All OK so print out some information.
pl("Found jBPM workflow : " + JBPM_WORKFLOW_NAME);
pl("Name = " + workflowDef.name);
pl("Description = " + workflowDef.description);
pl("Id = " + workflowDef.id);
pl("Title = " + workflowDef.title);
pl("Version = " + workflowDef.version);
pl("—– Add all of the files.");
// Add the files to the workflow.
NodeRef workflowNodeRef = workflowService.createPackage(null);
for (int x = 0; x < fileList.length; x++) {
nodeService.addChild(workflowNodeRef, fileRefs[x], ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "Advert within the workflow package"));
}
// Finally kick the workflow off.
pl("—– Start workflow");
pl("Get full path and figure out the studio and team from this.");
String fullPath = nodeService.getPath(actionedUponNodeRef).toDisplayPath(nodeService);
pl("NAME = " + fullPath);
String[] result = fullPath.split("/");
for (int x=0; x<result.length; x++)
pl("Item[" + x + "] = " + result[x]);
// Set the due date.
Date dueDate = new Date(System.currentTimeMillis() + DUE_HOURS.getTime());
pl("Due date = now + " + (DUE_HOURS.getTime() / DAY_IN_MILLIS) + "days (" + dueDate.toString() + ")");
// To get the parameters passed to the action.
Map<String, Serializable> pars = ruleAction.getParameterValues();
pl("pars string = " + pars.toString());
Set<String> keys = pars.keySet();
Iterator<String> i = keys.iterator();
while(i.hasNext()) {
pl("pars key = " + i.next());
}
pl("ruleAction.getActionDefinitionName = " + ruleAction.getActionDefinitionName());
pl("ruleAction.getTitle = " + ruleAction.getTitle());
// Get a list of properties.
Map<QName, Serializable> m = this.nodeService.getProperties(actionedUponNodeRef);
pl("m.toString() = " + m.toString());
Set<QName> mKeys = m.keySet();
Iterator<QName> mI = mKeys.iterator();
while(mI.hasNext()) {
pl("pars key = " + mI.next());
}
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
parameters.put(WorkflowModel.ASSOC_PACKAGE, workflowNodeRef);
parameters.put(WorkflowModel.ASSOC_ASSIGNEE, "admin");
parameters.put(WorkflowModel.PROP_DUE_DATE, dueDate);
parameters.put(WorkflowModel.PROP_DESCRIPTION, "My description….");
parameters.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate);
parameters.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "My workflow description….");
WorkflowPath path = workflowService.startWorkflow(workflowDef.id, parameters);
pl("Path.toString = " + path.toString());
pl("Path.id = " + path.id);
pl("Path.active = " + (path.active ? "true" : "false"));
StoreRef workflowStoreRef = workflowNodeRef.getStoreRef();
pl("workflowStoreRef.toString = " + workflowStoreRef.toString());
WorkflowTaskDefinition taskDef = workflowDef.getStartTaskDefinition();
TypeDefinition td = taskDef.metadata;
pl("td.getDescription = " + td.getDescription());
pl("td.getName = " + td.getName());
pl("—– Ending Action");
pl("————————————————————————");
}
}
}
05-07-2008 01:40 AM
05-07-2008 03:10 AM
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="mywf:my_migration_workflow">
<!– ======================================================================= –>
<!– Deploy to localhost 8080 /alfresco/jbpm/deployprocess –>
<!– Swimlanes for the different users the advert may touch. –>
<swimlane name="artistsPool">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<pooledactors>#{people.getGroup(mywf_assigneeInfo)}</pooledactors>
</assignment>
</swimlane>
<swimlane name="artist">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<actor>#{mywf_artist}</actor>
</assignment>
</swimlane>
<!– Need this for initial start task. From then on it belongs to an artist or reader. –>
<swimlane name="initiator">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<actor>#{bpm_assignee}</actor>
</assignment>
</swimlane>
<!– ======================================================================= –>
<!– States the job goes through. –>
<start-state name="Start">
<task name="mywf:allocateToStudioTask" swimlane="initiator"/>
<transition name="Send to Artists" to="Waiting for Artist">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
<variable name="mywf_assigneeInfo" access="write" />
<expression>
mylog.info(person.properties.userName + " started " + mywf_orderNum);
mywf_assigneeInfo = "GROUP_" + mywf_studio + "-" + mywf_team + "-Artists";
</expression>
</script>
</action>
</transition>
</start-state>
<task-node name="Waiting for Artist">
<task name="mywf:waitingForArtistTask" swimlane="artistsPool" />
<transition name="Work this advert" to="Create">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
<variable name="mywf_artist" access="write" />
<expression>
var workDate = new Date();
var logLine = workDate.getFullYear() + "-" + utils.pad(workDate.getMonth()+1,2) + "-" + utils.pad(workDate.getDate(),2);
logLine += " " + utils.pad(workDate.getHours(),2) + ":" + utils.pad(workDate.getMinutes(),2) + ":" + utils.pad(workDate.getSeconds(),2);
logLine += " : Artist Working Advert ";
logLine += "(" + mywf_orderNum;
logLine += ", " + person.properties.userName;
logLine += ", " + mywf_studio;
logLine += ", " + mywf_team + ")\r\n";
var nodeParent = companyhome.childByNamePath("Completed");
var fileName = mywf_orderNum + ".log";
var logFile = nodeParent.childByNamePath(fileName);
if (logFile == null) {
logFile = nodeParent.createFile(fileName);
}
if (logFile != null) {
logFile.content += logLine;
}
mylog.info(person.properties.userName + " working " + mywf_orderNum);
mywf_artist = person.properties.userName;
</expression>
</script>
</action>
</transition>
</task-node>
<task-node name="Create">
<task name="mywf:createTask" swimlane="artist" />
<transition name="Complete Job" to="Approved">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
<expression>
var completedHome = companyhome.childByNamePath("Completed");
var completeDate = new Date();
var jobSpace = mywf_orderNum + "_" + completeDate.getFullYear() + utils.pad(completeDate.getMonth()+1,2) + utils.pad(completeDate.getDate(),2);
jobSpace += "_" + utils.pad(completeDate.getHours(),2) + utils.pad(completeDate.getMinutes(),2) + utils.pad(completeDate.getSeconds(),2);
var completedSpace = completedHome.createFolder(jobSpace);
var doneFileContents = jobSpace + "\r\n";
doneFileContents += mywf_orderNum + ".log\r\n";
doneFileContents += mywf_orderNum + ".xml\r\n";
doneFileContents += mywf_orderNum + "_import.txt\r\n";
for (var i = 0; i < bpm_package.children.length; i++) {
bpm_package.children[i].move(completedSpace);
doneFileContents += bpm_package.children[i].name + "\r\n";
}
var jobFile = companyhome.childByNamePath(mywf_studio + "/" + mywf_team + "/" + mywf_orderNum + "_import.txt");
if (jobFile != null) {
jobFile.move(completedSpace);
var completeLine = completeDate.getFullYear() + "-" + utils.pad(completeDate.getMonth()+1,2) + "-" + utils.pad(completeDate.getDate(),2);
completeLine += " " + utils.pad(completeDate.getHours(),2) + ":" + utils.pad(completeDate.getMinutes(),2) + ":" + utils.pad(completeDate.getSeconds(),2);
completeLine += " : Artist Completed Advert ";
completeLine += "(" + mywf_orderNum;
completeLine += ", " + person.properties.userName;
completeLine += ", " + mywf_studio;
completeLine += ", " + mywf_team + ")\r\n";
var completeFileName = mywf_orderNum + ".log";
var completeFile = completedHome.childByNamePath(completeFileName);
if (completeFile == null) {
completeFile = completedHome.createFile(completeFileName);
}
if (completeFile != null) {
completeFile.content += completeLine;
completeFile.move(completedSpace);
var xmlFileName = mywf_orderNum + ".xml";
var uploadAreaSpace = companyhome.childByNamePath("UploadArea");
if (uploadAreaSpace == null) {
mylog.error("Unable to move completed files for " + mywf_orderNum);
} else {
var xmlFile = uploadAreaSpace.childByNamePath(xmlFileName);
if (xmlFile == null) {
mylog.error("Unable to move completed files for " + mywf_orderNum);
} else {
xmlFile.move(completedSpace);
var triggerFileName = mywf_orderNum + "_export.txt";
var triggerFile = completedSpace.childByNamePath(triggerFileName);
if (triggerFile == null) {
triggerFile = completedHome.createFile(triggerFileName);
}
if (triggerFile == null) {
mylog.error("Unable to move completed files for " + mywf_orderNum);
} else {
triggerFile.content += doneFileContents;
triggerFile.move(completedSpace);
mylog.info(person.properties.userName + " completed " + mywf_orderNum + " : Into folder Completed/" + jobSpace);
}
}
}
}
}
</expression>
</script>
</action>
</transition>
</task-node>
<end-state name="Approved" />
<!– ======================================================================= –>
</process-definition>
05-14-2008 02:55 PM
Tags
Find what you came for
We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.