Backend Development 20 min read

State Machine Integration for New Product Onboarding

The article details how Dewu’s new product onboarding workflow was refactored into a Spring StateMachine‑driven architecture that separates channel‑specific logic via a Strategy‑pattern operation layer, defines clear enum status domains, and uses guards, actions, and choice states to achieve maintainable, extensible, and idempotent state transitions.

DeWu Technology
DeWu Technology
DeWu Technology
State Machine Integration for New Product Onboarding

This article describes the design and implementation of a state‑machine‑based workflow for the "new product onboarding" process on the Dewu platform.

It first outlines the business flow: a product goes through several review stages (selection, merchant research, data verification) and the corresponding status fields are stored in two tables – the "new product sample" table and the SPU (Standard Product Unit) table.

Key problems that motivate the state‑machine adoption are:

Large number of status values and unclear transition rules make the code hard to understand and maintain.

Transitions are currently hard‑coded, leading to risky or non‑idempotent state changes.

Adding or modifying statuses requires extensive code changes and full‑process regression testing.

The solution selects Spring StateMachine as the framework and introduces a clean separation of concerns using the Strategy pattern.

Enum definitions for the two status domains are shown:

public enum NewProductShowEnum {
    DRAFT(0, "草稿"),
    CHECKING(1, "选品中"),
    UNPUT_ON_SALE_UNPASS(2, "选品不通过"),
    UNPUT_ON_SALE_PASSED(3, "商研审核中"),
    UNPUT_ON_SALE_PASSED_UNSEND(4, "商品资料待审核"),
    UNPUT_ON_SALE_PASSED_UNSEND_NOT_PUT(5, "鉴别不通过"),
    UNPUT_ON_SALE_PASSED_SEND(6, "请寄样"),
    SEND_PRODUCT(7, "商品已寄样"),
    SEND_PASS(8, "寄样鉴别通过"),
    SEND_REJECT(9, "寄样鉴别不通过"),
    GONDOR_INVALID(10, "作废"),
    FINSH_SPU(11, "新品资料审核通过")
}
public enum SpuStatusEnum {
    OFF_SHELF(0, "下架"),
    ON_SHELF(1, "上架"),
    TO_APPROVE(2, "待审核"),
    APPROVED(3, "审核通过"),
    REJECT(4, "审核不通过"),
    TO_RISK_APPROVE(8, "待风控审核"),
    TO_LEGAL_APPROVE(9, "待法务审核")
}

A generic operation interface abstracts all channel‑specific actions:

public interface NspOperate
{
    Integer supportApplyType();
    String operateCode();
    void preProcessRequest(C context);
    void verify(C context);
    void process(C context);
    void persistent(C context);
    void post(C context);
}

The factory method that retrieves the correct implementation based on channel and operation code:

public NspOperate getNspOperate(Integer applyType, String operateCode) {
    String key = buildKey(applyType, operateCode);
    NspOperate nspOperate = operateMap.get(key);
    if (Objects.isNull(nspOperate)) {
        String generalKey = buildKey(-1, operateCode);
        nspOperate = operateMap.get(generalKey);
    }
    AssertUtils.throwIf(Objects.isNull(nspOperate), "NspOperate not found! key = " + key);
    return nspOperate;
}

The concrete state‑machine configuration (example for the C‑end channel) defines states, transitions, guards and actions:

@Configuration
@EnableStateMachineFactory(name = "newSpuApplyStateMachineFactory")
public class NewSpuApplyStateMachineConfig extends EnumStateMachineConfigurerAdapter
{
    // ... bean definitions omitted for brevity ...
    @Override
    public void configure(StateMachineStateConfigurer
config) throws Exception {
        config.withStates()
            .initial(NewProductShowEnum.STM_INITIAL)
            .state(NewProductShowEnum.CHECKING)
            .state(NewProductShowEnum.UNPUT_ON_SALE_UNPASS)
            // other states omitted
            .states(EnumSet.allOf(NewProductShowEnum.class));
    }
    @Override
    public void configure(StateMachineTransitionConfigurer
transitions) throws Exception {
        transitions.withExternal()
            .source(NewProductShowEnum.STM_INITIAL)
            .target(NewProductShowEnum.CHECKING)
            .event(NewSpuApplyStateMachineEventsEnum.NEW_APPLY)
            .guard(nspNewApplyGuard)
            .action(nspNewApplyAction)
            // more transitions omitted for brevity
            ;
    }
}

Guard and action implementations delegate to the channel‑specific NspOperate instance. Example of a guard with a fixed target state:

@Component
public class NspNewApplyGuard extends AbstractGuard
{
    @Resource
    private NewSpuApplyOperateHelper helper;
    @Override
    protected boolean process(StateContext
context) {
        NewSpuApplyContext ctx = getSendEventContext(context).getRequest().getParams();
        Integer applyType = ctx.getApplyType();
        NspOperate
op = helper.getNspOperate(applyType, NewSpuApplyStateMachineEventsEnum.NEW_APPLY.getCode());
        op.preProcessRequest(ctx);
        op.verify(ctx);
        return true;
    }
}

And the corresponding action:

@Component
public class NspNewApplyAction extends AbstractSuccessAction
{
    @Resource
    private NewSpuApplyOperateHelper helper;
    @Override
    protected void process(StateContext
context) {
        NewSpuApplyContext ctx = getSendEventContext(context).getRequest().getParams();
        Integer applyType = ctx.getApplyType();
        NspOperate
op = helper.getNspOperate(applyType, NewSpuApplyStateMachineEventsEnum.NEW_APPLY.getCode());
        op.process(ctx);
        op.persistent(ctx);
        op.post(ctx);
    }
}

For transitions that require runtime decision, a Choice state is used together with a NspStatusDecider interface to compute the target status based on business logic.

The article also discusses how the design decouples channel‑specific logic (via strategy beans), keeps guard/action code reusable, and simplifies future extensions such as adding new channels, new status nodes, or reordering states.

In conclusion, the combination of a well‑structured state machine and a strategy‑based operation layer reduces code coupling, improves maintainability, and provides a clear, extensible framework for the product onboarding workflow.

design patternsworkflowbackendjavaproduct onboardingSpringState Machine
DeWu Technology
Written by

DeWu Technology

A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.

0 followers
Reader feedback

How this landed with the community

login 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.