package com.example.statemachinedemo.statemachine; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateContext; import org.springframework.statemachine.action.Action; import org.springframework.statemachine.config.EnableStateMachineFactory; import org.springframework.statemachine.config.StateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; import org.springframework.statemachine.guard.Guard; import org.springframework.statemachine.listener.StateMachineListenerAdapter; import org.springframework.statemachine.state.State; @Configuration @EnableStateMachineFactory @Slf4j class SimpleEnumStateMachineConfiguration extends StateMachineConfigurerAdapter { @Override public void configure(StateMachineTransitionConfigurer transitions) throws Exception { Guard guard1 = null; Action action2 = null; transitions .withExternal().source(OrderStates.SUBMITTED).target(OrderStates.PAID).event(OrderEvents.PAY) .and() .withExternal().source(OrderStates.PAID).target(OrderStates.FULFILLED).event(OrderEvents.FULFILL) .and() .withExternal().source(OrderStates.SUBMITTED).target(OrderStates.CANCELED).event(OrderEvents.CANCEL).guard(new Guard() { @Override public boolean evaluate(StateContext context) { return false; } }) .and() .withExternal().source(OrderStates.PAID).target(OrderStates.CANCELED).event(OrderEvents.CANCEL) .and() .withExternal().source(OrderStates.SUBMITTED).event(OrderEvents.ABCD) // it needs to have target specified to get added to .transitions collections // .withExternal().source(OrderStates.SUBMITTED).target(OrderStates.SUBMITTED).event(OrderEvents.ABCD) // .and() .withChoice() .source(OrderStates.SUBMITTED) .first(OrderStates.PAID2, new Guard() { @Override public boolean evaluate(StateContext context) { return false; } }) .last(OrderStates.PAID3) .and() .withChoice().source(OrderStates.PAID) .first(OrderStates.PAID1, new Guard() { @Override public boolean evaluate(StateContext context) { return true; } }) .then(OrderStates.PAID2, guard1) .then(OrderStates.HAPPEN, new Guard() { @Override public boolean evaluate(StateContext context) { return false; } }) .last(OrderStates.PAID3) .and().withExternal().source(OrderStates.PAID2).target(OrderStates.CANCELED) .and().withExternal().source(OrderStates.PAID3).target(OrderStates.CANCELED) // .and().withLocal().source(OrderStates.SUBMITTED).target(OrderStates.CANCELED) .and().withExternal().source(OrderStates.PAID1).event(OrderEvents.ABCD).action(new Action() { @Override public void execute(StateContext context) { ; } }).action(action2); } @Override public void configure(StateMachineStateConfigurer states) throws Exception { states.withStates() .initial(OrderStates.SUBMITTED) .state(OrderStates.PAID) .state(OrderStates.PAID2) .state(OrderStates.PAID3) .end(OrderStates.FULFILLED) .end(OrderStates.CANCELED); } @Override public void configure(StateMachineConfigurationConfigurer config) throws Exception { StateMachineListenerAdapter listenerAdapter = new StateMachineListenerAdapter<>() { @Override public void stateChanged(State from, State to) { log.info("state changed from {} to {}", from, to); } }; config.withConfiguration() .autoStartup(false) .listener(listenerAdapter); } }