loganrussell48
loganrussell48

Reputation: 1864

Send Event and retrieve resulting state to Spring StateMachine

I have a spring state machine with a few different states.

I have a RestController that allows someone to send an event to the statemachine, and I want to respond with the state that the machine ends up in due to that event, but my current setup is still returning the starting state (although the machine does actually change states, the second call to the endpoint will respond with the correct state). Here is the code that I have:

return stateMachine.sendEvent(Mono.just(new Message<OrchestratorEvent>() {
            @Override
            public OrchestratorEvent getPayload() {
                return OrchestratorEvent.PRODUCTION_DONE;
            }

            @Override
            public MessageHeaders getHeaders() {
                return new MessageHeaders(Collections.emptyMap());
            }
        })).then(Mono.just(stateMachine.getState().getId().getStringValue()));

It appears that the maybe the event is sent to the machine, but it's not fully processed by the time that the downstream Mono tries to pull the new stateId out of the machine.

However, the following works like I'd expect, but comes at the cost of not being "fully-reactive" (and sendEvent like this is deprecated):

    @GetMapping
    public Mono<String> transition(){
        this.stateMachine.sendEvent(OrchestratorEvent.PRODUCTION_DONE);
        return Mono.just(stateMachine.getState().getId().getStringValue());
    }

I thought that this was the whole point of it being reactive, it would signal when it is done, and then I can safely pull the new state and get its ID. What am I missing? Thanks so much in advance!

Upvotes: 1

Views: 1322

Answers (1)

loganrussell48
loganrussell48

Reputation: 1864

The answer is that the returned Mono needed to be deferred, so the final code ended up like this:

return this.statemachine.sendEvent(Mono.just(MessageBuilder.withPayload(PRODUCTION_DONE).build())).then(Mono.deferred(()->this.statemachine.getState().getId()));

Deferring the Mono I guess lets the the new state get pulled out of the machine once that Mono is actually subscribed to. Still not fully understanding why the first approach I had doesn't work.

This example from the spring website led me to this answer

Upvotes: 2

Related Questions