SPR-8770 Ensure RequestDataValueProcessor is invoked from RedirectView.

master
Rossen Stoyanchev 13 years ago
parent 2980ef4c75
commit fd97c8d7a4
  1. 39
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java
  2. 9
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java
  3. 4
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/RequestDataValueProcessorWrapper.java
  4. 5
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/form/AbstractHtmlElementTagTests.java
  5. 33
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java
  6. 71
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
  7. 1
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ViewResolverTests.java

@ -38,6 +38,8 @@ import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.SmartView;
@ -250,13 +252,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
String targetUrl = createTargetUrl(model, request);
if (getWebApplicationContext() != null) {
RequestContext requestContext = createRequestContext(request, response, model);
RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
if (processor != null) {
targetUrl = processor.processUrl(request, targetUrl);
}
}
targetUrl = updateTargetUrl(targetUrl, model, request, response);
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
if (!CollectionUtils.isEmpty(flashMap)) {
@ -489,6 +485,35 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
return (input != null ? URLEncoder.encode(input, encodingScheme) : null);
}
/**
* Find the registered {@link RequestDataValueProcessor}, if any, and allow
* it to update the redirect target URL.
* @return the updated URL or the same as URL as the one passed in
*/
protected String updateTargetUrl(String targetUrl, Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) {
RequestContext requestContext = null;
if (getWebApplicationContext() != null) {
requestContext = createRequestContext(request, response, model);
}
else {
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
if (wac != null && wac.getServletContext() != null) {
requestContext = new RequestContext(request, response, wac.getServletContext(), model);
}
}
if (requestContext != null) {
RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
if (processor != null) {
targetUrl = processor.processUrl(request, targetUrl);
}
}
return targetUrl;
}
/**
* Send a redirect back to the HTTP client
* @param request current HTTP request (allows for reacting to request method)

@ -389,7 +389,8 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
// Check for special "redirect:" prefix.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
return applyLifecycleMethods(viewName, view);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
@ -433,10 +434,14 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}
private View applyLifecycleMethods(String viewName, AbstractView view) {
return (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
}
/**
* Creates a new View instance of the specified view class and configures it.
* Does <i>not</i> perform any lookup for pre-defined View instances.

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.servlet.tags.form;
package org.springframework.web.servlet.support;
import java.util.Map;
@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
class DelegatingRequestDataValueProcessor implements RequestDataValueProcessor {
public class RequestDataValueProcessorWrapper implements RequestDataValueProcessor {
private RequestDataValueProcessor processor;

@ -32,6 +32,7 @@ import org.springframework.mock.web.MockPageContext;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper;
import org.springframework.web.servlet.support.JspAwareRequestContext;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.support.RequestContextUtils;
@ -66,7 +67,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
MockPageContext pageContext = createPageContext();
MockHttpServletRequest request = (MockHttpServletRequest) pageContext.getRequest();
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
wac.registerSingleton("requestDataValueProcessor", DelegatingRequestDataValueProcessor.class);
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
extendRequest(request);
extendPageContext(pageContext);
RequestContext requestContext = new JspAwareRequestContext(pageContext);
@ -103,7 +104,7 @@ public abstract class AbstractHtmlElementTagTests extends AbstractTagTests {
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
ServletRequest request = getPageContext().getRequest();
StaticWebApplicationContext wac = (StaticWebApplicationContext) RequestContextUtils.getWebApplicationContext(request);
wac.getBean(DelegatingRequestDataValueProcessor.class).setRequestDataValueProcessor(mockProcessor);
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
return mockProcessor;
}

@ -16,6 +16,16 @@
package org.springframework.web.servlet.view;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -28,7 +38,6 @@ import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@ -40,9 +49,6 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
*/
@ -418,8 +424,14 @@ public class ContentNegotiatingViewResolverTests {
request.addHeader("Accept", "application/json");
request.setRequestURI("/test");
StaticWebApplicationContext webAppContext = new StaticWebApplicationContext();
webAppContext.setServletContext(new MockServletContext());
webAppContext.refresh();
UrlBasedViewResolver urlViewResolver = new InternalResourceViewResolver();
urlViewResolver.setApplicationContext(webAppContext);
ViewResolver xmlViewResolver = createMock(ViewResolver.class);
viewResolver.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, new UrlBasedViewResolver()));
viewResolver.setViewResolvers(Arrays.<ViewResolver>asList(xmlViewResolver, urlViewResolver));
View xmlView = createMock("application_xml", View.class);
View jsonView = createMock("application_json", View.class);
@ -491,15 +503,14 @@ public class ContentNegotiatingViewResolverTests {
@Test
public void nestedViewResolverIsNotSpringBean() throws Exception {
StaticWebApplicationContext webAppContext = new StaticWebApplicationContext();
webAppContext.setServletContext(new MockServletContext());
webAppContext.refresh();
InternalResourceViewResolver nestedResolver = new InternalResourceViewResolver();
nestedResolver.setApplicationContext(webAppContext);
nestedResolver.setViewClass(InternalResourceView.class);
viewResolver.setViewResolvers(new ArrayList<ViewResolver>(Arrays.asList(nestedResolver)));
StaticWebApplicationContext appContext = new StaticWebApplicationContext();
appContext.setServletContext(new MockServletContext());
appContext.refresh();
viewResolver.setApplicationContext(appContext);
viewResolver.setDefaultContentType(MediaType.TEXT_HTML);
String viewName = "view";

@ -34,15 +34,22 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.AssertionFailedError;
import org.easymock.EasyMock;
import org.junit.Test;
import org.springframework.beans.TestBean;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
import org.springframework.web.util.WebUtils;
/**
@ -118,8 +125,8 @@ public class RedirectViewTests {
RedirectView rv = new RedirectView();
rv.setUrl("http://url.somewhere.com/path");
rv.setHttp10Compatible(false);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HttpServletRequest request = new MockHttpServletRequest();
HttpServletResponse response = new MockHttpServletResponse();
FlashMap flashMap = new FlashMap();
flashMap.put("successMessage", "yay!");
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
@ -131,6 +138,64 @@ public class RedirectViewTests {
assertEquals("/path", flashMap.getTargetRequestPath());
assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap());
}
@Test
public void updateTargetUrl() throws Exception {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
wac.setServletContext(new MockServletContext());
wac.refresh();
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
RedirectView rv = new RedirectView();
rv.setApplicationContext(wac); // Init RedirectView with WebAppCxt
rv.setUrl("/path");
HttpServletRequest request = new MockHttpServletRequest();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
HttpServletResponse response = new MockHttpServletResponse();
EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123");
EasyMock.replay(mockProcessor);
rv.render(new ModelMap(), request, response);
EasyMock.verify(mockProcessor);
}
@Test
public void updateTargetUrlWithContextLoader() throws Exception {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
MockServletContext servletContext = new MockServletContext();
ContextLoader contextLoader = new ContextLoader(wac);
contextLoader.initWebApplicationContext(servletContext);
try {
RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class);
wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
RedirectView rv = new RedirectView();
rv.setUrl("/path");
HttpServletRequest request = new MockHttpServletRequest();
HttpServletResponse response = new MockHttpServletResponse();
EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123");
EasyMock.replay(mockProcessor);
rv.render(new ModelMap(), request, response);
EasyMock.verify(mockProcessor);
}
finally {
contextLoader.closeWebApplicationContext(servletContext);
}
}
@Test
public void emptyMap() throws Exception {
@ -296,7 +361,7 @@ public class RedirectViewTests {
expectedUrlForEncoding = "/context" + expectedUrlForEncoding;
expect(request.getContextPath()).andReturn("/context");
}
HttpServletResponse response = createMock("response", HttpServletResponse.class);
expect(response.encodeRedirectURL(expectedUrlForEncoding)).andReturn(expectedUrlForEncoding);
response.sendRedirect(expectedUrlForEncoding);

@ -158,6 +158,7 @@ public class ViewResolverTests {
view = vr.resolveViewName("redirect:myUrl", Locale.getDefault());
assertEquals("Correct view class", RedirectView.class, view.getClass());
assertEquals("Correct URL", "myUrl", ((RedirectView) view).getUrl());
assertSame("View not initialized as bean", wac, ((RedirectView) view).getApplicationContext());
view = vr.resolveViewName("forward:myUrl", Locale.getDefault());
assertEquals("Correct view class", InternalResourceView.class, view.getClass());

Loading…
Cancel
Save