Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guarded Transition for not changing State #41

Closed
tuncatunc opened this issue Jul 27, 2015 · 3 comments
Closed

Guarded Transition for not changing State #41

tuncatunc opened this issue Jul 27, 2015 · 3 comments
Assignees

Comments

@tuncatunc
Copy link

When I configure a state transition with permitIf and the guard function doesn't allow the transition
I'm getting following exception. However I except the state unchanged.

        smCfg.configure(State.STATE_0)
            .permitIf(Event.TC_setup, State.STATE_1, new FuncBoolean()
            {

                @Override
                public boolean call()
                {
                    boolean result = hdlcIo.setup(); 
                    return result;
                }
            })
java.lang.IllegalStateException: No valid leaving transitions are permitted from state 'STATE_0' for trigger 'TC_setup'. Consider ignoring the trigger.
    at com.github.oxo42.stateless4j.StateMachine$1.doIt(StateMachine.java:30)
    at com.github.oxo42.stateless4j.StateMachine.publicFire(StateMachine.java:196)
    at com.github.oxo42.stateless4j.StateMachine.fire(StateMachine.java:133)
    at com.ayes.atmgw.service.ph.fde.FdeStateMachine.setup(FdeStateMachine.java:472)
    at com.ayes.atmgw.tests.TestFdeStateMachine.test02_STATE0_TC_Setup_fails(TestFdeStateMachine.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
@rv7akro
Copy link

rv7akro commented Jan 13, 2016

I encountered the exact same problem, posted here, but then figured out the answer. For me the solution was to create two complimentary gate clauses. In one instance (the positive you-may-proceed scenario) I had a "positive" gate clause on the '.permitIf()', then a "negative" gate clause on the '.ignoreIf()'. A snippet of my configuration for the state machine where this is used looks like the following ...

    config.configure(AgentState.IDLE)
        .onEntry(stateEnter)
        .onExit(stateExit)
        .permitIf(DependenciesReady.class, AgentState.STARTING, hunkydory)
        .ignoreIf(DependenciesReady.class, snafued)
        .permit(Shutdown.class, AgentState.OFF)
        .ignore(DependenciesNotReady.class)
        .ignore(HealthNotOk.class)
        .permitIf(HealthOk.class, AgentState.STARTING, hunkydory)
        .ignoreIf(HealthOk.class, snafued)
        .ignore(Started.class)
        .ignore(Stopped.class);

Note that I had to include complimentary pairs for both the "DependenciesReady" event as well as the "HealthOk" event. Both must be true to allow the state machine controlling the life cycle for this situation progress to a READY state. Hope this helps.

@Ktar5
Copy link
Contributor

Ktar5 commented May 10, 2018

This is obviously a /very/ lame way of working around this issue. So I'll figure out a way to work this into the code so that users no longer run into this. Thanks for submitting and thanks for helping out @rv7akro

@Ktar5 Ktar5 self-assigned this May 10, 2018
@Ktar5 Ktar5 added this to the 2.6.0 milestone May 10, 2018
@Ktar5
Copy link
Contributor

Ktar5 commented May 10, 2018

Turns out that if we implement this any other way, we end up removing some portion of the functionality. I'll update the error message to reflect what I've found.

Edit: Err-- I'll see if I can just create a simplified way to fixing this issue such as permitOnlyIf() or something of the sorts.

@Ktar5 Ktar5 closed this as completed May 10, 2018
Ktar5 added a commit that referenced this issue May 10, 2018
As titled, permits the transition if guard true, but ignores the
transition if guard is false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants