From 477c9e335f5b7178a9bafeb3d15fc521e9b6f1aa Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Fri, 11 Apr 2008 20:26:35 +0000 Subject: [PATCH] flow handler simplification --- .../samples/booking/BookingFlowHandler.java | 6 ++---- .../webflow/context/ExternalContext.java | 2 +- .../webflow/context/portlet/FlowUrlHandler.java | 7 +++++++ .../context/portlet/PortletExternalContext.java | 2 +- .../context/servlet/ServletExternalContext.java | 2 +- .../engine/impl/RequestControlContextImpl.java | 2 +- .../webflow/mvc/portlet/AbstractFlowHandler.java | 3 +-- .../webflow/mvc/portlet/FlowHandler.java | 6 +++--- .../webflow/mvc/portlet/FlowHandlerAdapter.java | 15 ++++++++------- .../webflow/mvc/servlet/AbstractFlowHandler.java | 10 +++++----- .../webflow/mvc/servlet/FlowController.java | 10 ++++++++-- .../webflow/mvc/servlet/FlowHandler.java | 12 +++++++----- .../webflow/mvc/servlet/FlowHandlerAdapter.java | 11 ++++++++--- .../webflow/test/MockExternalContext.java | 2 +- .../webflow/test/MockRequestContext.java | 2 +- .../mvc/portlet/FlowHandlerAdapterTests.java | 13 ++++++++----- .../webflow/mvc/servlet/FlowControllerTests.java | 8 +++----- .../mvc/servlet/FlowHandlerAdapterTests.java | 6 ++---- 18 files changed, 68 insertions(+), 51 deletions(-) diff --git a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/BookingFlowHandler.java b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/BookingFlowHandler.java index 650a4dad..d701a26a 100644 --- a/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/BookingFlowHandler.java +++ b/spring-webflow-samples/booking-mvc/src/main/java/org/springframework/webflow/samples/booking/BookingFlowHandler.java @@ -3,14 +3,12 @@ package org.springframework.webflow.samples.booking; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.view.RedirectView; import org.springframework.webflow.core.collection.AttributeMap; import org.springframework.webflow.mvc.servlet.AbstractFlowHandler; public class BookingFlowHandler extends AbstractFlowHandler { - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { - return new ModelAndView(new RedirectView("/spring/hotels/index", true)); + return "/spring/hotels/index"; } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java index 4fdba354..c954411f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java @@ -99,7 +99,7 @@ public interface ExternalContext { * @param flowExecutionKey the flow execution key * @return the flow execution URL */ - public String getFlowExecutionUri(String flowId, String flowExecutionKey); + public String getFlowExecutionUrl(String flowId, String flowExecutionKey); /** * Provides access to the user's principal security object. diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/FlowUrlHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/FlowUrlHandler.java index eb0fb234..d19f59a8 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/FlowUrlHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/FlowUrlHandler.java @@ -50,6 +50,13 @@ public interface FlowUrlHandler { */ public void setFlowExecutionInSession(String flowExecutionKey, RenderRequest request); + /** + * Creates a flow execution URL suitable for use as an action URL. + * @param flowId the flow id + * @param flowExecutionKey the flow execution key + * @param response the render response + * @return the execution url + */ public String createFlowExecutionUrl(String flowId, String flowExecutionKey, RenderResponse response); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java index f24929e9..91281273 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java @@ -175,7 +175,7 @@ public class PortletExternalContext implements ExternalContext { return false; } - public String getFlowExecutionUri(String flowId, String flowExecutionKey) { + public String getFlowExecutionUrl(String flowId, String flowExecutionKey) { if (this.isRenderPhase()) { return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, (RenderResponse) response); } else { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java index d84e8ade..57028368 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java @@ -191,7 +191,7 @@ public class ServletExternalContext implements ExternalContext { return ajaxRequest; } - public String getFlowExecutionUri(String flowId, String flowExecutionKey) { + public String getFlowExecutionUrl(String flowId, String flowExecutionKey) { return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, request); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java index eba71f2d..d31f4c9a 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java @@ -174,7 +174,7 @@ class RequestControlContextImpl implements RequestControlContext { public String getFlowExecutionUrl() { String key = flowExecution.getKey() != null ? flowExecution.getKey().toString() : null; if (key != null) { - return externalContext.getFlowExecutionUri(flowExecution.getDefinition().getId(), key); + return externalContext.getFlowExecutionUrl(flowExecution.getDefinition().getId(), key); } else { return null; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/AbstractFlowHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/AbstractFlowHandler.java index 44e2cb64..c59dffbe 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/AbstractFlowHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/AbstractFlowHandler.java @@ -29,8 +29,7 @@ public class AbstractFlowHandler implements FlowHandler { return null; } - public ModelAndView handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, - RenderResponse response) { + public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, RenderResponse response) { return null; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandler.java index 953495c4..b844fbc2 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandler.java @@ -58,10 +58,10 @@ public interface FlowHandler { * @param output the output returned by the flow execution * @param request the current render request * @param response the current render response - * @return the model and view to render on the occurrence of this outcome, or null if the outcome was not handled + * @return the id of the flow to start after handling the outcome, or null if the outcome should be handled by the + * caller */ - public ModelAndView handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, - RenderResponse response); + public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, RenderResponse response); /** * Handles a flow exception that was not handled by the Web Flow system. Used by a Controller to handle a specific diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapter.java index d55d2311..435f9e95 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapter.java @@ -75,8 +75,8 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen session.removeAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE); String outcome = result.getEndedOutcome(); AttributeMap output = result.getEndedOutput(); - ModelAndView mv = flowHandler.handleFlowOutcome(outcome, output, request, response); - return mv != null ? mv : defaultHandleFlowOutcome(flowHandler, outcome, output, request, response); + String flowId = flowHandler.handleFlowOutcome(outcome, output, request, response); + return defaultHandleFlowOutcome(flowHandler, outcome, output, flowId, request, response); } else { return startFlow(request, response, flowHandler); } @@ -131,14 +131,15 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen } protected ModelAndView defaultHandleFlowOutcome(FlowHandler flowHandler, String outcome, AttributeMap output, - RenderRequest request, RenderResponse response) throws IOException { - // by default, just start the flow over passing the output as input - String flowId = flowHandler.getFlowId(); + String nextFlowId, RenderRequest request, RenderResponse response) throws IOException { + if (nextFlowId == null) { + nextFlowId = flowHandler.getFlowId(); + } if (logger.isDebugEnabled()) { - logger.debug("Restarting a new execution of ended flow '" + flowId + "'"); + logger.debug("Starting a new execution of flow '" + nextFlowId + "'"); } PortletExternalContext context = createPortletExternalContext(request, response); - flowExecutor.launchExecution(flowId, new LocalAttributeMap(output.asMap()), context); + flowExecutor.launchExecution(nextFlowId, new LocalAttributeMap(output.asMap()), context); return null; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AbstractFlowHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AbstractFlowHandler.java index b7cf5e70..7df43d4d 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AbstractFlowHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AbstractFlowHandler.java @@ -24,13 +24,13 @@ public class AbstractFlowHandler implements FlowHandler { return null; } - public ModelAndView handleException(FlowException e, HttpServletRequest request, HttpServletResponse response) { - return null; - } - - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { return null; } + public ModelAndView handleException(FlowException e, HttpServletRequest request, HttpServletResponse response) { + return null; + } + } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java index e3489a64..e2f05ca0 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; +import org.springframework.web.servlet.view.RedirectView; import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler; import org.springframework.webflow.context.servlet.FlowUrlHandler; import org.springframework.webflow.context.servlet.ServletExternalContext; @@ -268,13 +269,18 @@ public class FlowController extends AbstractController { HttpServletRequest request, HttpServletResponse response) throws IOException { FlowHandler handler = getFlowHandler(flowId); if (handler != null) { - ModelAndView result = handler.handleExecutionOutcome(outcome, endedOutput, request, response); - return result != null ? result : defaultHandleFlowOutcome(flowId, outcome, endedOutput, request, response); + String location = handler.handleExecutionOutcome(outcome, endedOutput, request, response); + return location != null ? createRedirectView(location) : defaultHandleFlowOutcome(flowId, outcome, + endedOutput, request, response); } else { return defaultHandleFlowOutcome(flowId, outcome, endedOutput, request, response); } } + private ModelAndView createRedirectView(String location) { + return new ModelAndView(new RedirectView(location, true)); + } + private ModelAndView handleFlowException(FlowException e, HttpServletRequest request, HttpServletResponse response) throws IOException { String flowId = urlHandler.getFlowId(request); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandler.java index 35e6eb09..ba4e0f9a 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandler.java @@ -52,15 +52,16 @@ public interface FlowHandler { public MutableAttributeMap createExecutionInputMap(HttpServletRequest request); /** - * Handles a specific flow execution outcome. Used by a Controller to select a new view to render after the flow - * ends. + * Handles a specific flow execution outcome. Used by a Controller to get the location of the resource to redirect + * to after the outcome is handled. * @param outcome the outcome that was reached * @param output the output returned by the flow execution * @param request the current request * @param response the current response - * @return the model and view to render on the occurrence of this outcome, or null if the outcome was not handled + * @return the location of the new resource to redirect to, or null if the execution outcome was not handled and + * should be handled by the caller */ - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response); /** @@ -70,7 +71,8 @@ public interface FlowHandler { * the flow executor system if no execution could be restored. * @param request the current request * @param response the current response - * @return the model and view to render on the occurrence of this exception, or null if the exception is not handled + * @return the model and view to render on the occurrence of this exception, or null if the exception was not + * handled and should be handled by the caller */ public ModelAndView handleException(FlowException e, HttpServletRequest request, HttpServletResponse response); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java index f9c928c7..23a65976 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.web.context.support.WebApplicationObjectSupport; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.view.RedirectView; import org.springframework.webflow.context.servlet.DefaultFlowUrlHandler; import org.springframework.webflow.context.servlet.FlowUrlHandler; import org.springframework.webflow.context.servlet.ServletExternalContext; @@ -224,16 +225,20 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H sendRedirect(context, request, response, context.getExternalRedirectUrl()); return null; } else { - ModelAndView mv = handler.handleExecutionOutcome(result.getEndedOutcome(), result.getEndedOutput(), + String location = handler.handleExecutionOutcome(result.getEndedOutcome(), result.getEndedOutput(), request, response); - return mv != null ? mv : defaultHandleFlowOutcome(result.getFlowId(), result.getEndedOutcome(), result - .getEndedOutput(), request, response); + return location != null ? createRedirectView(location) : defaultHandleFlowOutcome(result.getFlowId(), + result.getEndedOutcome(), result.getEndedOutput(), request, response); } } else { throw new IllegalStateException("Execution result should have been one of [paused] or [ended]"); } } + private ModelAndView createRedirectView(String location) { + return new ModelAndView(new RedirectView(location, true)); + } + private void sendRedirect(ServletExternalContext context, HttpServletRequest request, HttpServletResponse response, String targetUrl) throws IOException { if (context.isAjaxRequest()) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java index fbeba2cf..d468edf2 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java @@ -133,7 +133,7 @@ public class MockExternalContext implements ExternalContext { return ajaxRequest; } - public String getFlowExecutionUri(String flowId, String flowExecutionKey) { + public String getFlowExecutionUrl(String flowId, String flowExecutionKey) { return "/" + flowId + "?execution=" + flowExecutionKey; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockRequestContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockRequestContext.java index 3e5e2841..bb64fecb 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockRequestContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockRequestContext.java @@ -180,7 +180,7 @@ public class MockRequestContext implements RequestContext { "Flow execution key not yet assigned; unable to build the flow execution url"); } else { String flowDefinitionId = flowExecutionContext.getDefinition().getId(); - return externalContext.getFlowExecutionUri(flowDefinitionId, flowExecutionContext.getKey().toString()); + return externalContext.getFlowExecutionUrl(flowDefinitionId, flowExecutionContext.getKey().toString()); } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapterTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapterTests.java index dd3a0d21..84383f80 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapterTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/mvc/portlet/FlowHandlerAdapterTests.java @@ -85,10 +85,10 @@ public class FlowHandlerAdapterTests extends TestCase { } } - public ModelAndView handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, + public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, RenderResponse response) { if (handleExecutionOutcome) { - return new ModelAndView("redirect:/home"); + return "home"; } else { return null; } @@ -172,16 +172,19 @@ public class FlowHandlerAdapterTests extends TestCase { public void testHandleFlowOutcomeCustomFlowHandler() throws Exception { handleExecutionOutcome = true; renderRequest.setContextPath("/springtravel"); - executor.launchExecution("foo", flowInput, renderContext); LocalAttributeMap output = new LocalAttributeMap(); output.put("bar", "baz"); Event outcome = new Event(this, "finish", output); FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome); PortletSession session = renderRequest.getPortletSession(); session.setAttribute("flowExecutionResult", result); + executor.launchExecution("home", flowInput, renderContext); + EasyMock.expectLastCall().andReturn(FlowExecutionResult.createEndedResult("bar", outcome)); + EasyMock.replay(new Object[] { executor }); ModelAndView mv = controller.handleRender(renderRequest, renderResponse, flowHandler); - assertNotNull(mv); - assertEquals("redirect:/home", mv.getViewName()); + assertNull(mv); + EasyMock.verify(new Object[] { executor }); + } public void testHandleFlowExceptionCustomFlowHandler() throws Exception { diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java index 32c072a5..ca615bc3 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java @@ -23,8 +23,6 @@ import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException; import org.springframework.webflow.executor.FlowExecutionResult; import org.springframework.webflow.executor.FlowExecutor; -import org.springframework.webflow.mvc.servlet.FlowController; -import org.springframework.webflow.mvc.servlet.FlowHandler; import org.springframework.webflow.test.MockFlowExecutionKey; public class FlowControllerTests extends TestCase { @@ -291,7 +289,7 @@ public class FlowControllerTests extends TestCase { return input; } - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { return null; } @@ -327,7 +325,7 @@ public class FlowControllerTests extends TestCase { return input; } - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { assertEquals("finish", outcome); assertEquals("baz", output.get("bar")); @@ -372,7 +370,7 @@ public class FlowControllerTests extends TestCase { return null; } - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { return null; } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapterTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapterTests.java index 52f5d18a..20a23fb0 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapterTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapterTests.java @@ -23,8 +23,6 @@ import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException; import org.springframework.webflow.executor.FlowExecutionResult; import org.springframework.webflow.executor.FlowExecutor; -import org.springframework.webflow.mvc.servlet.FlowHandler; -import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter; import org.springframework.webflow.test.MockFlowExecutionKey; public class FlowHandlerAdapterTests extends TestCase { @@ -72,10 +70,10 @@ public class FlowHandlerAdapterTests extends TestCase { } } - public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, + public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) { if (handleExecutionOutcome) { - return new ModelAndView("redirect:/home"); + return "/home"; } else { return null; }