Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Lightweight Workflow Execution Using Dexecutor

DZone's Guide to

Lightweight Workflow Execution Using Dexecutor

Organizing your tasks in a manageable way can be difficult and unwieldly. Add in something like Dexecutor, and your life gets a whole lot easier.

· Java Zone ·
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Dexecutor can be used very easily for workflow like cases as depicted in the following diagram.

dexecutor-workflow-example

Dexecutor instance is created using DexecutorConfig, which in turn requires ExecutionEngine and TaskProvider, Default Implementation of ExecutionEngine uses ExecutorService, so lets create a Dexecutor Instance first (source code can be found here):

private static ExecutorService buildExecutor() {
   ExecutorService executorService = Executors.newFixedThreadPool(ThreadPoolUtil.ioIntesivePoolSize());
   return executorService;
 }
private Dexecutor<String, Boolean> buildDexecutor(final ExecutorService executorService) {
   DexecutorConfig<String, Boolean> config = new DexecutorConfig<>(executorService, new WorkFlowTaskProvider());
   return new DefaultDexecutor<>(config);
 }

TaskProvider comes into action, when it is the time to execute the task, for this example we will have simple implementation WorkFlowTaskProvider

public class WorkFlowTaskProvider implements TaskProvider<String, Boolean> {

    private final Map<String, Task<String, Boolean>> tasks = new HashMap<String, Task<String, Boolean>>() {

        private static final long serialVersionUID = 1L;
        {
            put(TaskOne.NAME, new TaskOne());
            put(TaskTwo.NAME, new TaskTwo());
            put(TaskThree.NAME, new TaskThree());
            put(TaskFour.NAME, new TaskFour());
            put(TaskFive.NAME, new TaskFive());
            put(TaskSix.NAME, new TaskSix());
            put(TaskSeven.NAME, new TaskSeven());
        }    
    };

    @Override
    public Task<String, Boolean> provideTask(final String id) {
        return this.tasks.get(id);
    }
}

For simplicity, we have implemented Task for each of the tasks (1..7), those can be found here, Most of the task implementations are same except for TaskTwo (if task 2 result is TRUE then tasks 3 and 4 would be executed otherwise task 5 would be executed) and TaskFive (If task 5 is executed (not skipped) then task task 6 would be executed).

dexecutor-task

TaskFive (TaskThree, TaskFour and TaskSix) overrides shouldExecute() method, to signal if the task should be executed or skipped.

dexecutor-skipping-task-execution

Next step is to build the graph:

dexecutor-workflow-graph-building

If WorkFlowApplication is executed, the following output can be observed.

Output if TaskTwo Is False

Executing TaskOne , result : true
Executing TaskTwo , result : false
Executing TaskFive , result : true
Executing TaskSix , result : true
Executing TaskSeven , result : true

Output if TaskTwo Is True

Executing TaskOne , result : true
Executing TaskTwo , result : true
Executing TaskFour , result : true
Executing TaskThree , result : true
Executing TaskSeven , result : true


Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:
dexecutor ,java ,distributed workflow

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}