Сохранение контекста конечного автомата в HttpSession java.io.NotSerializableException: org.springframework.statemachine.support.DefaultStateMachineContext - PullRequest
0 голосов
/ 16 мая 2019

Я создал StateMachinePersist реализацию для сохранения StateMachineContext y HttpSession:

@Suppress("UNCHECKED_CAST")
class SessionStateMachinePersist(private val session: HttpSession) : StateMachinePersist<States, String, String> {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun read(contextObj: String): StateMachineContext<States, String>?  {
        val stateMachineContext = session.getAttribute("${session.id}-$contextObj") as StateMachineContext<States, String>?
        logger.debug("Session {} has state machine context {}?", session.id, contextObj, stateMachineContext != null)
        return stateMachineContext
    }

    override fun write(context: StateMachineContext<States, String>, contextObj: String) {
        session.setAttribute("${session.id}-$contextObj", context)
    }
}

Когда он собирается сохранить DefaultStateMachineContext, он генерирует следующее исключение, поскольку DefaultStateMachineContext не сериализуем: Caused by: java.io.NotSerializableException: org.springframework.statemachine.support.DefaultStateMachineContext

Как я могу использовать реализацию StateMachineContext, которая сериализуема?

1 Ответ

0 голосов
/ 17 мая 2019

Вот как мне удалось сделать контекст конечного автомата сериализуемым и сохранить его в сеансе Http:

SerializableStateMachineContext

class SerializableStateMachineContext<S, E>(var id: String?, var childs: List<StateMachineContext<S, E>>?, var state: S?,
                                            var historyStates: Map<S, S>?, var event: E?, var eventHeaders: Map<String, Any>?,
                                            var extendedState: SerializableExtendedState?) : Serializable {

    constructor() : this(null, null, null, null, null, null, null)

}

SerializableExtendedState

class SerializableExtendedState(var variables: Map<Any, Any>) : Serializable {

    constructor() : this(mutableMapOf())

}

SessionStateMachinePersist

@Suppress("UNCHECKED_CAST")
class SessionStateMachinePersist(private val session: HttpSession) : StateMachinePersist<States, String, String> {

    private val logger = LoggerFactory.getLogger(javaClass)

    override fun read(contextObj: String): StateMachineContext<States, String>? {
        val stateMachineContext = session.getAttribute("${session.id}-$contextObj") as SerializableStateMachineContext<States, String>?
        logger.debug("Session {} has state machine context {}?", session.id, contextObj, stateMachineContext != null)
        return DefaultStateMachineContext(stateMachineContext?.childs ?: mutableListOf(), stateMachineContext?.state, stateMachineContext?.event,
                stateMachineContext?.eventHeaders, DefaultExtendedState(stateMachineContext?.extendedState?.variables ?: mutableMapOf()), stateMachineContext?.historyStates)
    }

    override fun write(context: StateMachineContext<States, String>, contextObj: String) {
        val serializableExtendedState = SerializableExtendedState(context.extendedState.variables.toMap())
        val serializableStateMachineContext = SerializableStateMachineContext(null, context.childs, context.state, context.historyStates, context.event, context.eventHeaders, serializableExtendedState)
        session.setAttribute("${session.id}-$contextObj", serializableStateMachineContext)
    }
}

Затем, где бы вы ни работали с конечным автоматом, вам просто нужно его восстановить, выполните операцию триггера исохраните это, например:

    @PostMapping(value = ["/process-input"], consumes = [MediaType.APPLICATION_JSON_VALUE], produces = [MediaType.APPLICATION_JSON_VALUE])
    @ResponseBody
    fun processInput(session: HttpSession, @RequestBody projectCreationInput: ProjectCreationInput, model: ModelMap, status: SessionStatus) {

        val stateMachinePersister = buildStateMachinePersister(session)
        stateMachinePersister.restore(stateMachine, "myid")

        ...

        triggerStateMachineExecution(projectCreationInput, event, status)

        ...

        stateMachinePersister.persist(stateMachine, "myid")

    }

    private fun buildStateMachinePersister(session: HttpSession): DefaultStateMachinePersister<States, String, String> {
        val stateMachinePersist = SessionStateMachinePersist(session)
        return DefaultStateMachinePersister(stateMachinePersist)
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...