This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Writing a Custom Workflow Template

You may have already tried out workflow support for user store operations where you can configure user store operations to get approved at one or more steps.

Multi-step approval is a very simple example of flows that can be used with IS workflow feature, but users are allowed define different types of configurable flows by adding a new workflow template.


Adding a New Workflow Template

A workflow template defines a configurable flow. It is an abstract representation of a workflow. You can add a new template by creating a custom bundle as below and copying it to repository/components/dropins folder.


First, you need to create a SampleTemplate class which extends AbstractTemplate class. The following methods should be overridden:

  • getInputData() :  Provides the parameter definition required by the template.

  • getTemplateId() : Should return the template Id which should be unique

  • getName() : Returns a user friendly name for the template. This will be the name shown at the admin UI

  • getDescription(): Returns a description about this template

Following is a sample class written for a multi-step approval template. 


public class SampleTemplate extends AbstractTemplate {

    public SampleTemplate(String metaDataXML) throws WorkflowRuntimeException {
        super(metaDataXML);
    }

    @Override
    protected InputData getInputData(String parameterName) throws WorkflowException {
        return null;
    }

    @Override
    public String getTemplateId() {
        return TEMPLATE_ID;
    }

    @Override
    public String getName() {
        return APPROVAL_TEMPLATE_NAME;
    }

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}



The configurable details of the template such as “Template ID”, “Template Name”, “Template Meta Data”, etc. should be separately defined in xml file like below.


<met:MetaData xmlns:met="http://metadata.bean.mgt.workflow.identity.carbon.wso2.org">
    <met:Template>
        <met:TemplateId>SampleTemplate</met:TemplateId>
        <met:TemplateName>SampleTemplate</met:TemplateName>
        <met:TemplateDescription>Sample Template</met:TemplateDescription>
        <met:ParametersMetaData xmlns:met="http://metadata.bean.mgt.workflow.identity.carbon.wso2.org">
            <met:ParameterMetaData Name="UserAndRole" InputType="Multiple_Steps_User_Role" isRequired="true">
                <met:DisplayName>User and Role</met:DisplayName>
            </met:ParameterMetaData>
        </met:ParametersMetaData>
    </met:Template>
</met:MetaData>


The finally in the service component, we need to register this template at activation. We can do this as follows.


bundleContext.registerService(AbstractTemplate.class, new SampleTemplate(readFileContent(Constants.TEMPLATE_PARAMETER_METADATA_FILE_NAME)), null);


 Now we need to add a concrete implementation of this template.

Adding a Workflow Template Implementation

The template implementation defines how the template should be deployed and executed. Optionally you can write this as a separate bundle and copy into repository/components/dropins folder. 

The implementations can be written by extending the AbstractWorkflow class. The following methods should be overridden: 

  • getInputData() :  Returns a parameter definition required by the template implementation 

The following shows a sample class written for a sample template. 

public class SampleTemplateImplementation extends AbstractWorkflow {

    private static Log log = LogFactory.getLog(SampleTemplateImplementation.class);

    public SampleTemplateImplementation(Class<? extends TemplateInitializer> templateInitializerClass,
                                        Class<? extends WorkFlowExecutor> workFlowExecutorClass, String metaDataXML) {
        super(templateInitializerClass, workFlowExecutorClass, metaDataXML);
    }

    @Override
    protected InputData getInputData(ParameterMetaData parameterMetaData) throws WorkflowException {
        InputData inputData = null;
        if (parameterMetaData != null && parameterMetaData.getName() != null) {
            String parameterName = parameterMetaData.getName();
            if ("BPSProfile".equals(parameterName)) {
                inputData = new InputData();
                MapType mapType = new MapType();
                inputData.setMapType(mapType);
                Item item = new Item();
                item.setKey("embeded_bps");
                item.setValue("embeded_bps");
                mapType.setItem(new Item[]{item});
            } else if ("HTSubject".equals(parameterName)) {
                inputData = new InputData();
                MapType mapType = new MapType();
                inputData.setMapType(mapType);
                Item item1 = new Item();
                item1.setKey("subject1");
                item1.setValue("subject1");
                Item item2 = new Item();
                item2.setKey("subject2");
                item2.setValue("subject2");
                mapType.setItem(new Item[]{item1, item2});
            }
        }
        return inputData;
    }

    @Override
    public void deploy(List<Parameter> parameterList) throws WorkflowException {
        super.deploy(parameterList);
    }
}

The configurable details of the template implementation such as “Template ID”, “Template Implementation ID”, “Template Implementation Meta Data”, etc. should be separately defined in xml file like below. 

<met:MetaData xmlns:met="http://metadata.bean.mgt.workflow.identity.carbon.wso2.org">
    <met:WorkflowImpl>
        <met:WorkflowImplId>SampleWorkflow</met:WorkflowImplId>
        <met:WorkflowImplName>SampleWorkflow</met:WorkflowImplName>
        <met:WorkflowImplDescription>Sample Workflow</met:WorkflowImplDescription>
        <met:TemplateId>SampleTemplate</met:TemplateId>
        <met:ParametersMetaData>
            <met:ParameterMetaData Name="BPSProfile" InputType="Select" isRequired="true" isInputDataRequired="true">
                <met:DisplayName>BPS Profile(Server Profile Name)</met:DisplayName>
            </met:ParameterMetaData>
            <met:ParameterMetaData Name="HTSubject" InputType="Select" isRequired="true" isInputDataRequired="true">
                <met:DisplayName>Task Subject(Approval task subject to display)</met:DisplayName>
            </met:ParameterMetaData>
        </met:ParametersMetaData>
    </met:WorkflowImpl>
</met:MetaData>

Finally, in the service component, we need to register this template at activation as follows. 

bundleContext.registerService(AbstractWorkflow.class, new SampleTemplateImplementation(BPELDeployer.class, RequestExecutor.class, readFileContent(Constants.WORKFLOW_IMPL_PARAMETER_METADATA_FILE_NAME)), null);

Now when adding a new workflow, you will get a drop-down menu to select which template to follow in that workflow. 

 

Source of the sample which used for this documentation can be found here.