/** * Configure common properties for a state. */ private void configureCommonProperties(State state, Action[] entryActions, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) { state.getEntryActionList().addAll(entryActions); state.getExceptionHandlerSet().addAll(exceptionHandlers); state.getAttributes().putAll(attributes); } }
/** * Returns the de-serialized id indicating the current state of this session. */ String getStateId() { if (state == null) { return stateId; } else { return state.getId(); } }
/** * Enter this state in the provided flow control context. This implementation just calls the * {@link #doEnter(RequestControlContext)} hook method, which should be implemented by subclasses, after executing * the entry actions. * @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 */ public final void enter(RequestControlContext context) throws FlowExecutionException { if (logger.isDebugEnabled()) { logger.debug("Entering state '" + getId() + "' of flow '" + getFlow().getId() + "'"); } context.setCurrentState(this); doPreEntryActions(context); entryActionList.execute(context); doEnter(context); }
@SuppressWarnings("unchecked") public MutableAttributeMap<Object> getViewScope() throws IllegalStateException { if (state == null) { throw new IllegalStateException("The current state of this flow '" + definition.getId() + "' is [null] - cannot access view scope"); } if (!state.isViewState()) { throw new IllegalStateException("The current state '" + state.getId() + "' of this flow '" + definition.getId() + "' is not a view state - view scope not accessible"); } return (MutableAttributeMap<Object>) scope.get(VIEW_MAP_ATTRIBUTE); }
/** * Add given state definition to this flow definition. Marked protected, as this method is to be called by the * (privileged) state definition classes themselves during state construction as part of a FlowBuilder invocation. * @param state the state to add * @throws IllegalArgumentException when the state cannot be added to the flow; for instance if another state shares * the same id as the one provided or if given state already belongs to another flow */ protected void add(State state) throws IllegalArgumentException { if (this != state.getFlow() && state.getFlow() != null) { throw new IllegalArgumentException("State " + state + " cannot be added to this flow '" + getId() + "' -- it already belongs to a different flow: '" + state.getFlow().getId() + "'"); } if (this.states.contains(state) || this.containsState(state.getId())) { throw new IllegalArgumentException("This flow '" + getId() + "' already contains a state with id '" + state.getId() + "' -- state ids must be locally unique to the flow definition; " + "existing state-ids of this flow include: " + StylerUtils.style(getStateIds())); } boolean firstAdd = states.isEmpty(); states.add(state); if (firstAdd) { setStartState(state); } }
public String toString() { ToStringCreator creator = new ToStringCreator(this).append("id", getId()).append("flow", flow.getId()) .append("entryActionList", entryActionList).append("exceptionHandlerSet", exceptionHandlerSet); appendToString(creator); return creator.toString(); }
val stateMap = new LinkedHashMap<String, Object>(); if (!state.getAttributes().asMap().isEmpty()) { stateMap.put("attributes", CollectionUtils.wrap(state.getAttributes())); if (StringUtils.isNotBlank(state.getCaption())) { stateMap.put("caption", state.getCaption()); var acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false) .map(Object::toString) .collect(Collectors.toList()); stateMap.put("isEndState", Boolean.TRUE); if (state.isViewState()) { stateMap.put("isViewState", state.isViewState()); stateMap.put("isRedirect", ((ViewState) state).getRedirect()); acts = StreamSupport.stream(state.getEntryActionList().spliterator(), false) .map(Object::toString) .collect(Collectors.toList());
/** * Enter this state in the provided flow control context. This implementation just calls the * {@link #doEnter(RequestControlContext)} hook method, which should be implemented by subclasses, after executing * the entry actions. * @param context the control context for the currently executing flow, used by this state to manipulate the flow * execution * @return a view selection containing model and view information needed to render the results of the state * processing * @throws FlowExecutionException if an exception occurs in this state */ public final ViewSelection enter(RequestControlContext context) throws FlowExecutionException { if (logger.isDebugEnabled()) { logger.debug("Entering state '" + getId() + "' of flow '" + getFlow().getId() + "'"); } context.setCurrentState(this); entryActionList.execute(context); return doEnter(context); }
public void testHandledException() { state.getExceptionHandlerSet().add(new FlowExecutionExceptionHandler() { public boolean canHandle(FlowExecutionException exception) { return true; } public void handle(FlowExecutionException exception, RequestControlContext context) { handled = true; } }); FlowExecutionException e = new FlowExecutionException(flow.getId(), state.getId(), "Whatev"); MockRequestControlContext context = new MockRequestControlContext(flow); assertTrue(state.handleException(e, context)); assertTrue(handled); }
/** * Configure common properties for a state. */ private void configureCommonProperties(State state, Action[] entryActions, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) { state.getEntryActionList().addAll(entryActions); state.getExceptionHandlerSet().addAll(exceptionHandlers); state.getAttributeMap().putAll(attributes); } }
/** * Set the current state of this flow session. * @param state the state that is currently active in this flow session * @see FlowExecutionImpl#setCurrentState(State) * @see FlowExecutionImplStateRestorer */ void setState(State state) { Assert.notNull(state, "The state is required"); Assert.isTrue(flow == state.getOwner(), "The state does not belong to the flow associated with this flow session"); this.state = state; this.stateId = state.getId(); }
/** * Handle an exception that occurred in this state during the context of the current flow execution request. * @param exception the exception that occurred * @param context the flow execution control context */ public boolean handleException(FlowExecutionException exception, RequestControlContext context) { return getExceptionHandlerSet().handleException(exception, context); }
public void testStateEnterWithEntryAction() { TestAction action = new TestAction(); state.getEntryActionList().add(action); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); assertEquals(state, context.getCurrentState()); assertTrue(action.isExecuted()); assertTrue(entered); assertEquals(1, action.getExecutionCount()); }
public void testCouldNotHandleException() { FlowExecutionException e = new FlowExecutionException(flow.getId(), state.getId(), "Whatev"); MockRequestControlContext context = new MockRequestControlContext(flow); assertFalse(state.handleException(e, context)); }
/** * Try to handle given exception using execution exception handlers registered at the state level. Returns null if * no handler handled the exception. * @return true if the exception was handled */ private boolean tryStateHandlers(FlowExecutionException exception, RequestControlContext context) { if (exception.getStateId() != null) { State state = getActiveSessionInternal().getFlow().getStateInstance(exception.getStateId()); return state.handleException(exception, context); } else { return false; } }
/** * Start a new session for this flow in its start state. This boils down to the following: * <ol> * <li>Create (setup) all registered flow variables ({@link #addVariable(FlowVariable)}) in flow scope.</li> * <li>Map provided input data into the flow. Typically data will be mapped into flow scope using the registered * input mapper ({@link #setInputMapper(Mapper)}).</li> * <li>Execute all registered start actions ( {@link #getStartActionList()}).</li> * <li>Enter the configured start state ({@link #setStartState(State)})</li> * </ol> * @param context the flow execution control context * @param input eligible input into the session * @throws FlowExecutionException when an exception occurs starting the flow */ public void start(RequestControlContext context, MutableAttributeMap<?> input) throws FlowExecutionException { assertStartStateSet(); createVariables(context); if (inputMapper != null) { MappingResults results = inputMapper.map(input, context); if (results != null && results.hasErrorResults()) { throw new FlowInputMappingException(getId(), results); } } startActionList.execute(context); startState.enter(context); }
public void buildStates() throws FlowBuilderException { State state = new EndState(getFlow(), "end"); state.getEntryActionList().add(new AbstractAction() { protected Event doExecute(RequestContext context) throws Exception { throw new NullPointerException("failing"); } }); new TransitionableState(getFlow(), "showError") { protected void doEnter(RequestControlContext context) throws FlowExecutionException { } }; }
/** * Set the current state of this flow session. * @param state the state that is currently active in this flow session * @see FlowExecutionImpl#setCurrentState(State) * @see FlowExecutionImplStateRestorer */ void setState(State state) { Assert.notNull(state, "The state is required"); Assert.isTrue(flow == state.getOwner(), "The state does not belong to the flow associated with this flow session"); this.state = state; }
public void testAddStates() { Flow flow = new Flow("myFlow"); new EndState(flow, "myState1"); new EndState(flow, "myState2"); assertEquals("Wrong start state:", "myState1", flow.getStartState().getId()); assertEquals("State count wrong:", 2, flow.getStateCount()); assertTrue(flow.containsState("myState1")); assertTrue(flow.containsState("myState2")); State state = flow.getStateInstance("myState1"); assertEquals("Wrong flow:", flow.getId(), state.getFlow().getId()); assertEquals("Wrong state:", "myState1", flow.getState("myState1").getId()); assertEquals("Wrong state:", "myState2", flow.getState("myState2").getId()); }