Implementing a Task

A task can be added on the fly during runtime. You implement a task class and put that class under Swordfish_installed_directory/custom directory. Then it will be automatically loaded when you open flow designer.

To implement a task, a task class must implement TaskHandler and define an TaskDefinition java annotation.

TaskHandler interface

package com.ism.was.flow.entity;

import java.util.Map;
import java.util.Properties;

public interface TaskHandler {
	public boolean initializeTask(Properties props);
	public boolean execute(String flowId, String taskId, String transactionId, FlowTask [] tasks, Map requestData);
	public TaskResult getResult();
	public String getName();
	public boolean finalizeTask();
}


                

Signature

public boolean initializeTask(Properties props);
                

Description

Used when extra additional initialization is required for a task

Parameters

props - input attributes defined in flow.

Return

boolean value.

  • True - initialization succeeded

  • False - initialization failed

Signature

public boolean execute(String flowId, String taskId, String transactionId, FlowTask [] tasks, Map requestData);
                

Description

Main method of a task

Parameters

  • flowId - flow id

  • taskId - task id

  • transactionId - transaction id

  • tasks - tasks executed previously

  • requestData - collection of output data from previous tasks

Return

boolean value.

  • True - succeeded

  • False - failed

Signature

public TaskResult getResult();
                

Description

Returns the result of task execution. This result contains the input and output data of the task execution

Parameters

Return

TaskResult may contain error information, if it failed.

Signature

public boolean finalizeTask();
                

Description

Used when an additional finalization is required of a task

Parameters

Return

boolean value.

  • True - succeeded

  • False - failed

TaskDefinition annotation

package com.ism.was.flow.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface TaskDefinition {
	public String name();
	public String description();
	public int arguments();
	public String html() default "";
	public String type() default "java";
	public String icon() default "";
	public FieldDefinition [] fields() default {};
	public FieldDefinition [] outs() default {};
	public boolean test() default false;
	public String testLink() default "";
	public boolean custom() default false;
	public String customPage() default "";
}
                

Attributes

NameDescription

name

Task name displayed in flow designer

description

Task description

arguments

Number of input attribute. For display purpose only.

html

custom html page for input/output attributes

type

task type. For display purpose only

icon

path of task icon. ex) images/task.png

fields

input attribute list

outs

output attribute list

test

whether test page is provided

testLink

custom html page for testing

custom

True if custom html page is provided for input attibutes

customPage

The class path of the html page

ex) com/ism/was/flow/handler/html/ftptransfer-task.html

FieldDefinition

package com.ism.was.flow.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface FieldDefinition {

	public String name();
	public String label() default "";
	public String help() default "";
	public int width() default 0;
	public String type() default "text";
	public int height() default 0;
	public int rows() default 3;
	public int cols() default 80;
	public String selectFrom() default "";
	public String [] options() default {};
	public String [] labels() default {};
}

                

Attributes

NameDescription

name

Attribute name displayed in property editor

label

Label of attribute

help

Help message

width

Not used. For display purpose only. HTML text box

height

Not used. For display purpose only. HTML text box

rows

For display purpose only. HTML textarea

cols

For display purpose only. HTML textarea

selectFrom

Used only when option list of HTML select is from a class invocation

options

Available values of the attribute. HTML select

labels

For display purpose only. HTML select

Example implementation - Wait Task

package com.ism.was.flow.handler;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import com.ism.common.Common;
import com.ism.common.logger.DefaultLogger;
import com.ism.was.flow.annotation.FieldDefinition;
import com.ism.was.flow.annotation.TaskDefinition;
import com.ism.was.flow.config.FlowConstants;
import com.ism.was.flow.entity.FlowTask;
import com.ism.was.flow.entity.SubFlowExecution;
import com.ism.was.flow.entity.TaskHandler;
import com.ism.was.flow.entity.TaskResult;
import com.ism.was.flow.log.SubFlowExecutionLog;
import com.ism.was.flow.log.SubflowLogManager;
import com.ism.was.flow.util.FlowUtil;

@TaskDefinition(
		name="Wait", description="Wait sub flow completion", arguments=-1,
		custom=false,type="function",
		icon="images/wait.png",
		fields = { 
			@FieldDefinition(name="SubFlowId", width=100, height=30, rows=10, cols=80, type="select", selectFrom="com.ism.projects.jpa.web.flow.FlowProcessor" ),
			@FieldDefinition(name="ExecutionCount", width=100, height=30, rows=10, cols=80, type="text" ),
			@FieldDefinition(name="Timeout", width=100, height=30, rows=10, cols=80, type="text" ),
		},
		outs = { 

		}
	)
public class WaitSubTask implements TaskHandler {

	protected Properties props;
	protected TaskResult result;
	
	protected Properties outprops;
	
	private String resultValueName = null;
	
	public boolean initializeTask(Properties props) {
		// TODO Auto-generated method stub
		this.props = props;
		return true;
	}

	public boolean execute(String flowId, String taskId, String gidSeq, FlowTask[] tasks, Map imap) {
		// TODO Auto-generated method stub
		
		result = new TaskResult(gidSeq);
    	result.setStartTime();
    	
		Vector imaps = new Vector();
    	HashMap omap = new HashMap();
    	omap.putAll(imap);
		
    	result.setSuccess(true);
    	
	String gid = (String)imap.get("GID");
		
	String subFlowId = (String)props.get("SubFlowId");
	String executionCount = (String)props.get("ExecutionCount");
	String timeout = (String)props.get("Timeout");
		
	resultValueName = (String)props.get("out-ResultValue");
	if ( resultValueName == null || resultValueName.trim().length() < 1 ) {
		resultValueName = "ResultValue";
	}
		
	Object rtn = null;

	int completedCount = 0;
    	try {
    		executionCount = (String)FlowUtil.getValue(imap, props, executionCount);
    		if ( executionCount == null ) {
    			throw new Exception("ExecutionCount cannot be null or empty");
    		}
    		int executionCountInt = -1;
    		try {
    			executionCountInt = Integer.parseInt(executionCount.trim());	
    		}catch( Exception e ) {
    			throw new Exception("ExecutionCount value is invalid[" + executionCount + "]");
    		}
    		long start = System.currentTimeMillis();
    		long timeoutLong = Long.parseLong(timeout) * 1000; //30 sec
    		boolean succeeded = false;
    		int interval = 0;
    		while ( true ) {
			String fkey = String.format("%s-%s-%s", flowId, subFlowId, gid);
        			int count = SubflowLogManager.countComplete(fkey);
	    		if ( ++interval % 10 == 0 ) {
        				DefaultLogger.logN("Expected count = {}, logged count = {}, {}, {}, {} ", executionCountInt, count, flowId, subFlowId, gid);
    			}else {
        				DefaultLogger.logV("Expected count = {}, logged count = {}, {}, {}, {} ", executionCountInt, count, flowId, subFlowId, gid);
    			}
	        		if ( count != executionCountInt ) {
        				Thread.sleep(2000);
        			}else {
	        			succeeded = true;
            			SubflowLogManager.removeSubflows(fkey);
        				break;
	        		}
        			if ( Common.shutdown ) {
        				break;
	        		}
        			long now = System.currentTimeMillis();
	        		if ( now > (start + timeoutLong) ) {
        				break;
        			}
    		}
		omap.put(resultValueName, rtn);
    		result.setSuccess(succeeded);
    	}catch( Exception e ) {
    		DefaultLogger.logE(e, "Failed to executing function");
        		result.setErrorMessage(e.getMessage());
        		result.setException(e);
    		result.setSuccess(false);
    	}
	result.setData(omap);
    	result.setEndTime();
    	
    	return result.isSuccess();
	}

	public TaskResult getResult() {
		// TODO Auto-generated method stub
		return result;
	}

	public String getName() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean finalizeTask() {
		// TODO Auto-generated method stub
		return false;
	}
	
}


                

Last updated