Hi Francis,
There are a few things not right or needed in your approach below.
I've provided comments inline.
On 16-04-14 15:07, [email protected] wrote:
Hi all,
I would like to know the best practice to serialize/deserialize SCXML fsm.
I do this during the creation of the SCXML executor, scInstace is the
serialized context:
List<CustomAction> customActions = new ArrayList<CustomAction>();
CustomAction ca =
new CustomAction("http://my.custom-actions.domain/CUSTOM1",
"hello", Hello.class);
customActions.add(ca);
JexlEvaluator evaluator = new JexlEvaluator();
try {
scxml = SCXMLReader.read(StopWatch.class.getClassLoader().
} catch (Exception e) {
e.printStackTrace();
throw e;
}
executor = null;
try {
executor = new SCXMLExecutor(evaluator, null, new
SimpleErrorReporter());
While you can recreate SCXMLExecutor each time, this is not the intended usage.
The SCXMLExecutor holds the external event queue. If you are using Invokers, and
you *do* in your example, then these might still be (kept) 'running' while the
state machine itself is currently stabilized. So after a return from go() or
triggerEvent(). And these invokers might send back events into the external
queue for further processing. So then you should keep hold of the SCXMLExecutor
instance, across serialization/deserialization of the SCInstance.
If you don't use Invokers, or don't expect them to still be running after the
state machine stabilized (which might be the case in your example?) then I guess
recreating the SCXMLExecutor is fine. But then you should not set the
statemachine again (after attachIstance) as that will re-initialize the
SCInstance itself. Same goes for calling go() again or otherwise re-initializing
the current state. What would be the point of serializing in that case anyway?
Note also, the statemachine is automatically serialized together with the
SCInstance, so you actually don't need to set it again.
if (scInstance != null) {
// serialized context use it
executor.attachInstance(scInstance);
executor.registerInvokerClass("x-test",
DummyInvoker.class);
executor.setStateMachine(scxml);
this shouldn't be done as it will re-initialize the SCInstance state
executor.go();
this does the same, so definitely shouldn't be done either, because this way
there is no 'state' retained from what you serialized before
setInitialState(executor, "paused");
same goes for this: if you re-attach the instance, I assume you would want to
'return' in the same state you left off, right?
} else {
// new context
Context rootContext = new JexlContext();
rootContext.set("var1", "value1");
executor.registerInvokerClass("x-test",
DummyInvoker.class);
executor.setStateMachine(scxml);
executor.setRootContext(rootContext);
executor.go();
This initialization part is fine
}
} catch (ModelException me) {
// Executor initialization failed, because the
// state machine specified has inconsistencies
me.printStackTrace();
}
I serialize executor.detachInstance(). It's seem to work, but is it the right
way to restart a SCXML 'session' ?
See comments above. You're almost good but especially need to think about the
Invoker use-cases and if that might require you to keep hold of the
SCXMLExecutor instance.
Regards, Ate
Thanks
Francis.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]