353.7fd27c0f.js 24.7 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1
(window.webpackJsonp=window.webpackJsonp||[]).push([[353],{778:function(e,t,n){"use strict";n.r(t);var a=n(56),o=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"_11-spring-mvc-integration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-spring-mvc-integration"}},[e._v("#")]),e._v(" 11. Spring MVC Integration")]),e._v(" "),n("h2",{attrs:{id:"_11-1-introduction"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-1-introduction"}},[e._v("#")]),e._v(" 11.1. Introduction")]),e._v(" "),n("p",[e._v("This chapter shows how to integrate Web Flow into a Spring MVC web\napplication. The "),n("code",[e._v("booking-mvc")]),e._v(" sample application is a good\nreference for Spring MVC with Web Flow. This application is a simplified\ntravel site that allows users to search for and book hotel rooms.")]),e._v(" "),n("h2",{attrs:{id:"_11-2-configuring-web-xml"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-2-configuring-web-xml"}},[e._v("#")]),e._v(" 11.2. Configuring web.xml")]),e._v(" "),n("p",[e._v("The first step to using Spring MVC is to configure the"),n("code",[e._v("DispatcherServlet")]),e._v(" in "),n("code",[e._v("web.xml")]),e._v(". You typically do\nthis once per web application.")]),e._v(" "),n("p",[e._v("The example below maps all requests that begin with"),n("code",[e._v("/spring/")]),e._v(" to the DispatcherServlet. An "),n("code",[e._v("init-param")]),e._v("is used to provide the "),n("code",[e._v("contextConfigLocation")]),e._v(". This is the\nconfiguration file for the web application.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("<servlet>\n\t<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>\n\t<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n\t<init-param>\n\t\t<param-name>contextConfigLocation</param-name>\n\t\t<param-value>/WEB-INF/web-application-config.xml</param-value>\n\t</init-param>\n</servlet>\n\n<servlet-mapping>\n\t<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>\n\t<url-pattern>/spring/*</url-pattern>\n</servlet-mapping>\n")])])]),n("h2",{attrs:{id:"_11-3-dispatching-to-flows"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-3-dispatching-to-flows"}},[e._v("#")]),e._v(" 11.3. Dispatching to flows")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("DispatcherServlet")]),e._v(" maps requests for application\nresources to handlers. A flow is one type of handler.")]),e._v(" "),n("h3",{attrs:{id:"_11-3-1-registering-the-flowhandleradapter"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-3-1-registering-the-flowhandleradapter"}},[e._v("#")]),e._v(" 11.3.1. Registering the FlowHandlerAdapter")]),e._v(" "),n("p",[e._v("The first step to dispatching requests to flows is to enable flow\nhandling within Spring MVC. To this, install the"),n("code",[e._v("FlowHandlerAdapter")]),e._v(":")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('\x3c!-- Enables FlowHandler URL mapping --\x3e\n<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">\n\t<property name="flowExecutor" ref="flowExecutor" />\n</bean>\n\t\t\t\n')])])]),n("h3",{attrs:{id:"_11-3-2-defining-flow-mappings"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-3-2-defining-flow-mappings"}},[e._v("#")]),e._v(" 11.3.2. Defining flow mappings")]),e._v(" "),n("p",[e._v("Once flow handling is enabled, the next step is to map specific\napplication resources to your flows. The simplest way to do this is to\ndefine a "),n("code",[e._v("FlowHandlerMapping")]),e._v(":")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('\x3c!-- Maps request paths to flows in the flowRegistry;\n\te.g. a path of /hotels/booking looks for a flow with id "hotels/booking" --\x3e\n<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">\n\t<property name="flowRegistry" ref="flowRegistry"/>\n\t<property name="order" value="0"/>\n</bean>\n\t\t\t\n')])])]),n("p",[e._v("Configuring this mapping allows the Dispatcher to map application\nresource paths to flows in a flow registry. For example, accessing the\nresource path "),n("code",[e._v("/hotels/booking")]),e._v(" would result in a registry\nquery for the flow with id "),n("code",[e._v("hotels/booking")]),e._v('. If a flow is\nfound with that id, that flow will handle the request. If no flow is\nfound, the next handler mapping in the Dispatcher\'s ordered chain will\nbe queried or a "noHandlerFound" response will be returned.')]),e._v(" "),n("h3",{attrs:{id:"_11-3-3-flow-handling-workflow"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-3-3-flow-handling-workflow"}},[e._v("#")]),e._v(" 11.3.3. Flow handling workflow")]),e._v(" "),n("p",[e._v("When a valid flow mapping is found, the"),n("code",[e._v("FlowHandlerAdapter")]),e._v(" figures out whether to start a new\nexecution of that flow or resume an existing execution based on\ninformation present the HTTP request. There are a number of defaults\nrelated to starting and resuming flow executions the adapter\nemploys:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("HTTP request parameters are made available in the input map of\nall starting flow executions.")])]),e._v(" "),n("li",[n("p",[e._v("When a flow execution ends without sending a final response,\nthe default handler will attempt to start a new execution in the\nsame request.")])]),e._v(" "),n("li",[n("p",[e._v("Unhandled exceptions are propagated to the Dispatcher unless\nthe exception is a NoSuchFlowExecutionException. The default handler\nwill attempt to recover from a NoSuchFlowExecutionException by\nstarting over a new execution.")])])]),e._v(" "),n("p",[e._v("Consult the API documentation for "),n("code",[e._v("FlowHandlerAdapter")]),e._v("for more information. You may override these defaults by subclassing or\nby implementing your own FlowHandler, discussed in the next\nsection.")]),e._v(" "),n("h2",{attrs:{id:"_11-4-implementing-custom-flowhandlers"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-4-implementing-custom-flowhandlers"}},[e._v("#")]),e._v(" 11.4. Implementing custom FlowHandlers")]),e._v(" "),n("p",[n("code",[e._v("FlowHandler")]),e._v(" is the extension point that can be used to\ncustomize how flows are executed in a HTTP servlet environment. A"),n("code",[e._v("FlowHandler")]),e._v(" is used by the "),n("code",[e._v("FlowHandlerAdapter")]),e._v("and is responsible for:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Returning the "),n("code",[e._v("id")]),e._v(" of a flow definition to\nexecute")])]),e._v(" "),n("li",[n("p",[e._v("Creating the input to pass new executions of that flow as they\nare started")])]),e._v(" "),n("li",[n("p",[e._v("Handling outcomes returned by executions of that flow as they\nend")])]),e._v(" "),n("li",[n("p",[e._v("Handling any exceptions thrown by executions of that flow as\nthey occur")])])]),e._v(" "),n("p",[e._v("These responsibilities are illustrated in the definition of the"),n("code",[e._v("org.springframework.mvc.servlet.FlowHandler")]),e._v(" interface:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("public interface FlowHandler {\n\n\tpublic String getFlowId();\n\n\tpublic MutableAttributeMap createExecutionInputMap(HttpServletRequest request);\n\n\tpublic String handleExecutionOutcome(FlowExecutionOutcome outcome,\n\t\tHttpServletRequest request, HttpServletResponse response);\n\n\tpublic String handleException(FlowException e,\n\t\tHttpServletRequest request, HttpServletResponse response);\n}\n\t\t\n")])])]),n("p",[e._v("To implement a FlowHandler, subclass"),n("code",[e._v("AbstractFlowHandler")]),e._v(". All these operations are optional, and\nif not implemented the defaults will apply. You only need to override the\nmethods that you need. Specifically:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("Override "),n("code",[e._v("getFlowId(HttpServletRequest)")]),e._v(" when the id\nof your flow cannot be directly derived from the HTTP request. By\ndefault, the id of the flow to execute is derived from the pathInfo\nportion of the request URI. For example,"),n("code",[e._v("http://localhost/app/hotels/booking?hotelId=1")]),e._v(" results in\na flow id of "),n("code",[e._v("hotels/booking")]),e._v(" by default.")])]),e._v(" "),n("li",[n("p",[e._v("Override"),n("code",[e._v("createExecutionInputMap(HttpServletRequest)")]),e._v(" when you need\nfine-grained control over extracting flow input parameters from the\nHttpServletRequest. By default, all request parameters are treated as\nflow input parameters.")])]),e._v(" "),n("li",[n("p",[e._v("Override "),n("code",[e._v("handleExecutionOutcome")]),e._v(" when you need to\nhandle specific flow execution outcomes in a custom manner. The\ndefault behavior sends a redirect to the ended flow's URL to restart a\nnew execution of the flow.")])]),e._v(" "),n("li",[n("p",[e._v("Override "),n("code",[e._v("handleException")]),e._v(" when you need fine-grained\ncontrol over unhandled flow exceptions. The default behavior attempts\nto restart the flow when a client attempts to access an ended or\nexpired flow execution. Any other exception is rethrown to the Spring\nMVC ExceptionResolver infrastructure by default.")])])]),e._v(" "),n("h3",{attrs:{id:"_11-4-1-example-flowhandler"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-4-1-example-flowhandler"}},[e._v("#")]),e._v(" 11.4.1. Example FlowHandler")]),e._v(" "),n("p",[e._v("A common interaction pattern between Spring MVC And Web Flow is\nfor a Flow to redirect to a @Controller when it ends. FlowHandlers allow\nthis to be done without coupling the flow definition itself with a\nspecific controller URL. An example FlowHandler that redirects to a\nSpring MVC Controller is shown below:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('public class BookingFlowHandler extends AbstractFlowHandler {\n\tpublic String handleExecutionOutcome(FlowExecutionOutcome outcome,\n\t\t\t\t\t\t\t\t\t\tHttpServletRequest request, HttpServletResponse response) {\n\t\tif (outcome.getId().equals("bookingConfirmed")) {\n\t\t\treturn "/booking/show?bookingId=" + outcome.getOutput().get("bookingId");\n\t\t} else {\n\t\t\treturn "/hotels/index";\n\t\t}\n\t}\n}\n\t\t\t\n')])])]),n("p",[e._v("Since this handler only needs to handle flow execution outcomes in\na custom manner, nothing else is overridden. The"),n("code",[e._v("bookingConfirmed")]),e._v(" outcome will result in a redirect to show\nthe new booking. Any other outcome will redirect back to the hotels\nindex page.")]),e._v(" "),n("h3",{attrs:{id:"_11-4-2-deploying-a-custom-flowhandler"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-4-2-deploying-a-custom-flowhandler"}},[e._v("#")]),e._v(" 11.4.2. Deploying a custom FlowHandler")]),e._v(" "),n("p",[e._v("To install a custom FlowHandler, simply deploy it as a bean. The\nbean name must match the id of the flow the handler should apply\nto.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />\n\t\t\t\n')])])]),n("p",[e._v("With this configuration, accessing the resource"),n("code",[e._v("/hotels/booking")]),e._v(" will launch the "),n("code",[e._v("hotels/booking")]),e._v("flow using the custom BookingFlowHandler. When the booking flow ends,\nthe FlowHandler will process the flow execution outcome and redirect to\nthe appropriate controller.")]),e._v(" "),n("h3",{attrs:{id:"_11-4-3-flowhandler-redirects"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-4-3-flowhandler-redirects"}},[e._v("#")]),e._v(" 11.4.3. FlowHandler Redirects")]),e._v(" "),n("p",[e._v("A FlowHandler handling a FlowExecutionOutcome or FlowException\nreturns a "),n("code",[e._v("String")]),e._v(" to indicate the resource to redirect to\nafter handling. In the previous example, the"),n("code",[e._v("BookingFlowHandler")]),e._v(" redirects to the"),n("code",[e._v("booking/show")]),e._v(" resource URI for "),n("code",[e._v("bookingConfirmed")]),e._v("outcomes, and the "),n("code",[e._v("hotels/index")]),e._v(" resource URI for all other\noutcomes.")]),e._v(" "),n("p",[e._v("By default, returned resource locations are relative to the\ncurrent servlet mapping. This allows for a flow handler to redirect to\nother Controllers in the application using relative paths. In addition,\nexplicit redirect prefixes are supported for cases where more control is\nneeded.")]),e._v(" "),n("p",[e._v("The explicit redirect prefixes supported are:")]),e._v(" "),n("ul",[n("li",[n("p",[n("code",[e._v("servletRelative:")]),e._v(" - redirect to a resource\nrelative to the current servlet")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("contextRelative:")]),e._v(" - redirect to a resource\nrelative to the current web application context path")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("serverRelative:")]),e._v(" - redirect to a resource relative\nto the server root")])]),e._v(" "),n("li",[n("p",[n("code",[e._v("http://")]),e._v(" or "),n("code",[e._v("https://")]),e._v(" - redirect to a\nfully-qualified resource URI")])])]),e._v(" "),n("p",[e._v("These same redirect prefixes are also supported within a flow\ndefinition when using the "),n("code",[e._v("externalRedirect:")]),e._v(" directive in\nconjunction with a view-state or end-state; for example,"),n("code",[e._v('view="externalRedirect:http://springframework.org"')])]),e._v(" "),n("h2",{attrs:{id:"_11-5-view-resolution"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-5-view-resolution"}},[e._v("#")]),e._v(" 11.5. View Resolution")]),e._v(" "),n("p",[e._v("Web Flow 2 maps selected view identifiers to files located within\nthe flow's working directory unless otherwise specified. For existing\nSpring MVC + Web Flow applications, an external "),n("code",[e._v("ViewResolver")]),e._v("is likely already handling this mapping for you. Therefore, to continue\nusing that resolver and to avoid having to change how your existing flow\nviews are packaged, configure Web Flow as follows:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">\n\t<webflow:location path="/WEB-INF/hotels/booking/booking.xml" />\n</webflow:flow-registry>\n\n<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>\n\n<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">\n\t<property name="viewResolvers" ref="myExistingViewResolverToUseForFlows"/>\n</bean>\n\t\t\n')])])]),n("p",[e._v("The MvcViewFactoryCreator is the factory that allows you to\nconfigure how the Spring MVC view system is used inside Spring Web Flow.\nUse it to configure existing ViewResolvers, as well as other services such\nas a custom MessageCodesResolver. You may also enable data binding use\nSpring MVC's native BeanWrapper by setting the"),n("code",[e._v("useSpringBinding")]),e._v(" flag to true. This is an alternative to\nusing the Unified EL for view-to-model data binding. See the\nJavaDoc API of this class for more information.")]),e._v(" "),n("h2",{attrs:{id:"_11-6-signaling-an-event-from-a-view"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-6-signaling-an-event-from-a-view"}},[e._v("#")]),e._v(" 11.6. Signaling an event from a View")]),e._v(" "),n("p",[e._v("When a flow enters a view-state it pauses, redirects the user to its\nexecution URL, and waits for a user event to resume. Events are generally\nsignaled by activating buttons, links, or other user interface commands.\nHow events are decoded server-side is specific to the view technology in\nuse. This section shows how to trigger events from HTML-based views\ngenerated by templating engines such as JSP, Velocity, or\nFreemarker.")]),e._v(" "),n("h3",{attrs:{id:"_11-6-1-using-a-named-html-button-to-signal-an-event"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-6-1-using-a-named-html-button-to-signal-an-event"}},[e._v("#")]),e._v(" 11.6.1. Using a named HTML button to signal an event")]),e._v(" "),n("p",[e._v("The example below shows two buttons on the same form that signal"),n("code",[e._v("proceed")]),e._v(" and "),n("code",[e._v("cancel")]),e._v(" events when clicked,\nrespectively.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<input type="submit" name="_eventId_proceed" value="Proceed" />\n<input type="submit" name="_eventId_cancel" value="Cancel" />\n\t\t\t\n')])])]),n("p",[e._v("When a button is pressed Web Flow finds a request parameter name\nbeginning with "),n("code",[e._v("_eventId_")]),e._v(" and treats the remaining substring\nas the event id. So in this example, submitting"),n("code",[e._v("_eventId_proceed")]),e._v(" becomes "),n("code",[e._v("proceed")]),e._v(". This style\nshould be considered when there are several different events that can be\nsignaled from the same form.")]),e._v(" "),n("h3",{attrs:{id:"_11-6-2-using-a-hidden-html-form-parameter-to-signal-an-event"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-6-2-using-a-hidden-html-form-parameter-to-signal-an-event"}},[e._v("#")]),e._v(" 11.6.2. Using a hidden HTML form parameter to signal an event")]),e._v(" "),n("p",[e._v("The example below shows a form that signals the"),n("code",[e._v("proceed")]),e._v(" event when submitted:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<input type="submit" value="Proceed" />\n<input type="hidden" name="_eventId" value="proceed" />\n\t\t\t\n')])])]),n("p",[e._v("Here, Web Flow simply detects the special "),n("code",[e._v("_eventId")]),e._v("parameter and uses its value as the event id. This style should only be\nconsidered when there is one event that can be signaled on the\nform.")]),e._v(" "),n("h3",{attrs:{id:"_11-6-3-using-a-html-link-to-signal-an-event"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-6-3-using-a-html-link-to-signal-an-event"}},[e._v("#")]),e._v(" 11.6.3. Using a HTML link to signal an event")]),e._v(" "),n("p",[e._v("The example below shows a link that signals the"),n("code",[e._v("cancel")]),e._v(" event when activated:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<a href="${flowExecutionUrl}&_eventId=cancel">Cancel</a>\n\t\t\t\n')])])]),n("p",[e._v("Firing an event results in a HTTP request being sent back to the\nserver. On the server-side, the flow handles decoding the event from\nwithin its current view-state. How this decoding process works is\nspecific to the view implementation. Recall a Spring MVC view\nimplementation simply looks for a request parameter named"),n("code",[e._v("_eventId")]),e._v(". If no "),n("code",[e._v("_eventId")]),e._v(" parameter is found,\nthe view will look for a parameter that starts with"),n("code",[e._v("_eventId_")]),e._v(" and will use the remaining substring as the event\nid. If neither cases exist, no flow event is triggered.")]),e._v(" "),n("h2",{attrs:{id:"_11-7-embedding-a-flow-on-a-page"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-7-embedding-a-flow-on-a-page"}},[e._v("#")]),e._v(" 11.7. Embedding A Flow On A Page")]),e._v(" "),n("p",[e._v("By default when a flow enters a view state, it executes a\nclient-side redirect before rendering the view. This approach is known as\nPOST-REDIRECT-GET. It has the advantage of separating the form processing\nfor one view from the rendering of the next view. As a result the browser\nBack and Refresh buttons work seamlessly without causing any browser\nwarnings.")]),e._v(" "),n("p",[e._v("Normally the client-side redirect is transparent from a user's\nperspective. However, there are situations where POST-REDIRECT-GET may not\nbring the same benefits. For example a flow may be embedded on a page and driven via\nAjax requests refreshing only the area of the page that belongs to the flow.\nNot only is it unnecessary to use client-side redirects in this case, it\nis also not the desired behavior with regards to keeping the surrounding\ncontent of the page intact.")]),e._v(" "),n("p",[e._v("The "),n("RouterLink",{attrs:{to:"/en/spring-web-flow/spring-js.html#spring-js-ajax"}},[e._v("Section 12.5, “Handling Ajax Requests”")]),e._v(' explains how to do\npartial rendering during Ajax requests. The focus of this section is to\nexplain how to control flow execution redirect behavior during\nAjax requests. To indicate a flow should execute in "page embedded" mode all\nyou need to do is append an extra parameter when launching the\nflow:')],1),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("/hotels/booking?mode=embedded\n")])])]),n("p",[e._v('When launched in "page embedded" mode a flow will not issue\nflow execution redirects during Ajax requests. The mode=embedded parameter\nonly needs to be passed when launching the flow. Your only other concern is\nto use Ajax requests and to render only the content required to update\nthe portion of the page displaying the flow.')]),e._v(" "),n("h3",{attrs:{id:"_11-7-1-embedded-mode-vs-default-redirect-behavior"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-7-1-embedded-mode-vs-default-redirect-behavior"}},[e._v("#")]),e._v(" 11.7.1. Embedded Mode Vs Default Redirect Behavior")]),e._v(" "),n("p",[e._v('By default Web Flow does a client-side redirect upon entering every view state.\nHowever if you remain in the same view state -- for example a transition without a "to" attribute -- during an Ajax request there will not be a client-side redirect.\nThis behavior should be quite familiar to Spring Web Flow 2 users.\nIt is appropriate for a top-level flow that supports the browser back button while still taking advantage of Ajax and partial rendering for use cases where you remain in the same view such as form validation, paging trough search results, and others.\nHowever transitions to a new view state are always followed with a client-side redirect.\nThat makes it impossible to embed a flow on a page or within a modal dialog and execute more than one view state without causing a full-page refresh.\nHence if your use case requires embedding a flow you can launch it in "embedded" mode.')]),e._v(" "),n("h3",{attrs:{id:"_11-7-2-embedded-flow-examples"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-7-2-embedded-flow-examples"}},[e._v("#")]),e._v(" 11.7.2. Embedded Flow Examples")]),e._v(" "),n("p",[e._v("If you'd like to see examples of a flow embedded on a page and within\na modal dialog please refer to the webflow-showcase project. You can check out\nthe source code locally, build it as you would a Maven project, and import\nit into Eclipse:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("cd some-directory\nsvn co https://src.springframework.org/svn/spring-samples/webflow-showcase\ncd webflow-showcase\nmvn package\n# import into Eclipse\n")])])]),n("h2",{attrs:{id:"_11-8-saving-flow-output-to-mvc-flash-scope"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#_11-8-saving-flow-output-to-mvc-flash-scope"}},[e._v("#")]),e._v(" 11.8. Saving Flow Output to MVC Flash Scope")]),e._v(" "),n("p",[e._v("Flow output can be automatically saved to MVC flash scope when an "),n("code",[e._v("end-state")]),e._v("performs an internal redirect. This is particularly useful when displaying a summary\nscreen at the end of a flow. For backwards compatibility this feature is disabled by\ndefault, to enable set "),n("code",[e._v("saveOutputToFlashScopeOnRedirect")]),e._v(" on your"),n("code",[e._v("FlowHandlerAdapter")]),e._v(" to "),n("code",[e._v("true")]),e._v(".")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('\x3c!-- Enables FlowHandler URL mapping --\x3e\n<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">\n\t<property name="flowExecutor" ref="flowExecutor" />\n\t<property name="saveOutputToFlashScopeOnRedirect" value="true" />\n</bean>\n\t\t\n')])])]),n("p",[e._v("The following example will add "),n("code",[e._v("confirmationNumber")]),e._v(" to the MVC flash scope\nbefore redirecting to the "),n("code",[e._v("summary")]),e._v(" screen.")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<end-state id="finish" view="externalRedirect:summary">\n\t<output name="confirmationNumber" value="booking.confirmationNumber" />\n</end-state>\n\t\t\n')])])])])}),[],!1,null,null,null);t.default=o.exports}}]);