Spring state machine to manage JPA entity
Asked Answered
C

2

6

I have a Task JPA @Entity which has field state - so it looks like state machine could be good abstraction to work with. The state may change by calling a REST endpoint in form like PUT /api/tasks/{id}/state. I wanted to utilize the concept of Actions, Guards as it looks like nice abstractions. I guess I need something along:

  1. In the REST endpoint create (or rather restore?) the state machine in state corresponding to the current Tasks's state and associate the JPA entity with it's context so it is available for Actions which can change the state task's state field (and others) and persist it back through Repository
  2. Send the event representing transition to new state

I assume point 1. will create the machine through builder as with @EnableStateMachineFactory you cannot really create the machine in particular state (which kind of make sense). I'm unclear how to add the entity which I probably findOne in @Repository to the state machine's context.

Would that be the right approach? Is there a sample covering this? I was pretty honest in going through the existing samples and didn't find anything similar.

Contradictory answered 17/12, 2018 at 22:32 Comment(0)
A
4

You should first ask yourself - do you really, really need a state machine for this (I don't know your full use case). The StateMachine will introduce some(a lot?) complexity in your code.

That being said, here's a possible design:

1) Implement your standard SOA for the Entity (e.g. TaskController -> TaskService -> TaskRepository).

2) Create a Service (W), which solely purpose is to create events and send them to the SM. In that Service (W), you will have the SM factory injected and the TaskService (for loading the state of an existing Task).

4) When Request/Event is sent to TaskController, you will call the Service (W), which will do the following:

5) In the state machine config, you will have source, target and action associated with that event. The action will call the TaskService and update the JPA entity.

This design makes sense if you have complex business rules when the Entity needs to be updated and you want the possible states transitions to be deterministic (e.g. you have a pre-defined workflow or state diagram). The business rules before each state transition can be abstracted as guards and the SM can be the interface through which others are interacting (updating) with your JPA Entity.

For rehydrating state machine from JPA Entity, please see this answer.

Amortization answered 18/2, 2019 at 8:11 Comment(2)
If i understand correctly this suggestion will cause a spring circular dependency issue: stateMachineConfig -> taskService -> stateMachineFactoryCounterbalance
Not really - there are two ways to create state machine based on Configuration classes: EnableStateMachine and EnableStateMachineFactory. When you use the Factory interface the configuration of the SM instances that will be returned are defined in the Factory itself (overriding the appropriate 'configure' methods). So it should look like "taskService -> stateMachineFactory".Amortization
T
-4

May I suggest the tutorial at Building REST Services with Spring? If you work all the way through it, you will see how to add actions that depend on the state of the object while creating a REST-based service.

Tachymetry answered 17/12, 2018 at 22:40 Comment(3)
Thanks! I actually built a lot of rest services already. The point is that you need check whether transition state -> state is allowed and apply correct transition action. This is exactly where state machine could save you effort (hope)Contradictory
The tutorial I mentioned includes a discussion and code for ResourceAssemblers, which enable you to write code to specify which actions are valid based on the state of the object being assembled, which is why I suggested the tutorial.Tachymetry
Without any offence - this is 100% off-topic :) Thanks for trying to help though.Contradictory

© 2022 - 2024 — McMap. All rights reserved.