17. Using Guards

Above guard1 and guard2 beans are attached to states entry and exit respectively.

@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
        throws Exception {
    transitions
        .withExternal()
            .source(States.SI).target(States.S1)
            .event(Events.E1)
            .guard(guard1())
            .and()
        .withExternal()
            .source(States.S1).target(States.S2)
            .event(Events.E1)
            .guard(guard2())
            .and()
        .withExternal()
            .source(States.S2).target(States.S3)
            .event(Events.E2)
            .guardExpression("extendedState.variables.get('myvar')");
}

You can directly implement Guard as an anonymous function or create a your own implementation and define appropriate implementation as a bean. In above sample guardExpression is simply checking if extended state variable myvar evaluates to TRUE.

@Bean
public Guard<States, Events> guard1() {
    return new Guard<States, Events>() {

        @Override
        public boolean evaluate(StateContext<States, Events> context) {
            return true;
        }
    };
}

@Bean
public BaseGuard guard2() {
    return new BaseGuard();
}

public class BaseGuard implements Guard<States, Events> {

    @Override
    public boolean evaluate(StateContext<States, Events> context) {
        return false;
    }
}
[Note]Note

StateContext is described in section Chapter 19, Using StateContext.

17.1 SpEL Expressions with Guards

It is also possible to use SpEL expressions as a replacement for a full Guard implementation. Only requirement is that expression needs to return a Boolean value to satisfy Guard implementation. This is demonstrated with a guardExpression() function which takes an expression as an argument.