user8125535
user8125535

Reputation:

How can I update custom properties in alfresco workflow task using only Java?

First, I want to say thanks to everyone that took their time to help me figure this out because I was searching for more than a week for a solution to my problem. Here it is:

My goal is to start a custom workflow in Alfresco Community 5.2 and to set some custom properties in the first task trough a web script using only the Public Java API. My class is extending AbstractWebScript. Currently I have success with starting the workflow and setting properties like bpm:workflowDescription, but I'm not able to set my custom properties in the tasks.

Here is the code:

    public class StartWorkflow extends AbstractWebScript {
    /**
     * The Alfresco Service Registry that gives access to all public content services in Alfresco.
     */
    private ServiceRegistry serviceRegistry;

    public void setServiceRegistry(ServiceRegistry serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
    }

    @Override
    public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {       

        // Create JSON object for the response
        JSONObject obj = new JSONObject();

        try {                        
            // Check if parameter defName is present in the request            
            String wfDefFromReq = req.getParameter("defName");
            if (wfDefFromReq == null) {
                obj.put("resultCode", "1 (Error)");
                obj.put("errorMessage", "Parameter defName not found.");
                return;      
            }            
            // Get the WFL Service
            WorkflowService workflowService = serviceRegistry.getWorkflowService();
            // Build WFL Definition name
            String wfDefName = "activiti$" + wfDefFromReq;
            // Get WorkflowDefinition object
            WorkflowDefinition wfDef = workflowService.getDefinitionByName(wfDefName);
            // Check if such WorkflowDefinition exists
            if (wfDef == null) {
                obj.put("resultCode", "1 (Error)");
                obj.put("errorMessage", "No workflow definition found for defName = " + wfDefName);
                return;
            }                       

            // Get parameters from the request
            Content reqContent = req.getContent();
            if (reqContent == null) {
                throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing request body.");
            }
            String content;
            content = reqContent.getContent();

            if (content.isEmpty()) {
                throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Content is empty");
            }

            JSONTokener jsonTokener = new JSONTokener(content);
            JSONObject json = new JSONObject(jsonTokener);           

            // Set the workflow description
            Map<QName, Serializable> params = new HashMap();
            params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Workflow started from JAVA API");          

            // Start the workflow
            WorkflowPath wfPath = workflowService.startWorkflow(wfDef.getId(), params);

            // Get params from the POST request
            Map<QName, Serializable> reqParams = new HashMap();
            Iterator<String> i = json.keys();
            while (i.hasNext()) {
                String paramName = i.next();
                QName qName = QName.createQName(paramName);
                String value = json.getString(qName.getLocalName());
                reqParams.put(qName, value);  
            }

            // Try to update the task properties

            // Get the next active task which contains the properties to update
            WorkflowTask wfTask = workflowService.getTasksForWorkflowPath(wfPath.getId()).get(0);
            // Update properties
            WorkflowTask updatedTask = workflowService.updateTask(wfTask.getId(), reqParams, null, null);

            obj.put("resultCode", "0 (Success)");
            obj.put("workflowId", wfPath.getId());

        } catch (JSONException e) {
            throw new WebScriptException(Status.STATUS_BAD_REQUEST, 
                    e.getLocalizedMessage());
        } catch (IOException ioe) {
            throw new WebScriptException(Status.STATUS_BAD_REQUEST, 
                    "Error when parsing the request.", 
                    ioe);
        } finally {
            // build a JSON string and send it back
            String jsonString = obj.toString();
            res.getWriter().write(jsonString);
        }

    }  
}

Here is how I call the webscript:

curl -v -uadmin:admin -X POST -d @postParams.json localhost:8080/alfresco/s/workflow/startJava?defName=nameOfTheWFLDefinition -H "Content-Type:application/json"

In postParams.json file I have the required pairs for property/value which I need to update:

{
"cmprop:propOne" : "Value 1",
"cmprop:propTwo" : "Value 2",
"cmprop:propThree" : "Value 3"

}

The workflow is started, bpm:workflowDescription is set correctly, but the properties in the task are not visible to be set.

I made a JS script which I call when the workflow is started:

execution.setVariable('bpm_workflowDescription', 'Some String ' + execution.getVariable('cmprop:propOne'));

And actually the value for cmprop:propOne is used and the description is properly updated - which means that those properties are updated somewhere (on execution level maybe?) but I cannot figure out why they are not visible when I open the task.

I had success with starting the workflow and updating the properties using the JavaScript API with:

if (wfdef) {

        // Get the params
        wfparams = {};
        if (jsonRequest) {
            for ( var prop in jsonRequest) {
                wfparams[prop] = jsonRequest[prop];
            }
        }

        wfpackage = workflow.createPackage();

        wfpath = wfdef.startWorkflow(wfpackage, wfparams);

The problem is that I only want to use the public Java API, please help. Thanks!

Upvotes: 0

Views: 1474

Answers (2)

Ben Chevallereau
Ben Chevallereau

Reputation: 439

Usually, I just try to import all tasks for my custom model prefix. So for you, it should look like that:

import java.util.Set;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.apache.log4j.Logger;

public class ImportVariables extends AbstractTaskListener {

    private Logger logger = Logger.getLogger(ImportVariables.class);

    @Override
    public void notify(DelegateTask task) {

        logger.debug("Inside ImportVariables.notify()");
        logger.debug("Task ID:" + task.getId());
        logger.debug("Task name:" + task.getName());
        logger.debug("Task proc ID:" + task.getProcessInstanceId());
        logger.debug("Task def key:" + task.getTaskDefinitionKey());

        DelegateExecution execution = task.getExecution();

        Set<String> executionVariables = execution.getVariableNamesLocal();
        for (String variableName : executionVariables) {
            // If the variable starts by "cmprop_"
            if (variableName.startsWith("cmprop_")) {
                // Publish it at the task level
                task.setVariableLocal(variableName, execution.getVariableLocal(variableName));
            }
        }
    }

}

Upvotes: 0

Ben Chevallereau
Ben Chevallereau

Reputation: 439

Do you set your variables locally in your tasks? From what I see, it seems that you define your variables at the execution level, but not at the state level. If you take a look at the ootb adhoc.bpmn20.xml file (https://github.com/Activiti/Activiti-Designer/blob/master/org.activiti.designer.eclipse/src/main/resources/templates/adhoc.bpmn20.xml), you can notice an event listener that sets the variable locally:

<extensionElements>
    <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
       <activiti:field name="script">
          <activiti:string>
           if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
           if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
          </activiti:string>
       </activiti:field>
    </activiti:taskListener>
</extensionElements>

Upvotes: 0

Related Questions