Say Goodbye to If‑Else Nightmares with Flow Orchestration

The article explains how excessive if‑else logic in Java back‑ends harms code isolation and scalability, and demonstrates a practical workflow‑orchestration solution using a FlowChain engine, complete with configuration, node definitions, execution flow, and source code examples from the open‑source MemberClub project.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Say Goodbye to If‑Else Nightmares with Flow Orchestration

Configure Flow Execution Chain

Different membership product transaction processes require distinct flow chains. The class DemoMemberPurchaseExtension implements a purchase extension point and defines three flow‑chain configurations, as shown in the screenshot.

Define Flow Nodes

Each flow node provides four methods: process, success, rollback, and callback. The diagram illustrates how these methods are declared.

Flow Execution

To run a flow, provide a context object and call FlowChain.execute. The engine links the nodes and executes them sequentially, following a responsibility‑chain pattern.

The execution order is:

Invoke each node's process method in order.

If a process throws an exception, invoke rollback on already‑executed nodes in reverse order.

If all process calls succeed, invoke success on nodes in reverse order.

Finally, call callback on every node regardless of success or failure.

Flow Engine Execution Principle

The core of FlowChain.execute is shown below:

public <T> void execute(FlowChain<T> chain, T context) {
    Exception exception = null;
    int index = -1;
    for (FlowNode<T> node : chain.getNodes()) {
        try {
            node.process(context);
            index++;
        } catch (Exception e) {
            if (e instanceof SkipException) {
                CommonLog.warn("当前流程:{} 发出 Skip请求,后续流程不再执行", node.getClass().getSimpleName());
                break;
            }
            exception = e;
            break;
        }
    }
    if (exception != null) {
        for (int i = index; i >= 0; i--) {
            FlowNode<T> node = chain.getNodes().get(i);
            try { node.rollback(context, exception); } catch (Exception e) { CommonLog.error("rollback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e); }
        }
    } else {
        for (int i = index; i >= 0; i--) {
            FlowNode<T> node = chain.getNodes().get(i);
            try { node.success(context); } catch (Exception e) { CommonLog.error("success 执行异常,忽略 name:{}", node.getClass().getSimpleName(), e); }
        }
    }
    for (int i = index; i >= 0; i--) {
        FlowNode<T> node = chain.getNodes().get(i);
        try { node.callback(context, exception); } catch (Exception e) { CommonLog.error("callback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e); }
    }
    if (exception != null) { throw exception; }
}

The full source code resides in the MemberClub repository:

https://gitee.com/-/ide/project/juejinwuyang/memberclub/edit/master/-/memberclub.common/src/main/java/com/memberclub/common/flow/FlowChainService.java

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendjavacode refactoringProcess EngineFlow Orchestration
Java Architect Handbook
Written by

Java Architect Handbook

Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.