Spring Statemachine: how to handle two transitions that has the same source state? - spring-statemachine

How does Spring Statemachine handle two transitions that has the same source state?
For example:
Source State: ready
Event: start
One transition will be lead to the target state running, another one will be failure
Any help would be appreciated.

the scenario you described above can be achieved in two ways.
In case of failure to process the incoming event (START), machine would remain in the original state (ready). The transition is only completed when event is process successfully.
However, if you really need to get away from READY state and move to RUNNING or FAILURE, one can use the Guard condition. You can use an evaluation function to define if the START event was successful or not and define to which state machine should go to.
This can be achieved using a CHOICE pseudo-state that is protected by a Guard class, based on machine configuration and Guard evaluation, machine would move to the expected state
The official doc for reference on how to make the implementation is here

Related

Use Cases for LRA

I am attempting to accomplish something along these lines with Quarkus, and Naryana:
client calls service to start a process that takes a while: /lra/start
This call sets off an LRA, and returns an LRA id used to track the status of the action
client can keep polling some endpoint to determine status
service eventually finishes and marks the action done through the coordinator
client sees that the action has completed, is given the result or makes another request to get that result
Is this a valid use case? Am I visualizing the correct way this tool can work? Based on how the linked guide reads, it seems that the endpoints are more of a passthrough to the coordinator, notifying it that we start and end an LRA. Is there a more programmatic way to interact with the coordinator?
Yes, it might be a valid use case, but in every case please read the MicroProfile LRA specification - https://github.com/eclipse/microprofile-lra.
The idea you describe is more or less one LRA participant executing in a new LRA and polling the status of this execution. This is not totally what the LRA is intended for, but surely can be used this way.
The main idea of LRA is the composition of distributed transactions based on the saga pattern. Basically, the point is to coordinate multiple services to achieve consistent results with an eventual consistency guarantee. So you see that the main benefit arises when you can propagate LRA through different services that either all complete their actions or all of their compensation callbacks will be called in case of failures (and, of course, only for the services that executed their actions in the first place). Here is also an example with the LRA propagation https://github.com/xstefank/quarkus-lra-trip-example.
EDIT: Sorry, I forgot to add the programmatic API that allows same interactions as annotations - https://github.com/jbosstm/narayana/blob/master/rts/lra/client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java. However, note that is not in the specification and is only specific to Narayana.

How to check if the event triggers the state machine in Spring Statemachine?

Let me summarize my question as follows,
I know that the stateMachine.sendEvent(Event e) returns a boolean value representing if the event triggers a transition or not, but it also triggers the transition if true.
However, I want only to check if the state machine is triggerable by that event or not, and not to trigger the transition afterwards. Is there any way to do that?
There is no built-in method to do that, but once you retrieve an instance of a StateMachine, you can implement a method to iterate over the transitions looking for the current state and check what are the available transitions for that state. Each AbstractTransition contains a source and target state
machine.getTransitions()

How Do I get next state/event in Spring state Machine

1) I am processing a particular event from the transition, how Do I get the info about next event?
2) If I need to stop the transition from one state to another during the transition action, how Do I do that?
1) I'm guessing your processing code runs in a transition's action.
You can get from the provided StateContext the source state, the target state, and the event that caused the transition.
You can't possibly get the next event, because it wasn't sent yet.
2) I don't think that's possible.
If the transition action might fail and it means that in this scenario you should go to an altogether different state - then you should redesign your statemachine to run this code from somewhere different than the transition action.
For example from the state's action, and send a different event based on success/failure.

Any Logic 6: event triggered sourced using conditions

I am building a model simulating an order process tiggering a production flow. The production flow should be initiated once the order is placed. My idea is to use an event named "start production" that is monitoring a boolean, which is changed by the above order entity.
I am facing various issues:
When starting the simulation my startProduction variable is changing from its initial value false to true already applying the starting condition in the event
If I apply in the action of the event the command event.restart() the simulation crashes as anylogic is constantly re-checking the event condition
How can I either solve the above problems or simulate the start of production based on an order income with a conditional logic?
Since my comment was the answer, let me add the answer here too.
It is always possible to use an event to trigger actions in your model, but it's also the most ineffective way, because you constantly running code that you may not need, making your simulation slower. The best thing you can do, whenever possible is to trigger things in the actions of your blocks. In this case when the order is generated you can use the inject function to add an agent to your production flow.
On the other hand, you can only use the restart function if the mode of your event is "user control" and it's probably the reason why you were getting an error.

Restful triggering of Camunda process definitions from nodejs

I’m a beginner at Camunda/BPMN and I want to use it to control what is going on in nodejs, mostly likely using a REST API, at least for now. (Unless folks have a better idea for how nodejs should talk to Camunda.) My goal is to deliver systems where non-programmers can update the business logic in very practical ways.
I'd like to trigger the start of perhaps more-than-one process by sending a REST message, say to reflect that "a new insurance policy has been sold" and that might trigger the instantiation of say 2 processes on Monday but perhaps on Tuesday we add a third and now the same REST API call should now trigger more activity on Wednesday. (I figure it is better for nodejs to know about events but not about the process definitions. After all, my goal is to use Camunda as a sort of business logic server for my application. The less the nodejs code needs to know, the better.)
Which REST API should I be using to express the message that, say "a new insurance policy has been sold"? When I look at:
https://docs.camunda.org/manual/develop/reference/rest/signal/post-signal/
I find it very confusing. What should "name" match in the biz process definitions? I assume I don't need an executionId? I assume I can leave out tenantId?
Would some string in the message match the ID of a start event in one or more process definitions (or what has to match what)?
When I look at a process, is there an easy way to tell what variables I need to supply to start that process running?
Should I perhaps avoid using this event-oriented style of kicking off processes and just use the POST /process-definition/key/{key}/start? It would seem to me to be better form to trigger activity with events or signals or something like that rather than to have my nodejs code know about the specific process definition by name.
Should I be using events or signals in this case?
I gather that the start event should not be a "None Start Event" but I'm not clear on what type of start event TO use if I want automatic triggering based on events or signals or something? Would a "Non-interrupting - Message Start Event" be the right sort? I'm finding this confusing.
Once I have triggered the process to start, what does nodejs need to send to step the process forward from one task in that instance to the next?
Thanks!
In order to instantiate a new workflow instance you have the following possibilities:
Start exactly one instance:
Start a workflow instance by its known "key": https://docs.camunda.org/manual/develop/reference/rest/process-definition/post-start-process-instance/
Start a workflow by a message start event: https://docs.camunda.org/manual/develop/reference/rest/message/post-message/. A message can only start one specific workflow instance, it is not allowed that this is not a unique relationship. The message start event is the one you have to use in your BPMN process model. See also https://docs.camunda.org/manual/develop/reference/bpmn20/events/message-events/. This might indeed be the better approach to make your client independent of the process definition key.
Start multiple instances:
- Start a workflow instance by a BPMN signal event: https://docs.camunda.org/manual/develop/reference/rest/signal/post-signal/. The signal name could start many instances as once.
The name of the message or name of signal would be configured in the BPMN model. Both could work for your use case.
Once a process instance is started it will move automatically execute the next steps.
Probably following this example (https://blog.bernd-ruecker.com/use-camunda-without-touching-java-and-get-an-easy-to-use-rest-based-orchestration-and-workflow-7bdf25ac198e) step by step can give you some better idea?

Resources