commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rahul Akolkar" <>
Subject Re: [SCXML] Weird behavior with invoke
Date Mon, 05 Feb 2007 19:11:56 GMT
On 2/2/07, Elam Birnbaum (ebirnbau) <> wrote:
> Hello everyone,
> This is my first post concerning Commons SCXML so please feel free to
> provide suggestions on the semantics of my post, the question itself, or
> the design I have chosen. Apologies in advance for the long e-mail!

Welcome, and I wouldn't worry about those things, if the thoroughness
of this email is anything to go by ;-)

> Introduction
> What I want to do is to have an SCXML document that at various points
> calls out to a Java class to perform internal things. Now I expect these
> SCXML documents to be exposed to my customers so the use of
> AbstractStateMachine is a bit limiting because of its requirements to
> have method names match state names and some additional weird behavior
> with attempting to throw events from within those methods.

Correct, that convenience class exists mainly for simple usecases
(such as the stopwatch example).

> So I have
> chosen to use <invoke> with a custom target type of "java" and my own
> Invoker class. This works very well for me because it allows me to have
> a single invoker class that can then act as my entrance point to other
> code which can perform arrange of different activities, based on which
> state it is in.


> Another function of my project is that the custom code that is executed
> by the invoke sends out messages. I then have registered message handler
> classes that are activated when I get a response message, but in
> separate threads spawned by a message handling thread pool. It is this
> message handler class that will then have to trigger SCXML events that
> cause the state machine to progress. In other words, my program has one
> thread that sets the state engine going, which enters the invoke and
> runs the invoke method of my invoker, but that invoke cannot trigger an
> event until I receive an asynchronous message. So the invoke method does
> not trigger any events within it and the state machine sits and waits.
> Then a separate thread activates the message handler, which then gets
> access to the SCXMLExecutor class and triggers an event which causes the
> special done event to be triggered for the invoke and the state machine
> to continue.

Sounds reasonable.

> This actually works fine, but I am seeing some weird
> behavior from within the Commons SCXML library that I am not sure
> whether is an indication that I am doing something wrong or an issue
> within the library.
> I will include a small class and the SCXML that I am using as an example
> of what I am doing. I will also include the output that I see and cannot
> explain.
>      public void invoke(final String source, final Map params) throws
> InvokerException {
>       System.out.println("Source = " + source);
>          try {
>        if (source.contains("foo")) {
>         System.out.println("Invoking Foo. Sending special done event.");
>            parentSCInstance.getExecutor().triggerEvent(new
> TriggerEvent(parentStateId + ".invoke.done",
> TriggerEvent.SIGNAL_EVENT));
>   public void parentEvents(TriggerEvent[] events) throws
> InvokerException {
>    System.out.println("In parentEvents for ID " + parentStateId +
>      ". There are " + events.length + " events. " +
>      "First event name = " + events[0].getName());
>    if (events[0].getName().equals("subsequent") &&
> parentStateId.equals("step2")) {
>           try {
>         System.out.println("Invoking Bar, Part 2. We are now done so we
> send the special done event.");
>            parentSCInstance.getExecutor().triggerEvent(new
> TriggerEvent(parentStateId + ".invoke.done",
> TriggerEvent.SIGNAL_EVENT));

This (turning around and triggering an event on the state machine) is
a no-no based on the following:

 * Once a state machine receives external stimulus (as one or more
events), it must complete processing before it can reach a stable
state and begin to process others stimuli. As a corollary, developer
responsibility is in not interrupting a state machine while it is
processing external event(s).

 * Commons SCXML uses JDK 1.4 and synchronized triggerEvent()
method(s). If the owning thread requests (such as in the above
example), Java will grant it the reentrant lock. Things may seem fine
here, but we've broken the first principle (above bullet).

 * <invoke> semantics work best when there is asynchronous
interaction. There shouldn't be any processing (of significance) in
any of the Invoker methods (invoke, parentEvents, cancel), just the
initiation of the processing which will asynchronously continue to
communicate with the state machine as needed.

So, in your test rig, you should change this existing pseudo:

public void invoke(...) {
  delay(); // to simulate processing

to this pseudo:

public void invoke(...) {
  new AsyncMessage(parentSCInstance.getExecutor(), eventName, delay).start();

> Questions
> So after all this, there are some questions I have:
> 1) Is it correct behavior to have the parentEvents method triggered on
> all invokes, even ones for states that have completed? Meaning I should
> possibly add a payload to the event to identify which invoke it is meant
> for and filter the handling within the parentEvent method? Or maybe is
> there a different way to trigger an event on just a single state?

No, there should be no need to add payload.

> 2) Should the special done event trigger the parentEvents method to be
> called on either it or any other invoker instance or should this special
> event simply be handled internally as one that signifies that the invoke
> is done and to move on?

Both scenarios make sense (you could have other processes listening as
well), its one of things that cannot be decided by the implementation
(we'll see what the next version of the W3C Draft says, or I will

> 3) Could it be possible that #1 and #2 are related to a bug in Commons
> SCXML that does not properly remove an invoker instance when the state
> in which the invoker resides completes? If that was done, then the
> situations described above would not happen, right? I have only been
> looking at things for a couple of weeks so I don't know if I am missing
> something in the design that requires things to be this way and I am
> simply not using the library correctly...

I suspect if you make the change above, these will generally work as expected.

> 4) Why would the cancel method be called in this scenario? Does this
> mean that even though the transitions are followed correctly, the
> history maintained by the system does not consider that step to have
> been completed, or is this just a trigger of a method in the invoker and
> just ignoring it causes no issues?

The implementation calls cancel to safeguard against zombie invoked
processes (even though invoke.done was triggered). We could change
that by special casing the invoke.done event as you indicate, I think
I will wait till the next draft (which I understand is due soon) to
make any change.

Could you please create an issue in JIRA [1] about the cancel method
in context of the invoke.done event? That'll ensure we review it
before the next release. Thanks.

> Apologies for the long e-mail, but this is a very specific situation
> that I needed to provide a lot of introduction in order for my questions
> to make sense!

Thanks for all the details, probably saved a few email round trips :-)

Finally, as mentioned on the Commons SCXML home page, the <invoke>
bits are being worked out (in the W3C Working Group, the draft lists a
few things as TBD), so the implementation also will need possible
changes and/or improvements related to the processing of <invoke>
(both semantics and syntax, such as event names) in future releases.



> Thanks,
> Elam Birnbaum
> Cisco

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message