FlowHandler
is the extension point that can be used to customize how flows are executed in a HTTP servlet environment.
A FlowHandler
is used by the FlowHandlerAdapter
and is responsible for:
Returning the id
of a flow definition to execute
Creating the input to pass new executions of that flow as they are started
Handling outcomes returned by executions of that flow as they end
Handling any exceptions thrown by executions of that flow as they occur
These responsibilities are illustrated in the definition of the org.springframework.mvc.servlet.FlowHandler
interface:
public interface FlowHandler { public String getFlowId(); public MutableAttributeMap createExecutionInputMap(HttpServletRequest request); public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request, HttpServletResponse response); public String handleException(FlowException e, HttpServletRequest request, HttpServletResponse response); }
To implement a FlowHandler, subclass AbstractFlowHandler
. All these operations are optional, and if not implemented
the defaults will apply. You only need to override the methods that you need. Specifically:
Override getFlowId(HttpServletRequest)
when the id of your flow cannot be directly derived from the HTTP request.
By default, the id of the flow to execute is derived from the pathInfo portion of the request URI.
For example, http://localhost/app/hotels/booking?hotelId=1
results in a flow id of hotels/booking
by default.
Override createExecutionInputMap(HttpServletRequest)
when you need fine-grained control over extracting
flow input parameters from the HttpServletRequest. By default, all request parameters are treated as flow input parameters.
Override handleExecutionOutcome
when you need to handle specific flow execution outcomes in a custom manner.
The default behavior sends a redirect to the ended flow's URL to restart a new execution of the flow.
Override handleException
when you need fine-grained control over unhandled flow exceptions.
The default behavior attempts to restart the flow when a client attempts to access an ended or expired flow execution.
Any other exception is rethrown to the Spring MVC ExceptionResolver infrastructure by default.
A common interaction pattern between Spring MVC And Web Flow is for a Flow to redirect to a @Controller when it ends. FlowHandlers allow this to be done without coupling the flow definition itself with a specific controller URL. An example FlowHandler that redirects to a Spring MVC Controller is shown below:
public class BookingFlowHandler extends AbstractFlowHandler { public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request, HttpServletResponse response) { if (outcome.getId().equals("bookingConfirmed")) { return "/booking/show?bookingId=" + outcome.getOutput().get("bookingId"); } else { return "/hotels/index"; } } }
Since this handler only needs to handle flow execution outcomes in a custom manner, nothing else is overridden.
The bookingConfirmed
outcome will result in a redirect to show the new booking.
Any other outcome will redirect back to the hotels index page.
To install a custom FlowHandler, simply deploy it as a bean. The bean name must match the id of the flow the handler should apply to.
<bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />
With this configuration, accessing the resource /hotels/booking
will launch the hotels/booking
flow using the custom BookingFlowHandler.
When the booking flow ends, the FlowHandler will process the flow execution outcome and redirect to the appropriate controller.
A FlowHandler handling a FlowExecutionOutcome or FlowException returns a String
to indicate the resource to redirect to after handling.
In the previous example, the BookingFlowHandler
redirects to the booking/show
resource URI for bookingConfirmed
outcomes,
and the hotels/index
resource URI for all other outcomes.
By default, returned resource locations are relative to the current servlet mapping. This allows for a flow handler to redirect to other Controllers in the application using relative paths. In addition, explicit redirect prefixes are supported for cases where more control is needed.
The explicit redirect prefixes supported are:
servletRelative:
- redirect to a resource relative to the current servlet
contextRelative:
- redirect to a resource relative to the current web application context path
serverRelative:
- redirect to a resource relative to the server root
http://
or https://
- redirect to a fully-qualified resource URI
These same redirect prefixes are also supported within a flow definition when using the externalRedirect:
directive in
conjunction with a view-state or end-state; for example, view="externalRedirect:http://springframework.org"