Page tree
Skip to end of metadata
Go to start of metadata


Create a new workflow

  1. Create a new BPMN2 process with the following information

    PropertyValue
    Process NameDispatchPublicationWorkflow
    Packageinfo.magnolia.workflow

    Good to know

    The step are very similar to the Exercise: Implement the email notifier.


Define a custom dispatch node work item handler (task)

  1. Define a new work item handler in the WorkItemDefinitions.wid

    PropertyValue
    name

    dispatchNode

    displayName

    DispatchNodePublication

    Good to know

    The step are very similar to the Exercise: Implement the email notifier.

  2. Reference an existing work item handler in the WorkItemDefinitions.wid

    PropertyValue
    name

    rejectNotification

    displayName

    RejectNotification

    Good to know

    The implementation of this task is provided by default by Magnolia. We only need to register the task in our work item definitions, so the editor can generate the right task attributes.


Draw the custom workflow

  1. Drag and drop the DispatchNodePublication task between the Start event and the End event.




  2. Open the palette's folder Tasks and select a User Task. Drag & drop it on the diagram between the DispatchNodePublicaion task and the End event. In the related Properties panel, set the name to "Review and Publish".




  3. Open the palette's folder Gateways and select a Data-based Exclusive (XOR). Drag & drop it on the diagram between the Human task task and the End event. In the related Properties panel, set the name to "Publisher's choice".


    Good to know

    The diagram errors are normal so far. We will deal with the elements definition in the next section.

  4. Open the palette's folder Sub Processes and select a Reusable Process. Drag & drop it on the diagram between the Exclusive Gateway task and the End event. In the related Properties panel, set the name to "Publication". Rename as well the End event into "End Publication".


  5. Open the palette's folder Tasks and select Custom Task. Drag & drop it on the diagram in an empty space. Do the same with a new End event. Link the Exclusive Gateway to the new Task and the new Task to the new End event. In the new End event's Properties panel, set the name to "End Rejection".




  6. Add a new End event named "End Cancellation".


Set the tasks parameters

  1. Reproduce the step 1 and 2 of the "Set the tasks parameters" section of the Exercise: Implement the email notifier. Add an additional process variable called taskResult typed java.util.Map and another called taskId typed String.
  2. Map the mgnlData variable as input data for the task DispatchNodePublication
  3. Select the Human Task and go to the Properties panel. Click on the tab User Task and set the task name to "enhancedPublish". Clear all attributes.

    Good to know

    We are going to extend the default Publication human task in a following section.



  4. Open the I/O Parameters and map the mgnlData and taskResult variables as input data.
  5. Still in the  I/O Parameters tab, map the taskResult and taskId variables as output data.
  6. Open the Exclusive Gateway Properties panel, click on the Gateway tab and make sure that the direction is set to "Diverging".
  7. Select the Sequence Flow linking the Exclusive Gateway and the Reusable Process. Set the name to "Approve". In the Sequence Flow tab, add a new condition (language: Java) and set the following code:

    Condition
    Map data = (Map) kcontext.getVariable("taskResult");
    String decision = (String) data.get("decision");
    return "approve".equalsIgnoreCase(decision);
  8. Select the Sequence Flow linking the Exclusive Gateway and the Reject task. Set the name to "Reject". In the Sequence Flow tab, add a new condition (language: Java) and set the following code:

    Condition
    Map data = (Map) kcontext.getVariable("taskResult");
    String decision = (String) data.get("decision");
    return "reject".equalsIgnoreCase(decision);
  9. Select the Sequence Flow linking the Exclusive Gateway and the cancellation End event. Set the name to "Abort". In the Sequence Flow tab, add a new condition (language: Java) and set the following code:

    Condition
    Map data = (Map) kcontext.getVariable("taskResult");
    String decision = (String) data.get("decision");
    return "abort".equalsIgnoreCase(decision);
  10. Select the Reusable Process and open the Call Activity tab. Set the called element to "info.magnolia.workflow.Publication" and uncheck the independent flag. Map the mgnlDatataskResult, commandName and taskId variables as input data.

  11. Select the Reject task and map the mgnlData and taskResult variables as input data.


Implement the DispatchNodePublication task

  1. Implement the work item handler definition.

    info.magnolia.services.training.workflow.task.DispatchNodeWorkItemHandlerDefinition
    /**
     * This file Copyright (c) 2017 Magnolia International
     * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
     *
     *
     * This program and the accompanying materials are made
     * available under the terms of the Magnolia Network Agreement
     * which accompanies this distribution, and is available at
     * http://www.magnolia-cms.com/mna.html
     *
     * Any modifications to this file must keep this entire header
     * intact.
     *
     */
    package info.magnolia.services.training.workflow.task;
    
    import info.magnolia.module.workflow.jbpm.workitem.handler.definition.ConfiguredWorkItemHandlerDefinition;
    
    /**
     * Definition of the task {@link DispatchNodeWorkItemHandler}.
     *
     * @author Magnolia International Ltd.
     */
    public class DispatchNodeWorkItemHandlerDefinition extends ConfiguredWorkItemHandlerDefinition {
    
        /**
         * Constructor.
         */
        public DispatchNodeWorkItemHandlerDefiniton() {
            // Assign of the default implementation
            this.setImplementationClass(DispatchNodeWorkItemHandler.class);
        }
    }
  2. Implement the work item handler.

    info.magnolia.services.training.workflow.task.DispatchNodeWorkItemHandler
    /**
     * This file Copyright (c) 2017 Magnolia International
     * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
     *
     *
     * This program and the accompanying materials are made
     * available under the terms of the Magnolia Network Agreement
     * which accompanies this distribution, and is available at
     * http://www.magnolia-cms.com/mna.html
     *
     * Any modifications to this file must keep this entire header
     * intact.
     *
     */
    package info.magnolia.services.training.workflow.task;
    
    import info.magnolia.context.Context;
    
    import java.util.Map;
    
    import org.kie.api.runtime.process.WorkItem;
    import org.kie.api.runtime.process.WorkItemHandler;
    import org.kie.api.runtime.process.WorkItemManager;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * Implementation of the dispatch node task.
     *
     * @author Magnolia International Ltd.
     */
    public class DispatchNodeWorkItemHandler implements WorkItemHandler {
        /** Logger. */
        private static final Logger LOG = LoggerFactory.getLogger(DispatchNodeWorkItemHandler.class);
    
        @SuppressWarnings("unchecked")
        @Override
        public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
            // Gets the local variable from the process instance
            Map<String, Object> mgnlData = (Map<String, Object>) workItem
                    .getParameter("mgnlData");
    
            // Gets the current page node path
            String publishedPage = (String) mgnlData.get(Context.ATTRIBUTE_PATH);
    
            // Dispatch to the related group
            mgnlData.put("groupId", this.dispatch(publishedPage));
    
            // Marks the task as completed so the process can continue
            manager.completeWorkItem(workItem.getId(), mgnlData);
        }
    
        @Override
        public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
    
        }
    
        /**
         * Dispatch the related group.
         *
         * @param publishedPage
         *            The published page node
         * @return The related group name
         */
        private String dispatch(String publishedPage) {
            String groupId = "publishers";
    
            if (publishedPage != null) {
                if (publishedPage.startsWith("/Extranet")) {
                    groupId = "publishersExtranet";
                } else if (publishedPage.startsWith("/Intranet")) {
                    groupId = "publishersIntranet";
                } else if (publishedPage.startsWith("/Internet")) {
                    groupId = "publishersInternet";
                }
            }
    
            LOG.info("Dispatching to {}", groupId);
    
            return groupId;
        }
    }


Implement the Enhanced Publication human task

  1. Implement a enhanced parameter resolver. We need to assign the group id according to the result of a previous task in the process.

    info.magnolia.services.training.workflow.humantask.EnhancedHumanTaskParameterResolver
    /**
     * This file Copyright (c) 2017 Magnolia International
     * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
     *
     *
     * This program and the accompanying materials are made
     * available under the terms of the Magnolia Network Agreement
     * which accompanies this distribution, and is available at
     * http://www.magnolia-cms.com/mna.html
     *
     * Any modifications to this file must keep this entire header
     * intact.
     *
     */
    package info.magnolia.services.training.workflow.humantask;
    
    import info.magnolia.context.Context;
    import info.magnolia.module.workflow.jbpm.humantask.HumanTask;
    import info.magnolia.module.workflow.jbpm.humantask.definition.PublicationTaskDefinition;
    import info.magnolia.module.workflow.jbpm.humantask.parameter.AbstractHumanTaskParameterResolver;
    import info.magnolia.services.training.workflow.BusinessWorkflowConstants;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.commons.collections4.CollectionUtils;
    import org.apache.commons.collections4.MapUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.kie.api.runtime.process.WorkItem;
    
    /**
     * Enhanced version of the Publication parameter resolver. It takes into
     * consideration the group id evaluated by a previous task in the process.
     *
     * @author Magnolia International Ltd.
     */
    public class EnhancedHumanTaskParameterResolver extends AbstractHumanTaskParameterResolver<PublicationTaskDefinition> {
    
        /**
         * Constructor.
         *
         * @param definition
         *            The human task definition.
         */
        public EnhancedHumanTaskParameterResolver(PublicationTaskDefinition definition) {
            super(definition);
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public void setTaskParameters(HumanTask task, WorkItem workItem) {
            // Extract the mgnlData from the work item context
            Map<String, Object> mgnlData = (Map<String, Object>) workItem
                    .getParameter("mgnlData");
    
            // Set the names
            String taskName = (String) workItem.getParameter(TASK_NAME);
            task.setName(taskName);
            // Set the actors
            task.setActorIds(this.getDefinition().getActors());
            // Set the groups
            task.setGroupIds(this.getGroupIds(mgnlData));
    
            // Copy the parameters map
            if (mgnlData != null) {
                // Set the comment
                task.setComment((String) mgnlData.get(Context.ATTRIBUTE_COMMENT));
                // Set the requestor
                task.setRequestor((String) mgnlData.get(Context.ATTRIBUTE_USERNAME));
    
                // Clone the work item content
                task.setContent(this.cloneContent(mgnlData));
            }
        }
    
        /**
         * Clone the current work item content.
         *
         * @param mgnlData
         *            The current work item content.
         * @return A clone of the current work item content.
         */
        protected Map<String, Object> cloneContent(Map<String, Object> mgnlData) {
            Map<String, Object> clone = new HashMap<>();
    
            if (MapUtils.isNotEmpty(mgnlData)) {
                Iterator<String> it = mgnlData.keySet().iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    clone.put(key, mgnlData.get(key));
                }
            }
    
            return clone;
        }
    
        /**
         * Get the group from the previous task or the definition.
         *
         * @param mgnlData
         *            The task results parameters map
         * @return The group id list
         */
        protected List<String> getGroupIds(Map<String, Object> mgnlData) {
            List<String> groupIds = new ArrayList<String>();
    
            // Get the possible group coming from a previously executed task
            if (MapUtils.isNotEmpty(mgnlData)) {
                String groupId = (String) mgnlData.get("groupId");
                if (StringUtils.isNotEmpty(groupId)) {
                    groupIds.add(groupId);
                }
            }
    
            // If not group id found in the process data, then take the definition
            // ones
            if (CollectionUtils.isEmpty(groupIds)) {
                groupIds = this.getDefinition().getGroups();
            }
    
            return groupIds;
        }
    }


Configure Magnolia

  1. Add the new workflow definition called "dispatchPublication".

    PropertyValue
    idinfo.magnolia.workflow.DispatchPublicationWorkflow
    resourcePathDispatchPublicationWorkflow.bpmn2
    typebpmn
  2. Add a new work item handler definition called "dispatchNode" as defined in the wid file.

    PropertyValue
    classinfo.magnolia.services.training.workflow.task.DispatchNodeWorkItemHandlerDefiniton
  3. Add a new human task definition. Still in the config app, browse to the node /modules/workflow-jbpm/tasks. Duplicate the node publish and renamed it into "enhancedPublish" as defined in the BPMN diagram. In the new node, delete the groups sub node and set the parameterResolver task to "info.magnolia.services.training.workflow.humantask.EnhancedHumanTaskParameterResolver".

  4. Apply the new workflow to the publication command (/modules/workflow/commands/workflow/activate/activate).
  5. Restart your Tomcat server.


Test the workflow

  1. Go the pages app and select the page called "Other".
  2. Press Publish. Follow the publication procedure. As superuser, we should be notified about that publication.
  3. Try do to the same with the page called "Internet".
  4. The superuser should not see this process. Connect with the user publisherInternet to continue.
  5. Try with the other pages.
  • No labels