Mithun
Mithun

Reputation: 8067

Spring State machine not accepting same event from multiple users

I have simple state machine with following States, Events and Transitions.

States: WIP, SUBMITTED, REJECTED, APPROVED

Events: SUBMIT, APPROVE, REJECT

Transitions:

@Override
public void configure(StateMachineTransitionConfigurer<States,Events> transitions) 
                          throws Exception {
    transitions
        .withExternal()
            .source(States.WIP)
            .target(States.SUBMIT)
            .event(Events.SUBMIT)
            .and()
        .withExternal()
            .source(States.SUBMITTED)
            .target(States.APPROVED)
            .event(Events.APPROVE)
            .and()
        .withExternal()
            .source(States.SUBMITTED)
            .target(States.REJECTED)
            .event(Events.REJECT);;
}
  1. WIP to SUBMITTED for SUBMIT event
  2. SUBMITTED to APPROVED for APPROVE event
  3. SUBMITTED to REJECTED for REJECT event

I have set WIP as the initial state as below:

@Override
public void configure(StateMachineStateConfigurer<States, Events> states) 
            throws Exception {
    states
    .withStates()
        .initial(States.WORK_IN_PROGRESS)
        .states(EnumSet.allOf(States.class));
}

Multiple users will interact with this state machine. When the same event is raised multiple times for a combination of source and target states, only the first event is accepted by the state machine the subsequent events are not accepted.

Is this a valid behaviour from state machine? If yes, Is there any extra configuration that I need to add?

Upvotes: 4

Views: 3277

Answers (1)

Janne Valkealahti
Janne Valkealahti

Reputation: 2646

Using one state machine instance in a scenario like this would only work if both agents and approvers handle exactly one set of docs. Naturally it creates problems for real world use cases because agent could only submit new docs when approver have put machine back to state where docs can be submitted.

So, you'd need a dedicated instance for every set of submitted docs. This can be done by either exposing a factory from a config http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#sm-factories or manually using builder http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#state-machine-via-builder. Then you need to manually control with which machine you are talking to.

You mentioned that docs can sit there days waiting for someone to approve which kinda creates a problem if you need to restart process holding state machines. (you'd lose state with simple in-process state machine)

I'd recommend a little different approach to tackle this problem. Check persist sample http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#statemachine-examples-persist which is a demo where "stuff" is kept in a database and a single state machine instance is used to update db via a state machine. This allows you to keep your stuff in a persistent store and handle transition logic within a state machine.

We're currently trying to make these use scenarios more easy to use by trying to implement better persist model and possibly introduce some magic via spring security and spring session to ease/protect different roles who can do what in a state machine. So stay tuned for future releases.

Upvotes: 6

Related Questions