Hi folks,

I'm new to scxml, so please help me understand this in case I got something
wrong.

The `SCXMLSemanticsImp` seems to only forward events to invoked machines,
if the event has been tagged with the `invokeId` of that invoked machine
and if `autoForward` is set to `true` in the invoke definition.
See:
https://github.com/apache/commons-scxml/blob/4eab174e5e8289e0ad200f9e5d56678bc7b66eee/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java#L1069

However, this seems to contradict the w3c spec:
https://www.w3.org/TR/2015/REC-scxml-20150901/#invoke
The spec states, that "When the 'autoforward' attribute is set to true, the
SCXML Processor must send an exact copy of every external event it receives
to the invoked process."

1. So it should also send the events through if the `invokeId` is not set
on the event itself.
2. On the other hand, it should also send the event through if
`autoForward` is `false`, but the `invokeId` of the event matches the
machine's `invokeId`.

The current implementation doesn't do that.

Could you please help me if my understanding is correct?

Thank you,
Torsten


P.S.: A fix I'm using in my project currently looks like the following in
kotlin (I'm currently just not sure if I need to run the finalize code in
the autoforward case as well):


class SemanticsImplFix : SCXMLSemanticsImpl() {

private fun shouldAutoForward(invoke: Invoke, event: TriggerEvent,
invokeId: String): Boolean =
(
invoke.isAutoForward &&
!(
event.name == "done.invoke.$invokeId" ||
event.name.startsWith("done.invoke.$invokeId.")
)
)

private fun forwardEvent(exctx: SCXMLExecutionContext, event: TriggerEvent,
invoke: Invoke) {
try {
exctx.getInvoker(invoke).parentEvent(event)
} catch (ie: InvokerException) {
exctx.appLog.error(ie.message, ie)
throw ModelException(ie.message, ie.cause)
}
}

override fun processInvokes(exctx: SCXMLExecutionContext, event:
TriggerEvent) {
for ((invoke, value) in exctx.invokeIds) {
if (value == event.invokeId) {
val finalize = invoke.finalize
if (finalize != null) {
if (finalize.actions.isEmpty()) {
/*
The current https://www.w3.org/TR/2015/REC-scxml-20150901/#finalize
specification for
using an empty <finalize/> (no actions) is rather complex when:
- the invoke also has a namelist attribute and/or params with a location
attribute
- and the event payload has values reachable by those namelist and/or
params 'location' attributes
then the statemachine data at those locations should be updated with the
payload values.

As the same functionality can be achieved (even if less convenient) by
using a <finalize>
with <assign/> elements for each of these locations, *and* there are no
SCXML IRP tests
for using an empty <finalize/>, the above logic is NOT implemented.
*/
} else {
executeContent(exctx, finalize)
}
}
forwardEvent(exctx, event, invoke)
} else if (shouldAutoForward(invoke, event, value)) {
forwardEvent(exctx, event, invoke)
}
}
}
}

Reply via email to