public void handle(FlowExecutionException exception, RequestControlContext context) { if (logger.isDebugEnabled()) { logger.debug("Handling flow execution exception " + exception, exception); } exposeException(context, exception, findRootCause(exception)); actionList.execute(context); context.execute(new Transition(getTargetStateResolver(exception))); }
public TransitionDefinition getTransition(String eventId) { for (Transition transition : transitions) { if (transition.getId().equals(eventId)) { return transition; } } return null; }
/** * Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type * in polymorphic fashion. * <p> * Simply looks up the first transition that matches the state of the context and executes it. * @param context the control context for the currently executing flow, used by this state to manipulate the flow * execution * @throws FlowExecutionException if an exception occurs in this state */ protected void doEnter(RequestControlContext context) throws FlowExecutionException { getRequiredTransition(context).execute(this, context); } }
/** * Create a new transition that matches on the specified criteria, transitioning to the target state calculated by * the provided targetStateResolver. * @param matchingCriteria the criteria for matching this transition * @param targetStateResolver the resolver of the target state of this transition * @see #setExecutionCriteria(TransitionCriteria) */ public Transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver) { setMatchingCriteria(matchingCriteria); setTargetStateResolver(targetStateResolver); }
/** * Factory method that creates a new transition, a path from one step in a flow to another. This method is an atomic * operation that returns a fully initialized transition. It encapsulates the selection of the transition * implementation as well as the transition assembly. * @param targetStateResolver the resolver of the target state of the transition (required) * @param matchingCriteria the criteria that matches the transition; may be null * @param executionCriteria the criteria that governs execution of the transition after match; may be null * @param attributes attributes to assign to the transition, which may also be used to affect transition * construction; may be null * @return the fully initialized transition instance */ public Transition createTransition(TargetStateResolver targetStateResolver, TransitionCriteria matchingCriteria, TransitionCriteria executionCriteria, AttributeMap<?> attributes) { Transition transition = new Transition(targetStateResolver); if (matchingCriteria != null) { transition.setMatchingCriteria(matchingCriteria); } if (executionCriteria != null) { transition.setExecutionCriteria(executionCriteria); } transition.getAttributes().putAll(attributes); return transition; }
public String toString() { return new ToStringCreator(this).append("on", getMatchingCriteria()).append("to", getTargetStateResolver()) .toString(); } }
public void testResumeViewStateForEventStateNotExitedNonAjaxRedirectEnabled() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); ViewState state = new ViewState(flow, "viewState", viewFactory); Transition t = new Transition(on("submit"), null); TestAction action = new TestAction(); t.setExecutionCriteria(new ActionTransitionCriteria(action)); state.getTransitionSet().add(t); MockRequestControlContext context = new MockRequestControlContext(flow); context.setAlwaysRedirectOnPause(true); state.enter(context); context = new MockRequestControlContext(context.getFlowExecutionContext()); context.setAlwaysRedirectOnPause(true); context.putRequestParameter("_eventId", "submit"); context.getFlashScope().put("foo", "bar"); state.resume(context); assertTrue(context.getFlowExecutionContext().isActive()); assertEquals(1, action.getExecutionCount()); assertFalse("Render called", context.getFlowScope().contains("renderCalled")); assertTrue(context.getMockExternalContext().getFlowExecutionRedirectRequested()); assertEquals(StubViewFactory.USER_EVENT_STATE, context.getFlashScope().get(View.USER_EVENT_STATE_ATTRIBUTE)); assertTrue(context.getFlashScope().contains("foo")); }
/** * Factory method that creates a new transition, a path from one step in a flow to another. This method is an atomic * operation that returns a fully initialized transition. It encapsulates the selection of the transition * implementation as well as the transition assembly. * @param targetStateResolver the resolver of the target state of the transition (required) * @param matchingCriteria the criteria that matches the transition; may be null * @param executionCriteria the criteria that governs execution of the transition after match; may be null * @param attributes attributes to assign to the transition, which may also be used to affect transition * construction; may be null * @return the fully initialized transition instance * @throws FlowArtifactLookupException an exception occured creating the transition */ public Transition createTransition(TargetStateResolver targetStateResolver, TransitionCriteria matchingCriteria, TransitionCriteria executionCriteria, AttributeMap attributes) throws FlowArtifactLookupException { Transition transition = new Transition(targetStateResolver); if (matchingCriteria != null) { transition.setMatchingCriteria(matchingCriteria); } if (executionCriteria != null) { transition.setExecutionCriteria(executionCriteria); } transition.getAttributeMap().putAll(attributes); return transition; }
public void testExecuteTransitionWithNullSourceState() { Flow flow = new Flow("flow"); final TransitionableState target = new TransitionableState(flow, "state 2") { protected void doEnter(RequestControlContext context) throws FlowExecutionException { } }; TargetStateResolver targetResolver = (transition, sourceState, context) -> { assertNull(sourceState); return target; }; MockRequestControlContext context = new MockRequestControlContext(flow); Transition t = new Transition(targetResolver); boolean stateChanged = t.execute(null, context); assertTrue(stateChanged); assertSame(target, context.getCurrentState()); }
public void testTransitionExecutionRefused() { Flow flow = new Flow("flow"); final TransitionableState source = new TransitionableState(flow, "state 1") { public void exit(RequestControlContext context) { exitCalled = true; } protected void doEnter(RequestControlContext context) throws FlowExecutionException { } }; final TransitionableState target = new TransitionableState(flow, "state 2") { protected void doEnter(RequestControlContext context) throws FlowExecutionException { } }; TargetStateResolver targetResolver = (transition, sourceState, context) -> { assertSame(source, sourceState); return target; }; MockRequestControlContext context = new MockRequestControlContext(flow); context.setCurrentState(source); Transition t = new Transition(targetResolver); t.setExecutionCriteria(context1 -> false); boolean stateExited = t.execute(source, context); assertFalse(stateExited); assertFalse(exitCalled); assertSame(source, context.getCurrentState()); }
public void testSmartValidatorWithHintOnTransition() { Transition transition = new Transition(); transition.setMatchingCriteria(new DefaultTransitionCriteria(new StaticExpression(eventId))); transition.getAttributes().put("validationHints", new StaticExpression("State1")); ViewState state = new ViewState(requestContext.getRootFlow(), "state2", new StubViewFactory()); state.getTransitionSet().add(transition); requestContext.setCurrentState(state); LegacyModelValidator validator = new LegacyModelValidator(); ExtendedModel model = new ExtendedModel(); ValidationHelper helper = new ValidationHelper(model, requestContext, eventId, modelName, null, codesResolver, null); helper.setValidator(validator); helper.validate(); assertTrue(validator.fallbackInvoked); assertTrue(validator.hints.length > 0); assertEquals(Model.State1.class, validator.hints[0]); }
public void testTransitionExecutingWithSecurity() { SecurityFlowExecutionListener listener = new SecurityFlowExecutionListener(); RequestContext context = new MockRequestContext(); Transition transition = new Transition(new DefaultTargetStateResolver("target")); SecurityRule rule = getSecurityRuleAnyAuthorized(); transition.getAttributes().put(SecurityRule.SECURITY_ATTRIBUTE_NAME, rule); configureSecurityContext(); listener.transitionExecuting(context, transition); }
.map(tr -> tr.getId() + " -> " + tr.getTargetStateId() + " @ " + tr.getExecutionCriteria().toString()) .collect(Collectors.toList()); if (!acts.isEmpty()) {
val targetStateId = transition.getTargetStateId(); transition.setTargetStateResolver(new DefaultTargetStateResolver(CasWebflowConstants.STATE_ID_VERIFY_TRUSTED_DEVICE)); val verifyAction = createActionState(flow, CasWebflowConstants.STATE_ID_VERIFY_TRUSTED_DEVICE, val success = (Transition) submit.getTransition(CasWebflowConstants.TRANSITION_ID_SUCCESS); if (enableDeviceRegistration) { success.setTargetStateResolver(new DefaultTargetStateResolver(CasWebflowConstants.VIEW_ID_REGISTER_DEVICE)); } else { success.setTargetStateResolver(new DefaultTargetStateResolver(CasWebflowConstants.STATE_ID_REGISTER_TRUSTED_DEVICE));
/** * Returns a list of the supported transitional criteria used to match transitions in this state. * @return the list of transitional criteria */ public TransitionCriteria[] getTransitionCriterias() { TransitionCriteria[] criterias = new TransitionCriteria[transitions.size()]; int i = 0; for (Transition transition : transitions) { criterias[i++] = transition.getMatchingCriteria(); } return criterias; }
if (canExecute(context)) { if (sourceState != null) { if (logger.isDebugEnabled()) { throw new IllegalStateException("Execution of '" + this + "' was blocked by '" + getExecutionCriteria() + "', " + "; however, no source state is set at runtime. " + "This is an illegal situation: check your flow definition.");
private void configurePasswordResetFlow(final Flow flow, final String id) { createFlowVariable(flow, FLOW_VAR_ID_PASSWORD, PasswordChangeBean.class); val binder = createStateBinderConfiguration(CollectionUtils.wrapList(FLOW_VAR_ID_PASSWORD, "confirmedPassword")); val viewState = createViewState(flow, id, id, binder); createStateModelBinding(viewState, FLOW_VAR_ID_PASSWORD, PasswordChangeBean.class); viewState.getEntryActionList().add(this.initPasswordChangeAction); val transition = createTransitionForState(viewState, CasWebflowConstants.TRANSITION_ID_SUBMIT, PASSWORD_CHANGE_ACTION); transition.getAttributes().put("bind", Boolean.TRUE); transition.getAttributes().put("validate", Boolean.TRUE); createStateDefaultTransition(viewState, id); val pswChangeAction = createActionState(flow, PASSWORD_CHANGE_ACTION, createEvaluateAction(PASSWORD_CHANGE_ACTION)); val transitionSet = pswChangeAction.getTransitionSet(); transitionSet.add(createTransition(PasswordChangeAction.PASSWORD_UPDATE_SUCCESS, CasWebflowConstants.STATE_ID_PASSWORD_UPDATE_SUCCESS)); transitionSet.add(createTransition(CasWebflowConstants.TRANSITION_ID_ERROR, id)); } }
if (canExecute(context)) { if (logger.isDebugEnabled()) { logger.debug("Executing " + this);
/** * Factory method that creates a new transition, a path from one step in a flow to another. This method is an atomic * operation that returns a fully initialized transition. It encapsulates the selection of the transition * implementation as well as the transition assembly. * @param targetStateResolver the resolver of the target state of the transition (required) * @param matchingCriteria the criteria that matches the transition; may be null * @param executionCriteria the criteria that governs execution of the transition after match; may be null * @param attributes attributes to assign to the transition, which may also be used to affect transition * construction; may be null * @return the fully initialized transition instance */ public Transition createTransition(TargetStateResolver targetStateResolver, TransitionCriteria matchingCriteria, TransitionCriteria executionCriteria, AttributeMap<?> attributes) { Transition transition = new Transition(targetStateResolver); if (matchingCriteria != null) { transition.setMatchingCriteria(matchingCriteria); } if (executionCriteria != null) { transition.setExecutionCriteria(executionCriteria); } transition.getAttributes().putAll(attributes); return transition; }
public void testResumeViewStateForEventStateNotExitedNonAjax() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); ViewState state = new ViewState(flow, "viewState", viewFactory); Transition t = new Transition(on("submit"), null); TestAction action = new TestAction(); t.setExecutionCriteria(new ActionTransitionCriteria(action)); state.getTransitionSet().add(t); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); context = new MockRequestControlContext(context.getFlowExecutionContext()); context.getFlowScope().remove("renderCalled"); context.putRequestParameter("_eventId", "submit"); context.getFlashScope().put("foo", "bar"); state.resume(context); assertTrue(context.getFlowExecutionContext().isActive()); assertEquals(1, action.getExecutionCount()); assertTrue(context.getExternalContext().isResponseComplete()); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); assertFalse(context.getFlashScope().contains("foo")); assertFalse(context.getFlashScope().contains(View.USER_EVENT_STATE_ATTRIBUTE)); }