@Test public void testNonDeterminsticTransition() throws TooBusyException { final Foo stateful = new Foo(); final MutableInt eventCnt = new MutableInt(0); String eventA = "eventA"; final State<Foo> stateA = new StateImpl<Foo>("stateA"); final State<Foo> stateB = new StateImpl<Foo>("stateB", true); stateA.addTransition(eventA, new Transition<Foo>() { public StateActionPair<Foo> getStateActionPair(Foo stateful, String event, Object... args) { State<Foo> next = null; if (eventCnt.intValue() < 2) { next = stateA; } else { next = stateB; } eventCnt.add(1); return new StateActionPairImpl<Foo>(next, null); } }); List<State<Foo>> states = new LinkedList<State<Foo>>(); states.add(stateA); states.add(stateB); Persister<Foo> persister = new MemoryPersisterImpl<Foo>(stateful, states, stateA); final FSM<Foo> fsm = new FSM<Foo>("NDFSM", persister); State<Foo> current = fsm.onEvent(stateful, eventA); assertEquals(stateA, current); current = fsm.onEvent(stateful, eventA); assertEquals(stateA, current); current = fsm.onEvent(stateful, eventA); assertEquals(stateB, current); }
public State<T> onEvent(T stateful, String event, Object ... args) throws TooBusyException { int attempts = 0; while(this.retryAttempts == -1 || attempts < this.retryAttempts) { try { State<T> current = this.getCurrentState(stateful); Transition<T> transition = this.getTransition(event, current); if (transition != null) { current = this.transition(stateful, current, event, transition, args); } else { if (logger.isDebugEnabled()) logger.debug("{}({})::{}({})->{}/noop", this.name, stateful.getClass().getSimpleName(), current.getName(), event, current.getName()); if (current.isBlocking()) { this.setCurrent(stateful, current, current); throw new WaitAndRetryException(this.retryInterval); } } return current; } catch(RetryException re) { logger.warn("{}({})::Retrying event", this.name, stateful); if (WaitAndRetryException.class.isInstance(re)) { try { Thread.sleep(((WaitAndRetryException)re).getWait()); } catch(InterruptedException ie) { throw new RuntimeException(ie); } } attempts++; } } logger.error("{}({})::Unable to process event", this.name, stateful); throw new TooBusyException(); }
FSM { public State<T> onEvent(T stateful, String event, Object ... args) throws TooBusyException { int attempts = 0; while(this.retryAttempts == -1 || attempts < this.retryAttempts) { try { State<T> current = this.getCurrentState(stateful); Transition<T> transition = this.getTransition(event, current); if (transition != null) { current = this.transition(stateful, current, event, transition, args); } else { if (logger.isDebugEnabled()) logger.debug("{}({})::{}({})->{}/noop", this.name, stateful.getClass().getSimpleName(), current.getName(), event, current.getName()); if (current.isBlocking()) { this.setCurrent(stateful, current, current); throw new WaitAndRetryException(this.retryInterval); } } return current; } catch(RetryException re) { logger.warn("{}({})::Retrying event", this.name, stateful); if (WaitAndRetryException.class.isInstance(re)) { try { Thread.sleep(((WaitAndRetryException)re).getWait()); } catch(InterruptedException ie) { throw new RuntimeException(ie); } } attempts++; } } logger.error("{}({})::Unable to process event", this.name, stateful); throw new TooBusyException(); } }
FSM { public State<T> onEvent(T stateful, String event, Object ... args) throws TooBusyException { int attempts = 0; while(this.retryAttempts == -1 || attempts < this.retryAttempts) { try { State<T> current = this.getCurrentState(stateful); Transition<T> transition = this.getTransition(event, current); if (transition != null) { current = this.transition(stateful, current, event, transition, args); } else { if (logger.isDebugEnabled()) logger.debug("{}({})::{}({})->{}/noop", this.name, stateful.getClass().getSimpleName(), current.getName(), event, current.getName()); if (current.isBlocking()) { this.setCurrent(stateful, current, current); throw new WaitAndRetryException(this.retryInterval); } } return current; } catch(RetryException re) { logger.warn("{}({})::Retrying event", this.name, stateful); if (WaitAndRetryException.class.isInstance(re)) { try { Thread.sleep(((WaitAndRetryException)re).getWait()); } catch(InterruptedException ie) { throw new RuntimeException(ie); } } attempts++; } } logger.error("{}({})::Unable to process event", this.name, stateful); throw new TooBusyException(); } FSM(String name);  FSM(Persister<T> persister);  FSM(String name, Persister<T> persister);  FSM(String name, Persister<T> persister, int retryAttempts, int retryInterval); }
FSM { public State<T> onEvent(T stateful, String event, Object ... args) throws TooBusyException { int attempts = 0; while(this.retryAttempts == -1 || attempts < this.retryAttempts) { try { State<T> current = this.getCurrentState(stateful); Transition<T> transition = this.getTransition(event, current); if (transition != null) { current = this.transition(stateful, current, event, transition, args); } else { if (logger.isDebugEnabled()) logger.debug("{}({})::{}({})->{}/noop", this.name, stateful.getClass().getSimpleName(), current.getName(), event, current.getName()); if (current.isBlocking()) { this.setCurrent(stateful, current, current); throw new WaitAndRetryException(this.retryInterval); } } return current; } catch(RetryException re) { logger.warn("{}({})::Retrying event", this.name, stateful); if (WaitAndRetryException.class.isInstance(re)) { try { Thread.sleep(((WaitAndRetryException)re).getWait()); } catch(InterruptedException ie) { throw new RuntimeException(ie); } } attempts++; } } logger.error("{}({})::Unable to process event", this.name, stateful); throw new TooBusyException(); } FSM(String name);  FSM(Persister<T> persister);  FSM(String name, Persister<T> persister);  FSM(String name, Persister<T> persister, int retryAttempts, int retryInterval); State<T> onEvent(T stateful, String event, Object ... args); int getRetryAttempts(); void setRetryAttempts(int retries); int getRetryInterval(); void setRetryInterval(int retryInterval); Persister<T> getPersister(); void setPersister(Persister<T> persister); String getName(); void setName(String name); State<T> getCurrentState(T obj); }
FSM { public State<T> onEvent(T stateful, String event, Object ... args) throws TooBusyException { int attempts = 0; while(this.retryAttempts == -1 || attempts < this.retryAttempts) { try { State<T> current = this.getCurrentState(stateful); Transition<T> transition = this.getTransition(event, current); if (transition != null) { current = this.transition(stateful, current, event, transition, args); } else { if (logger.isDebugEnabled()) logger.debug("{}({})::{}({})->{}/noop", this.name, stateful.getClass().getSimpleName(), current.getName(), event, current.getName()); if (current.isBlocking()) { this.setCurrent(stateful, current, current); throw new WaitAndRetryException(this.retryInterval); } } return current; } catch(RetryException re) { logger.warn("{}({})::Retrying event", this.name, stateful); if (WaitAndRetryException.class.isInstance(re)) { try { Thread.sleep(((WaitAndRetryException)re).getWait()); } catch(InterruptedException ie) { throw new RuntimeException(ie); } } attempts++; } } logger.error("{}({})::Unable to process event", this.name, stateful); throw new TooBusyException(); } FSM(String name);  FSM(Persister<T> persister);  FSM(String name, Persister<T> persister);  FSM(String name, Persister<T> persister, int retryAttempts, int retryInterval); State<T> onEvent(T stateful, String event, Object ... args); int getRetryAttempts(); void setRetryAttempts(int retries); int getRetryInterval(); void setRetryInterval(int retryInterval); Persister<T> getPersister(); void setPersister(Persister<T> persister); String getName(); void setName(String name); State<T> getCurrentState(T obj);  }