public SimpleFlowDefinitionLocator() { new EndState(child, "state"); }
/** * Factory method that creates a new end state, a state where an executing flow session terminates. This method is * an atomic operation that returns a fully initialized state. It encapsulates the selection of the end state * implementation as well as the state assembly. * @param id the identifier to assign to the state, must be unique to its owning flow (required) * @param flow the flow that will own (contain) this state (required) * @param entryActions any state entry actions; may be null * @param finalResponseAction the state response renderer; may be null * @param outputMapper the state output mapper; may be null * @param exceptionHandlers any exception handlers; may be null * @param attributes attributes to assign to the State, which may also be used to affect state construction; may be * null * @return the fully initialized subflow state instance */ public State createEndState(String id, Flow flow, Action[] entryActions, Action finalResponseAction, Mapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) { EndState endState = new EndState(flow, id); if (finalResponseAction != null) { endState.setFinalResponseAction(finalResponseAction); } if (outputMapper != null) { endState.setOutputMapper(outputMapper); } configureCommonProperties(endState, entryActions, exceptionHandlers, attributes); return endState; }
/** * Specialization of State's <code>doEnter</code> template method that executes behavior specific to this state type * in polymorphic fashion. * <p> * This implementation pops the top (active) flow session off the execution stack, ending it, and resumes control in * the parent flow (if necessary). If the ended session is the root flow, a final response is rendered. * @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(final RequestControlContext context) throws FlowExecutionException { FlowSession activeSession = context.getFlowExecutionContext().getActiveSession(); if (activeSession.isRoot()) { // entire flow execution is ending; issue the final response if (finalResponseAction != null && !context.getExternalContext().isResponseComplete()) { ActionExecutor.execute(finalResponseAction, context); context.getExternalContext().recordResponseComplete(); } context.endActiveFlowSession(getId(), createSessionOutput(context)); } else { // there is a parent flow that will resume (this flow is a subflow) LocalAttributeMap<Object> sessionOutput = createSessionOutput(context); context.endActiveFlowSession(getId(), sessionOutput); } }
/** * Returns the subflow output map. This will invoke the output mapper (if any) to map data available in the flow * execution request context into a newly created empty map. */ protected LocalAttributeMap<Object> createSessionOutput(RequestContext context) { LocalAttributeMap<Object> output = new LocalAttributeMap<>(); if (outputMapper != null) { MappingResults results = outputMapper.map(context, output); if (results != null && results.hasErrorResults()) { throw new FlowOutputMappingException(getOwner().getId(), getId(), results); } } return output; }
/** * Add end state backed by view. * * @param flow the flow * @param id the id * @param viewFactory the view factory */ protected void createEndState(final Flow flow, final String id, final ViewFactory viewFactory) { try { final EndState endState = new EndState(flow, id); final Action finalResponseAction = new ViewFactoryActionAdapter(viewFactory); endState.setFinalResponseAction(finalResponseAction); logger.debug("Created end state state {} on flow id {}, backed by view factory {}", id, flow.getId(), viewFactory); } catch (final Exception e) { logger.error(e.getMessage(), e); } }
private MockFlowSession newFlowSession(boolean persistenceContext, FlowSession parent) { MockFlowSession flowSession = new MockFlowSession(); flowSession.setParent(parent); if (persistenceContext) { flowSession.getDefinition().getAttributes().put("persistenceContext", "true"); } EndState endState = new EndState(flowSession.getDefinitionInternal(), "success"); endState.getAttributes().put("commit", true); flowSession.setState(endState); return flowSession; }
public void testEnterEndStateWithFinalResponseRenderer() { Flow flow = new Flow("myFlow"); EndState state = new EndState(flow, "end"); StubFinalResponseAction action = new StubFinalResponseAction(); state.setFinalResponseAction(action); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); assertTrue(action.executeCalled); }
/** * Factory method that creates a new end state, a state where an executing flow session terminates. This method is * an atomic operation that returns a fully initialized state. It encapsulates the selection of the end state * implementation as well as the state assembly. * @param id the identifier to assign to the state, must be unique to its owning flow (required) * @param flow the flow that will own (contain) this state (required) * @param entryActions any state entry actions; may be null * @param viewSelector the state confirmation view selector strategy; may be null * @param outputMapper the state output mapper; may be null * @param exceptionHandlers any exception handlers; may be null * @param attributes attributes to assign to the State, which may also be used to affect state construction; may be * null * @return the fully initialized subflow state instance * @throws FlowArtifactLookupException an exception occured creating the state */ public State createEndState(String id, Flow flow, Action[] entryActions, ViewSelector viewSelector, AttributeMapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) throws FlowArtifactLookupException { EndState endState = new EndState(flow, id); if (viewSelector != null) { endState.setViewSelector(viewSelector); } if (outputMapper != null) { endState.setOutputMapper(outputMapper); } configureCommonProperties(endState, entryActions, exceptionHandlers, attributes); return endState; }
public void testEnterEndStateWithOutputMapper() { Flow flow = new Flow("myFlow") { @SuppressWarnings("unused") public void end(RequestControlContext context, MutableAttributeMap<Object> output) throws FlowExecutionException { assertEquals("foo", output.get("y")); } }; EndState state = new EndState(flow, "end"); DefaultMapper mapper = new DefaultMapper(); ExpressionParser parser = new WebFlowSpringELExpressionParser(new SpelExpressionParser()); Expression x = parser.parseExpression("flowScope.x", new FluentParserContext().evaluate(RequestContext.class)); Expression y = parser.parseExpression("y", new FluentParserContext().evaluate(MutableAttributeMap.class)); mapper.addMapping(new DefaultMapping(x, y)); state.setOutputMapper(mapper); MockRequestControlContext context = new MockRequestControlContext(flow); context.getFlowScope().put("x", "foo"); state.enter(context); }
System.out.println("Second Node is = "+secondNode); EndState endState = new EndState(); endState.setName("end"); System.out.println("End State is = "+endState); secondNode.addArrivingTransition(t3); secondNode.addLeavingTransition(t4); endState.addArrivingTransition(t4);
@Override public EndState createEndState(final Flow flow, final String id, final ViewFactory viewFactory) { if (containsFlowState(flow, id)) { LOGGER.trace("Flow [{}] already contains a definition for state id [{}]", flow.getId(), id); return (EndState) flow.getStateInstance(id); } val endState = new EndState(flow, id); if (viewFactory != null) { val finalResponseAction = new ViewFactoryActionAdapter(viewFactory); endState.setFinalResponseAction(finalResponseAction); LOGGER.trace("Created end state state [{}] on flow id [{}], backed by view factory [{}]", id, flow.getId(), viewFactory); } else { LOGGER.trace("Created end state state [{}] on flow id [{}]", id, flow.getId()); } return endState; }
public void testCancelEndState() { assertEquals("Table should only have one row", 1, getCount()); MockRequestContext context = new MockRequestContext(); MockFlowSession flowSession = new MockFlowSession(); flowSession.getDefinition().getAttributes().put("persistenceContext", "true"); jpaListener.sessionStarting(context, flowSession, null); context.setActiveSession(flowSession); assertSessionBound(); TestBean bean = new TestBean(1, "Keith Donald"); EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory); em.persist(bean); assertEquals("Table should still only have one row", 1, getCount()); EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel"); endState.getAttributes().put("commit", false); flowSession.setState(endState); jpaListener.sessionEnding(context, flowSession, "cancel", null); jpaListener.sessionEnded(context, flowSession, "success", null); assertEquals("Table should only have two rows", 1, getCount()); assertSessionNotBound(); }
public void testEnterEndStateWithFinalResponseRendererResponseAlreadyComplete() { Flow flow = new Flow("myFlow"); EndState state = new EndState(flow, "end"); StubFinalResponseAction action = new StubFinalResponseAction(); state.setFinalResponseAction(action); MockRequestControlContext context = new MockRequestControlContext(flow); context.getExternalContext().recordResponseComplete(); state.enter(context); assertFalse(action.executeCalled); }
public void testEnterEndStateTerminateFlowSession() { final Flow subflow = new Flow("mySubflow"); EndState state = new EndState(subflow, "end"); MockFlowSession session = new MockFlowSession(subflow); Flow parent = new Flow("parent"); SubflowState subflowState = new SubflowState(parent, "subflow", new AbstractGetValueExpression() { public Object getValue(Object context) throws EvaluationException { return subflow; } }); subflowState.getTransitionSet().add(new Transition(on("end"), to("end"))); new EndState(parent, "end"); MockFlowSession parentSession = new MockFlowSession(parent); parentSession.setState(subflowState); session.setParent(parentSession); MockRequestControlContext context = new MockRequestControlContext(new MockFlowExecutionContext(session)); state.enter(context); assertFalse("Active", context.getFlowExecutionContext().isActive()); }
/** * Returns the subflow output map. This will invoke the output mapper (if any) to map data available in the flow * execution request context into a newly created empty map. */ protected LocalAttributeMap createSessionOutput(RequestContext context) { LocalAttributeMap output = new LocalAttributeMap(); if (outputMapper != null) { MappingResults results = outputMapper.map(context, output); if (results != null && results.hasErrorResults()) { throw new FlowOutputMappingException(getOwner().getId(), getId(), results); } } return output; }
/** * Factory method that creates a new end state, a state where an executing flow session terminates. This method is * an atomic operation that returns a fully initialized state. It encapsulates the selection of the end state * implementation as well as the state assembly. * @param id the identifier to assign to the state, must be unique to its owning flow (required) * @param flow the flow that will own (contain) this state (required) * @param entryActions any state entry actions; may be null * @param finalResponseAction the state response renderer; may be null * @param outputMapper the state output mapper; may be null * @param exceptionHandlers any exception handlers; may be null * @param attributes attributes to assign to the State, which may also be used to affect state construction; may be * null * @return the fully initialized subflow state instance */ public State createEndState(String id, Flow flow, Action[] entryActions, Action finalResponseAction, Mapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap<?> attributes) { EndState endState = new EndState(flow, id); if (finalResponseAction != null) { endState.setFinalResponseAction(finalResponseAction); } if (outputMapper != null) { endState.setOutputMapper(outputMapper); } configureCommonProperties(endState, entryActions, exceptionHandlers, attributes); return endState; }
/** * Add end state backed by view. * * @param flow the flow * @param id the id * @param viewId the view id */ protected void addEndStateBackedByView(final Flow flow, final String id, final String viewId) { try { final EndState endState = new EndState(flow, id); final ViewFactory viewFactory = this.flowBuilderServices.getViewFactoryCreator().createViewFactory( new LiteralExpression(viewId), this.flowBuilderServices.getExpressionParser(), this.flowBuilderServices.getConversionService(), null, this.flowBuilderServices.getValidator(), this.flowBuilderServices.getValidationHintResolver()); final Action finalResponseAction = new ViewFactoryActionAdapter(viewFactory); endState.setFinalResponseAction(finalResponseAction); LOGGER.debug("Created end state state {} on flow id {}, backed by view {}", id, flow.getId(), viewId); } catch (final Exception e) { LOGGER.error(e.getMessage(), e); } }
public void testFlowCommitsInSingleRequest() { assertEquals("Table should only have one row", 1, getCount()); MockRequestContext context = new MockRequestContext(); MockFlowSession flowSession = new MockFlowSession(); flowSession.getDefinition().getAttributes().put("persistenceContext", "true"); jpaListener.sessionStarting(context, flowSession, null); context.setActiveSession(flowSession); assertSessionBound(); TestBean bean = new TestBean(1, "Keith Donald"); EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory); em.persist(bean); assertEquals("Table should still only have one row", 1, getCount()); EndState endState = new EndState(flowSession.getDefinitionInternal(), "success"); endState.getAttributes().put("commit", true); flowSession.setState(endState); jpaListener.sessionEnding(context, flowSession, "success", null); jpaListener.sessionEnded(context, flowSession, "success", null); assertEquals("Table should only have two rows", 2, getCount()); assertSessionNotBound(); }