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

Join dosen't enter when fork a substate #337

Open
924060929 opened this issue Mar 24, 2017 · 3 comments
Open

Join dosen't enter when fork a substate #337

924060929 opened this issue Mar 24, 2017 · 3 comments

Comments

@924060929
Copy link

924060929 commented Mar 24, 2017

I write a demo in spring-statemachine-recipes:

package org.springframework.statemachine.recipes.mytest;

import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.recipes.tasks.TasksHandler;

public class Main {
    public static void main(String[] args) {

        TasksHandler handler = TasksHandler.builder()
            .task("1", taskRunnable("1"))
            .task("1", "12", taskRunnable("12"))
//            .task("1", "13", taskRunnable("13"))  // note off then run, will print success
            .listener(new TasksHandler.TasksListenerAdapter() {
                @Override
                public void onTasksSuccess() {
                    System.out.println("success");
                }
            })
            .build();


        StateMachine<String, String> machine = handler.getStateMachine();
        machine.start();
        handler.runTasks();

    }

    private static Runnable taskRunnable(final String id) {
        return new Runnable() {
            @Override
            public void run() {
                System.out.println("run taskRunnable " + id);
            }
        };
    }
}

Run this code will not print ‘success’, but if you note off the note line and run, it will print 'success'

@924060929
Copy link
Author

924060929 commented Mar 25, 2017

I fix this problem by rewrite org.springframework.statemachine.config.AbstractStateMachineFactory

private StateMachine<S, E> buildMachine(Map<Object, StateMachine<S, E>> machineMap, Map<S, State<S, E>> stateMap,
			Map<S, StateHolder<S, E>> holderMap, Collection<StateData<S, E>> stateDatas, Collection<TransitionData<S, E>> transitionsData,
			BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState,
			TransitionsData<S, E> stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler, String machineId,
			UUID uuid, StateMachineModel<S, E> stateMachineModel)
			
	...
	} else if (stateData.getPseudoStateKind() == PseudoStateKind.JOIN) {
		S s = stateData.getState();
		List<S> list = stateMachineTransitions.getJoins().get(s);
		List<State<S, E>> joins = new ArrayList<State<S,E>>();

		// if join source is a regionstate, get
		// it's end states from regions
		if (list.size() == 1) {
			State<S, E> ss1 = stateMap.get(list.get(0));
			if (ss1 instanceof RegionState) { 
				Collection<Region<S, E>> regions = ((RegionState<S, E>)ss1).getRegions();
				for (Region<S, E> r : regions) {
					Collection<State<S, E>> ss2 = r.getStates();
					for (State<S, E> ss3 : ss2) {
						if (ss3.getPseudoState() != null && ss3.getPseudoState().getKind() == PseudoStateKind.END) {
							joins.add(ss3);
							continue;
						}
					}
				}
			/** ================================
                          *  I add this 'else if' to fix this problem.
                          * ================================
                          */
			} else if (ss1 instanceof StateMachineState) {
			    Collection<State<S, E>> subStates = ((StateMachineState) ss1).getSubmachine().getStates();
			    for (State<S, E> subState : subStates) {
			        if (subState.getPseudoState() != null && subState.getPseudoState().getKind() == PseudoStateKind.END) {
			            joins.add(subState);
			        }
			    }
                       }
		} else {
			for (S fs : list) {
				joins.add(stateMap.get(fs));
			}
		}

		List<JoinStateData<S, E>> joinTargets = new ArrayList<JoinStateData<S, E>>();
		Collection<TransitionData<S, E>> transitions = stateMachineTransitions.getTransitions();
		for (TransitionData<S, E> tt : transitions) {
			if (tt.getSource() == s) {
				StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(tt.getTarget()));
				if (holder.getState() == null) {
					holderMap.put(tt.getTarget(), holder);
				}
				joinTargets.add(new JoinStateData<S, E>(holder, tt.getGuard()));
			}
		}
		JoinPseudoState<S, E> pseudoState = new JoinPseudoState<S, E>(joins, joinTargets);

		state = buildStateInternal(stateData.getState(), stateData.getDeferred(), stateData.getEntryActions(),
				stateData.getExitActions(), stateData.getStateActions(), pseudoState, stateMachineModel);
		states.add(state);
		stateMap.put(stateData.getState(), state);
	}
	...
}

@jvalkeal
Copy link
Contributor

Thx, would you like to create PR? If not then I'll try to come up with a test and add this fix.

@klu2
Copy link

klu2 commented Mar 19, 2019

I am having a similar issue, this one could fix it. Is there any plan merge and close that issue?

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