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"