diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/view/DefaultLogicResult.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/view/DefaultLogicResult.java index 79d793cf5..5a79c025d 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/view/DefaultLogicResult.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/view/DefaultLogicResult.java @@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory; import br.com.caelum.vraptor.Get; +import br.com.caelum.vraptor.Result; import br.com.caelum.vraptor.controller.ControllerMethod; import br.com.caelum.vraptor.controller.DefaultControllerMethod; import br.com.caelum.vraptor.controller.HttpMethod; @@ -68,17 +69,20 @@ public class DefaultLogicResult implements LogicResult { private final FlashScope flash; private final MethodInfo methodInfo; + private Result result; + /** * @deprecated CDI eyes only */ protected DefaultLogicResult() { - this(null, null, null, null, null, null, null, null, null); + this(null, null, null, null, null, null, null, null, null, null); } @Inject public DefaultLogicResult(Proxifier proxifier, Router router, MutableRequest request, HttpServletResponse response, - Container container, PathResolver resolver, TypeNameExtractor extractor, FlashScope flash, MethodInfo methodInfo) { + Container container, PathResolver resolver, TypeNameExtractor extractor, FlashScope flash, MethodInfo methodInfo, Result result) { this.proxifier = proxifier; + this.result = result; this.response = unproxifyIfPossible(response); this.request = unproxifyIfPossible(request); this.router = router; @@ -97,24 +101,27 @@ public DefaultLogicResult(Proxifier proxifier, Router router, MutableRequest req @Override public T forwardTo(final Class type) { return proxifier.proxify(type, new MethodInvocation() { + @Override public Object intercept(T proxy, Method method, Object[] args, SuperMethod superMethod) { try { logger.debug("Executing {}", method); ControllerMethod old = methodInfo.getControllerMethod(); methodInfo.setControllerMethod(DefaultControllerMethod.instanceFor(type, method)); - Object result = method.invoke(container.instanceFor(type), args); + Object methodResult = method.invoke(container.instanceFor(type), args); methodInfo.setControllerMethod(old); Type returnType = method.getGenericReturnType(); if (!(returnType == void.class)) { - request.setAttribute(extractor.nameFor(returnType), result); + request.setAttribute(extractor.nameFor(returnType), methodResult); } - if (!response.isCommitted()) { - String path = resolver.pathFor(DefaultControllerMethod.instanceFor(type, method)); - logger.debug("Forwarding to {}", path); - request.getRequestDispatcher(path).forward(request, response); + if (response.isCommitted() || result.used()) { + logger.debug("Response already commited, not forwarding."); + return null; } + String path = resolver.pathFor(DefaultControllerMethod.instanceFor(type, method)); + logger.debug("Forwarding to {}", path); + request.getRequestDispatcher(path).forward(request, response); return null; } catch (InvocationTargetException e) { propagateIfPossible(e.getCause()); diff --git a/vraptor-core/src/test/java/br/com/caelum/vraptor/view/DefaultLogicResultTest.java b/vraptor-core/src/test/java/br/com/caelum/vraptor/view/DefaultLogicResultTest.java index 231703d40..9efea7aaf 100644 --- a/vraptor-core/src/test/java/br/com/caelum/vraptor/view/DefaultLogicResultTest.java +++ b/vraptor-core/src/test/java/br/com/caelum/vraptor/view/DefaultLogicResultTest.java @@ -72,11 +72,13 @@ public class DefaultLogicResultTest { private @Mock TypeNameExtractor extractor; private @Mock RequestDispatcher dispatcher; private @Mock FlashScope flash; + private @Mock Result result; private Proxifier proxifier; private MethodInfo methodInfo; + public static class MyComponent { int calls = 0; @@ -114,7 +116,7 @@ public void setup() { proxifier = new JavassistProxifier(); methodInfo = new MethodInfo(new ParanamerNameProvider()); this.logicResult = new DefaultLogicResult(proxifier, router, request, response, container, - resolver, extractor, flash, methodInfo); + resolver, extractor, flash, methodInfo, result); } @Test @@ -167,6 +169,15 @@ public void shouldNotForwardToMethodsDefaultViewWhenResponseIsCommited() throws verify(dispatcher, never()).forward(request, response); } + @Test + public void shouldNotForwardToMethodsDefaultViewWhenResultIsUsed() throws Exception { + givenDispatcherWillBeReturnedWhenRequested(); + when(response.isCommitted()).thenReturn(false); + when(result.used()).thenReturn(true); + logicResult.forwardTo(MyComponent.class).base(); + verify(dispatcher, never()).forward(request, response); + } + @Test public void shouldPutParametersOnFlashScopeOnRedirect() throws Exception {