KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > executor > mvc > FlowController


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.webflow.executor.mvc;
17
18 import java.util.HashMap JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import javax.servlet.http.HttpServletRequest JavaDoc;
22 import javax.servlet.http.HttpServletResponse JavaDoc;
23
24 import org.springframework.beans.factory.InitializingBean;
25 import org.springframework.util.Assert;
26 import org.springframework.web.servlet.ModelAndView;
27 import org.springframework.web.servlet.mvc.AbstractController;
28 import org.springframework.web.servlet.mvc.Controller;
29 import org.springframework.web.servlet.view.RedirectView;
30 import org.springframework.webflow.context.ExternalContext;
31 import org.springframework.webflow.context.servlet.ServletExternalContext;
32 import org.springframework.webflow.execution.support.ApplicationView;
33 import org.springframework.webflow.execution.support.ExternalRedirect;
34 import org.springframework.webflow.execution.support.FlowDefinitionRedirect;
35 import org.springframework.webflow.executor.FlowExecutor;
36 import org.springframework.webflow.executor.ResponseInstruction;
37 import org.springframework.webflow.executor.support.FlowExecutorArgumentHandler;
38 import org.springframework.webflow.executor.support.FlowRequestHandler;
39 import org.springframework.webflow.executor.support.RequestParameterFlowExecutorArgumentHandler;
40 import org.springframework.webflow.executor.support.RequestPathFlowExecutorArgumentHandler;
41
42 /**
43  * Point of integration between Spring Web MVC and Spring Web Flow: a
44  * {@link Controller} that routes incoming requests to one or more managed flow
45  * executions.
46  * <p>
47  * Requests into the web flow system are handled by a {@link FlowExecutor},
48  * which this class delegates to using a {@link FlowRequestHandler} helper.
49  * Consult the JavaDoc of that class for more information on how requests are
50  * processed.
51  * <p>
52  * Note: a single <code>FlowController</code> may execute all flows of your application.
53  * <ul>
54  * <li>By default, to have this controller launch a new flow execution
55  * (conversation), have the client send a
56  * {@link FlowExecutorArgumentHandler#getFlowIdArgumentName()} request
57  * parameter indicating the flow definition to launch.
58  * <li>To have this controller participate in an existing flow execution
59  * (conversation), have the client send a
60  * {@link FlowExecutorArgumentHandler#getFlowExecutionKeyArgumentName()}
61  * request parameter identifying the conversation to participate in.
62  * See the <code>flow-launcher</code> sample application for examples of the
63  * various strategies for launching and resuming flow executions.
64  * </ul>
65  * <p>
66  * Usage example:
67  * <pre>
68  * &lt;!--
69  * Exposes flows for execution at a single request URL.
70  * The id of a flow to launch should be passed in by clients using
71  * the &quot;_flowId&quot; request parameter:
72  * e.g. /app.htm?_flowId=flow1
73  * --&gt;
74  * &lt;bean name=&quot;/app.htm&quot; class=&quot;org.springframework.webflow.executor.mvc.FlowController&quot;&gt;
75  * &lt;property name=&quot;flowExecutor&quot; ref=&quot;flowExecutor&quot;/&gt;
76  * &lt;/bean&gt;
77  * </pre>
78  * <p>
79  * It is also possible to customize the {@link FlowExecutorArgumentHandler}
80  * strategy to allow for different types of controller parameterization, for
81  * example perhaps in conjunction with a REST-style request mapper (see
82  * {@link RequestPathFlowExecutorArgumentHandler}).
83  *
84  * @see org.springframework.webflow.executor.FlowExecutor
85  * @see org.springframework.webflow.executor.support.FlowRequestHandler
86  * @see org.springframework.webflow.executor.support.FlowExecutorArgumentHandler
87  *
88  * @author Erwin Vervaet
89  * @author Keith Donald
90  */

91 public class FlowController extends AbstractController implements InitializingBean {
92
93     /**
94      * The facade for executing flows (launching new executions, and resuming
95      * existing executions).
96      */

97     private FlowExecutor flowExecutor;
98
99     /**
100      * The strategy for handling flow executor parameters.
101      */

102     private FlowExecutorArgumentHandler argumentHandler = new RequestParameterFlowExecutorArgumentHandler();
103
104     /**
105      * Create a new flow controller. Allows bean style usage.
106      * @see #setFlowExecutor(FlowExecutor)
107      * @see #setArgumentHandler(FlowExecutorArgumentHandler)
108      */

109     public FlowController() {
110         // set the cache seconds property to 0 so no pages are cached by default
111
// for flows.
112
setCacheSeconds(0);
113     }
114
115     /**
116      * Returns the flow executor used by this controller.
117      * @return the flow executor
118      */

119     public FlowExecutor getFlowExecutor() {
120         return flowExecutor;
121     }
122
123     /**
124      * Sets the flow executor to use; setting this property is required.
125      * @param flowExecutor the fully configured flow executor to use
126      */

127     public void setFlowExecutor(FlowExecutor flowExecutor) {
128         this.flowExecutor = flowExecutor;
129     }
130
131     /**
132      * Returns the flow executor argument handler used by this controller.
133      * Defaults to {@link RequestParameterFlowExecutorArgumentHandler}.
134      * @return the argument handler
135      */

136     public FlowExecutorArgumentHandler getArgumentHandler() {
137         return argumentHandler;
138     }
139
140     /**
141      * Sets the flow executor argument handler to use. The default is
142      * {@link RequestParameterFlowExecutorArgumentHandler}.
143      * @param argumentHandler the fully configured argument handler
144      */

145     public void setArgumentHandler(FlowExecutorArgumentHandler argumentHandler) {
146         this.argumentHandler = argumentHandler;
147     }
148
149     /**
150      * Sets the identifier of the default flow to launch if no flowId argument
151      * can be extracted by the configured {@link FlowExecutorArgumentHandler}
152      * during request processing.
153      * <p>
154      * This is a convenience method that sets the default flow id of the
155      * controller's argument handler. Don't use this when using
156      * {@link #setArgumentHandler(FlowExecutorArgumentHandler)}.
157      */

158     public void setDefaultFlowId(String JavaDoc defaultFlowId) {
159         this.argumentHandler.setDefaultFlowId(defaultFlowId);
160     }
161
162     public void afterPropertiesSet() {
163         Assert.notNull(flowExecutor, "The flow executor property is required");
164         Assert.notNull(argumentHandler, "The argument handler property is required");
165     }
166
167     protected ModelAndView handleRequestInternal(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
168             throws Exception JavaDoc {
169         ServletExternalContext context = new ServletExternalContext(getServletContext(), request, response);
170         ResponseInstruction responseInstruction = createRequestHandler().handleFlowRequest(context);
171         return toModelAndView(responseInstruction, context);
172     }
173
174     /**
175      * Factory method that creates a new helper for processing a request into
176      * this flow controller. The handler is a basic template encapsulating
177      * reusable flow execution request handling workflow.
178      * This implementation just creates a new {@link FlowRequestHandler}.
179      * @return the controller helper
180      */

181     protected FlowRequestHandler createRequestHandler() {
182         return new FlowRequestHandler(getFlowExecutor(), getArgumentHandler());
183     }
184
185     /**
186      * Create a ModelAndView object based on the information in the selected
187      * response instruction. Subclasses can override this to return a
188      * specialized ModelAndView or to do custom processing on it.
189      * @param response instruction the response instruction to convert
190      * @return a new ModelAndView object
191      */

192     protected ModelAndView toModelAndView(ResponseInstruction response, ExternalContext context) {
193         if (response.isApplicationView()) {
194             // forward to a view as part of an active conversation
195
ApplicationView view = (ApplicationView)response.getViewSelection();
196             Map JavaDoc model = new HashMap JavaDoc(view.getModel());
197             argumentHandler.exposeFlowExecutionContext(
198                     response.getFlowExecutionKey(), response.getFlowExecutionContext(), model);
199             return new ModelAndView(view.getViewName(), model);
200         }
201         else if (response.isFlowDefinitionRedirect()) {
202             // restart the flow by redirecting to flow launch URL
203
String JavaDoc flowUrl = argumentHandler.createFlowDefinitionUrl((FlowDefinitionRedirect)response.getViewSelection(), context);
204             return new ModelAndView(new RedirectView(flowUrl));
205         }
206         else if (response.isFlowExecutionRedirect()) {
207             // redirect to active flow execution URL
208
String JavaDoc flowExecutionUrl = argumentHandler.createFlowExecutionUrl(
209                     response.getFlowExecutionKey(), response.getFlowExecutionContext(), context);
210             return new ModelAndView(new RedirectView(flowExecutionUrl));
211         }
212         else if (response.isExternalRedirect()) {
213             // redirect to external URL
214
ExternalRedirect redirect = (ExternalRedirect)response.getViewSelection();
215             String JavaDoc externalUrl = argumentHandler.createExternalUrl(redirect, response.getFlowExecutionKey(), context);
216             return new ModelAndView(new RedirectView(externalUrl));
217         }
218         else if (response.isNull()) {
219             // no response to issue
220
return null;
221         }
222         else {
223             throw new IllegalArgumentException JavaDoc("Don't know how to handle response instruction " + response);
224         }
225     }
226 }
Popular Tags