diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
index 89ba05baf6c..aed8f2a201c 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
@@ -174,6 +174,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
ManagedList> messageConverters = getMessageConverters(element, source, parserContext);
ManagedList> argumentResolvers = getArgumentResolvers(element, source, parserContext);
ManagedList> returnValueHandlers = getReturnValueHandlers(element, source, parserContext);
+ String asyncTimeout = getAsyncTimeout(element, source, parserContext);
+ RuntimeBeanReference asyncExecutor = getAsyncExecutor(element, source, parserContext);
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
handlerAdapterDef.setSource(source);
@@ -191,6 +193,12 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
if (returnValueHandlers != null) {
handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
+ if (asyncTimeout != null) {
+ handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
+ }
+ if (asyncExecutor != null) {
+ handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
+ }
String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
@@ -318,6 +326,21 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
}
}
+ private String getAsyncTimeout(Element element, Object source, ParserContext parserContext) {
+ Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
+ return (asyncElement != null) ? asyncElement.getAttribute("default-timeout") : null;
+ }
+
+ private RuntimeBeanReference getAsyncExecutor(Element element, Object source, ParserContext parserContext) {
+ Element asyncElement = DomUtils.getChildElementByTagName(element, "async-support");
+ if (asyncElement != null) {
+ if (asyncElement.hasAttribute("task-executor")) {
+ return new RuntimeBeanReference(asyncElement.getAttribute("task-executor"));
+ }
+ }
+ return null;
+ }
+
private ManagedList> getArgumentResolvers(Element element, Object source, ParserContext parserContext) {
Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers");
if (resolversElement != null) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/AsyncSupportConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/AsyncSupportConfigurer.java
new file mode 100644
index 00000000000..5f42833fdcd
--- /dev/null
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/AsyncSupportConfigurer.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.web.servlet.config.annotation;
+
+import java.util.concurrent.Callable;
+
+import org.springframework.core.task.AsyncTaskExecutor;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.web.context.request.async.AsyncTask;
+
+/**
+ * Helps with configuring a options for asynchronous request processing.
+ *
+ * @author Rossen Stoyanchev
+ * @since 3.2
+ */
+public class AsyncSupportConfigurer {
+
+ private AsyncTaskExecutor taskExecutor;
+
+ private Long timeout;
+
+ /**
+ * Set the default {@link AsyncTaskExecutor} to use when a controller method
+ * returns a {@link Callable}. Controller methods can override this default on
+ * a per-request basis by returning an {@link AsyncTask}.
+ *
+ *
By default a {@link SimpleAsyncTaskExecutor} instance is used and it's
+ * highly recommended to change that default in production since the simple
+ * executor does not re-use threads.
+ *
+ * @param taskExecutor the task executor instance to use by default
+ */
+ public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {
+ this.taskExecutor = taskExecutor;
+ return this;
+ }
+
+ /**
+ * Specify the amount of time, in milliseconds, before asynchronous request
+ * handling times out. In Servlet 3, the timeout begins after the main request
+ * processing thread has exited and ends when the request is dispatched again
+ * for further processing of the concurrently produced result.
+ *
If this value is not set, the default timeout of the underlying
+ * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.
+ *
+ * @param timeout the timeout value in milliseconds
+ */
+ public AsyncSupportConfigurer setDefaultTimeout(long timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ protected AsyncTaskExecutor getTaskExecutor() {
+ return this.taskExecutor;
+ }
+
+ protected Long getTimeout() {
+ return this.timeout;
+ }
+
+}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
index d0537a812c4..d9d58035b17 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
@@ -60,6 +60,11 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
this.configurers.configureContentNegotiation(configurer);
}
+ @Override
+ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+ this.configurers.configureAsyncSupport(configurer);
+ }
+
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
index a759cbe7333..b9f35396130 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
@@ -354,6 +354,17 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
adapter.setWebBindingInitializer(webBindingInitializer);
adapter.setCustomArgumentResolvers(argumentResolvers);
adapter.setCustomReturnValueHandlers(returnValueHandlers);
+
+ AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();
+ configureAsyncSupport(configurer);
+
+ if (configurer.getTaskExecutor() != null) {
+ adapter.setTaskExecutor(configurer.getTaskExecutor());
+ }
+ if (configurer.getTimeout() != null) {
+ adapter.setAsyncRequestTimeout(configurer.getTimeout());
+ }
+
return adapter;
}
@@ -516,6 +527,13 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
protected void addFormatters(FormatterRegistry registry) {
}
+ /**
+ * Override this method to configure asynchronous request processing options.
+ * @see AsyncSupportConfigurer
+ */
+ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+ }
+
/**
* Returns a {@link HttpRequestHandlerAdapter} for processing requests
* with {@link HttpRequestHandler}s.
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
index 97e8a047abc..215d34b7da7 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
@@ -74,6 +74,11 @@ public interface WebMvcConfigurer {
*/
void configureContentNegotiation(ContentNegotiationConfigurer configurer);
+ /**
+ * Configure asynchronous request handling options.
+ */
+ void configureAsyncSupport(AsyncSupportConfigurer configurer);
+
/**
* Add resolvers to support custom controller method argument types.
*
This does not override the built-in support for resolving handler
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
index 8cafe8ce867..ac63b1cbca9 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
@@ -64,6 +64,13 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
+ /**
+ * {@inheritDoc}
+ *
This implementation is empty.
+ */
+ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+ }
+
/**
* {@inheritDoc}
*
This implementation is empty.
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
index 75ba81eede3..e222c3b1260 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
@@ -55,6 +55,12 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
}
}
+ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+ for (WebMvcConfigurer delegate : this.delegates) {
+ delegate.configureAsyncSupport(configurer);
+ }
+ }
+
public void configureMessageConverters(List> converters) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureMessageConverters(converters);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
index ebfdd5b054a..8567a565ba9 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
@@ -62,6 +63,7 @@ import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.context.request.async.AsyncTask;
import org.springframework.web.context.request.async.AsyncWebRequest;
import org.springframework.web.context.request.async.AsyncWebUtils;
import org.springframework.web.context.request.async.WebAsyncManager;
@@ -400,26 +402,28 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
}
/**
- * Set the AsyncTaskExecutor to use when a controller method returns a
- * {@code Callable}.
- * The default instance type is a {@link SimpleAsyncTaskExecutor}.
- * It's recommended to change that default in production as the simple
- * executor does not re-use threads.
+ * Set the default {@link AsyncTaskExecutor} to use when a controller method
+ * return a {@link Callable}. Controller methods can override this default on
+ * a per-request basis by returning an {@link AsyncTask}.
+ *
By default a {@link SimpleAsyncTaskExecutor} instance is used.
+ * It's recommended to change that default in production as the simple executor
+ * does not re-use threads.
*/
- public void setAsyncTaskExecutor(AsyncTaskExecutor taskExecutor) {
+ public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
- * Set the timeout for asynchronous request processing in milliseconds.
- * When the timeout begins depends on the underlying async technology.
- * With the Servlet 3 async support the timeout begins after the main
- * processing thread has exited and has been returned to the container pool.
- *
If a value is not provided, the default timeout of the underlying
- * async technology is used (10 seconds on Tomcat with Servlet 3 async).
+ * Specify the amount of time, in milliseconds, before concurrent handling
+ * should time out. In Servlet 3, the timeout begins after the main request
+ * processing thread has exited and ends when the request is dispatched again
+ * for further processing of the concurrently produced result.
+ *
If this value is not set, the default timeout of the underlying
+ * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.
+ * @param timeout the timeout value in milliseconds
*/
- public void setAsyncRequestTimeout(long asyncRequestTimeout) {
- this.asyncRequestTimeout = asyncRequestTimeout;
+ public void setAsyncRequestTimeout(long timeout) {
+ this.asyncRequestTimeout = timeout;
}
/**
diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
index d04878dc2af..f58bd9289be 100644
--- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
@@ -90,6 +90,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
index bedc9ac477d..d7ad9c9e2fd 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
@@ -45,6 +45,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockRequestDispatcher;
import org.springframework.mock.web.MockServletContext;
+import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
@@ -451,7 +452,7 @@ public class MvcNamespaceTests {
}
@Test
- public void testCustomContentNegotiationManager() throws Exception {
+ public void testContentNegotiationManager() throws Exception {
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 12);
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
@@ -462,6 +463,16 @@ public class MvcNamespaceTests {
assertEquals(Arrays.asList(MediaType.valueOf("application/rss+xml")), manager.resolveMediaTypes(webRequest));
}
+ @Test
+ public void testAsyncSupportOptions() throws Exception {
+ loadBeanDefinitions("mvc-config-async-support.xml", 13);
+
+ RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class);
+ assertNotNull(adapter);
+ assertEquals(ConcurrentTaskExecutor.class, new DirectFieldAccessor(adapter).getPropertyValue("taskExecutor").getClass());
+ assertEquals(2500L, new DirectFieldAccessor(adapter).getPropertyValue("asyncRequestTimeout"));
+ }
+
private void loadBeanDefinitions(String fileName, int expectedBeanCount) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
index ddb26e672ad..7153c901f93 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
@@ -21,6 +21,7 @@ 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.assertSame;
import static org.junit.Assert.assertTrue;
@@ -54,14 +55,14 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
*/
public class DelegatingWebMvcConfigurationTests {
- private DelegatingWebMvcConfiguration mvcConfiguration;
+ private DelegatingWebMvcConfiguration delegatingConfig;
- private WebMvcConfigurer configurer;
+ private WebMvcConfigurer webMvcConfigurer;
@Before
public void setUp() {
- configurer = EasyMock.createMock(WebMvcConfigurer.class);
- mvcConfiguration = new DelegatingWebMvcConfiguration();
+ webMvcConfigurer = EasyMock.createMock(WebMvcConfigurer.class);
+ delegatingConfig = new DelegatingWebMvcConfiguration();
}
@Test
@@ -71,18 +72,20 @@ public class DelegatingWebMvcConfigurationTests {
Capture conversionService = new Capture();
Capture> resolvers = new Capture>();
Capture> handlers = new Capture>();
+ Capture asyncConfigurer = new Capture();
- configurer.configureMessageConverters(capture(converters));
- configurer.configureContentNegotiation(capture(contentNegotiationConfigurer));
- expect(configurer.getValidator()).andReturn(null);
- expect(configurer.getMessageCodesResolver()).andReturn(null);
- configurer.addFormatters(capture(conversionService));
- configurer.addArgumentResolvers(capture(resolvers));
- configurer.addReturnValueHandlers(capture(handlers));
- replay(configurer);
+ webMvcConfigurer.configureMessageConverters(capture(converters));
+ webMvcConfigurer.configureContentNegotiation(capture(contentNegotiationConfigurer));
+ expect(webMvcConfigurer.getValidator()).andReturn(null);
+ expect(webMvcConfigurer.getMessageCodesResolver()).andReturn(null);
+ webMvcConfigurer.addFormatters(capture(conversionService));
+ webMvcConfigurer.addArgumentResolvers(capture(resolvers));
+ webMvcConfigurer.addReturnValueHandlers(capture(handlers));
+ webMvcConfigurer.configureAsyncSupport(capture(asyncConfigurer));
+ replay(webMvcConfigurer);
- mvcConfiguration.setConfigurers(Arrays.asList(configurer));
- RequestMappingHandlerAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter();
+ delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer));
+ RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter();
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
assertSame(conversionService.getValue(), initializer.getConversionService());
@@ -91,8 +94,9 @@ public class DelegatingWebMvcConfigurationTests {
assertEquals(0, resolvers.getValue().size());
assertEquals(0, handlers.getValue().size());
assertEquals(converters.getValue(), adapter.getMessageConverters());
+ assertNotNull(asyncConfigurer);
- verify(configurer);
+ verify(webMvcConfigurer);
}
@Test
@@ -104,33 +108,33 @@ public class DelegatingWebMvcConfigurationTests {
converters.add(new StringHttpMessageConverter());
}
});
- mvcConfiguration = new DelegatingWebMvcConfiguration();
- mvcConfiguration.setConfigurers(configurers);
+ delegatingConfig = new DelegatingWebMvcConfiguration();
+ delegatingConfig.setConfigurers(configurers);
- RequestMappingHandlerAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter();
+ RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter();
assertEquals("Only one custom converter should be registered", 1, adapter.getMessageConverters().size());
}
@Test
public void getCustomValidator() {
- expect(configurer.getValidator()).andReturn(new LocalValidatorFactoryBean());
- replay(configurer);
+ expect(webMvcConfigurer.getValidator()).andReturn(new LocalValidatorFactoryBean());
+ replay(webMvcConfigurer);
- mvcConfiguration.setConfigurers(Arrays.asList(configurer));
- mvcConfiguration.mvcValidator();
+ delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer));
+ delegatingConfig.mvcValidator();
- verify(configurer);
+ verify(webMvcConfigurer);
}
@Test
public void getCustomMessageCodesResolver() {
- expect(configurer.getMessageCodesResolver()).andReturn(new DefaultMessageCodesResolver());
- replay(configurer);
+ expect(webMvcConfigurer.getMessageCodesResolver()).andReturn(new DefaultMessageCodesResolver());
+ replay(webMvcConfigurer);
- mvcConfiguration.setConfigurers(Arrays.asList(configurer));
- mvcConfiguration.getMessageCodesResolver();
+ delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer));
+ delegatingConfig.getMessageCodesResolver();
- verify(configurer);
+ verify(webMvcConfigurer);
}
@Test
@@ -139,13 +143,13 @@ public class DelegatingWebMvcConfigurationTests {
Capture> exceptionResolvers = new Capture>();
Capture contentNegotiationConfigurer = new Capture();
- configurer.configureMessageConverters(capture(converters));
- configurer.configureContentNegotiation(capture(contentNegotiationConfigurer));
- configurer.configureHandlerExceptionResolvers(capture(exceptionResolvers));
- replay(configurer);
+ webMvcConfigurer.configureMessageConverters(capture(converters));
+ webMvcConfigurer.configureContentNegotiation(capture(contentNegotiationConfigurer));
+ webMvcConfigurer.configureHandlerExceptionResolvers(capture(exceptionResolvers));
+ replay(webMvcConfigurer);
- mvcConfiguration.setConfigurers(Arrays.asList(configurer));
- mvcConfiguration.handlerExceptionResolver();
+ delegatingConfig.setConfigurers(Arrays.asList(webMvcConfigurer));
+ delegatingConfig.handlerExceptionResolver();
assertEquals(3, exceptionResolvers.getValue().size());
assertTrue(exceptionResolvers.getValue().get(0) instanceof ExceptionHandlerExceptionResolver);
@@ -153,7 +157,7 @@ public class DelegatingWebMvcConfigurationTests {
assertTrue(exceptionResolvers.getValue().get(2) instanceof DefaultHandlerExceptionResolver);
assertTrue(converters.getValue().size() > 0);
- verify(configurer);
+ verify(webMvcConfigurer);
}
@Test
@@ -165,10 +169,10 @@ public class DelegatingWebMvcConfigurationTests {
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
});
- mvcConfiguration.setConfigurers(configurers);
+ delegatingConfig.setConfigurers(configurers);
HandlerExceptionResolverComposite composite =
- (HandlerExceptionResolverComposite) mvcConfiguration.handlerExceptionResolver();
+ (HandlerExceptionResolverComposite) delegatingConfig.handlerExceptionResolver();
assertEquals("Only one custom converter is expected", 1, composite.getExceptionResolvers().size());
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java
new file mode 100644
index 00000000000..4324cf75a1e
--- /dev/null
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.servlet.config.annotation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.DirectFieldAccessor;
+import org.springframework.beans.TestBean;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.io.FileSystemResourceLoader;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.DefaultMessageCodesResolver;
+import org.springframework.validation.Errors;
+import org.springframework.validation.MessageCodesResolver;
+import org.springframework.validation.Validator;
+import org.springframework.web.accept.ContentNegotiationManager;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.context.request.ServletWebRequest;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.handler.AbstractHandlerMapping;
+import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
+import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
+import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+/**
+ * A test fixture with a sub-class of {@link WebMvcConfigurationSupport} that
+ * implements the various {@link WebMvcConfigurer} extension points.
+ *
+ * @author Rossen Stoyanchev
+ */
+public class WebMvcConfigurationSupportExtensionTests {
+
+ private TestWebMvcConfigurationSupport webConfig;
+
+ private StaticWebApplicationContext webAppContext;
+
+
+ @Before
+ public void setUp() {
+ this.webAppContext = new StaticWebApplicationContext();
+ this.webAppContext.setServletContext(new MockServletContext(new FileSystemResourceLoader()));
+ this.webAppContext.registerSingleton("controller", TestController.class);
+
+ this.webConfig = new TestWebMvcConfigurationSupport();
+ this.webConfig.setApplicationContext(this.webAppContext);
+ this.webConfig.setServletContext(this.webAppContext.getServletContext());
+ }
+
+ @Test
+ public void handlerMappings() throws Exception {
+ RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping();
+ rmHandlerMapping.setApplicationContext(webAppContext);
+ rmHandlerMapping.afterPropertiesSet();
+ HandlerExecutionChain chain = rmHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/"));
+ assertNotNull(chain.getInterceptors());
+ assertEquals(2, chain.getInterceptors().length);
+ assertEquals(LocaleChangeInterceptor.class, chain.getInterceptors()[0].getClass());
+ assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass());
+
+ AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) webConfig.viewControllerHandlerMapping();
+ handlerMapping.setApplicationContext(webAppContext);
+ assertNotNull(handlerMapping);
+ assertEquals(1, handlerMapping.getOrder());
+ HandlerExecutionChain handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/path"));
+ assertNotNull(handler.getHandler());
+
+ handlerMapping = (AbstractHandlerMapping) webConfig.resourceHandlerMapping();
+ handlerMapping.setApplicationContext(webAppContext);
+ assertNotNull(handlerMapping);
+ assertEquals(Integer.MAX_VALUE-1, handlerMapping.getOrder());
+ handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/resources/foo.gif"));
+ assertNotNull(handler.getHandler());
+
+ handlerMapping = (AbstractHandlerMapping) webConfig.defaultServletHandlerMapping();
+ handlerMapping.setApplicationContext(webAppContext);
+ assertNotNull(handlerMapping);
+ assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
+ handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/anyPath"));
+ assertNotNull(handler.getHandler());
+ }
+
+ @Test
+ public void requestMappingHandlerAdapter() throws Exception {
+ RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter();
+
+ // ConversionService
+ String actual = webConfig.mvcConversionService().convert(new TestBean(), String.class);
+ assertEquals("converted", actual);
+
+ // Message converters
+ assertEquals(1, adapter.getMessageConverters().size());
+
+ // Custom argument resolvers and return value handlers
+ @SuppressWarnings("unchecked")
+ List argResolvers= (List)
+ new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers");
+ assertEquals(1, argResolvers.size());
+
+ @SuppressWarnings("unchecked")
+ List handlers = (List)
+ new DirectFieldAccessor(adapter).getPropertyValue("customReturnValueHandlers");
+ assertEquals(1, handlers.size());
+
+ // Async support options
+ assertEquals(ConcurrentTaskExecutor.class, new DirectFieldAccessor(adapter).getPropertyValue("taskExecutor").getClass());
+ assertEquals(2500L, new DirectFieldAccessor(adapter).getPropertyValue("asyncRequestTimeout"));
+
+ assertEquals(false, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));
+ }
+
+ @Test
+ public void webBindingInitializer() throws Exception {
+ RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter();
+
+ ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
+ assertNotNull(initializer);
+
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(null, "");
+ initializer.getValidator().validate(null, bindingResult);
+ assertEquals("invalid", bindingResult.getAllErrors().get(0).getCode());
+
+ String[] codes = initializer.getMessageCodesResolver().resolveMessageCodes("invalid", null);
+ assertEquals("custom.invalid", codes[0]);
+ }
+
+ @Test
+ public void contentNegotiation() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.json");
+ NativeWebRequest webRequest = new ServletWebRequest(request);
+
+ ContentNegotiationManager manager = webConfig.requestMappingHandlerMapping().getContentNegotiationManager();
+ assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(webRequest));
+
+ request.setRequestURI("/foo.xml");
+ assertEquals(Arrays.asList(MediaType.APPLICATION_XML), manager.resolveMediaTypes(webRequest));
+
+ request.setRequestURI("/foo.rss");
+ assertEquals(Arrays.asList(MediaType.valueOf("application/rss+xml")), manager.resolveMediaTypes(webRequest));
+
+ request.setRequestURI("/foo.atom");
+ assertEquals(Arrays.asList(MediaType.APPLICATION_ATOM_XML), manager.resolveMediaTypes(webRequest));
+
+ request.setRequestURI("/foo");
+ request.setParameter("f", "json");
+ assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(webRequest));
+ }
+
+ @Test
+ public void exceptionResolvers() throws Exception {
+ HandlerExceptionResolverComposite composite = (HandlerExceptionResolverComposite) webConfig.handlerExceptionResolver();
+ assertEquals(1, composite.getExceptionResolvers().size());
+ }
+
+
+ @Controller
+ private static class TestController {
+
+ @RequestMapping("/")
+ public void handle() {
+ }
+ }
+
+ /**
+ * Since WebMvcConfigurationSupport does not implement WebMvcConfigurer, the purpose
+ * of this test class is also to ensure the two are in sync with each other. Effectively
+ * that ensures that application config classes that use the combo {@code @EnableWebMvc}
+ * plus WebMvcConfigurer can switch to extending WebMvcConfigurationSupport directly for
+ * more advanced configuration needs.
+ */
+ private class TestWebMvcConfigurationSupport extends WebMvcConfigurationSupport implements WebMvcConfigurer {
+
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ registry.addConverter(new Converter() {
+ public String convert(TestBean source) {
+ return "converted";
+ }
+ });
+ }
+
+ @Override
+ public void configureMessageConverters(List> converters) {
+ converters.add(new MappingJackson2HttpMessageConverter());
+ }
+
+ @Override
+ public Validator getValidator() {
+ return new Validator() {
+ public void validate(Object target, Errors errors) {
+ errors.reject("invalid");
+ }
+ public boolean supports(Class> clazz) {
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
+ configurer.setFavorParameter(true).setParameterName("f");
+ }
+
+ @Override
+ public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+ configurer.setDefaultTimeout(2500).setTaskExecutor(new ConcurrentTaskExecutor());
+ }
+
+ @Override
+ public void addArgumentResolvers(List argumentResolvers) {
+ argumentResolvers.add(new ModelAttributeMethodProcessor(true));
+ }
+
+ @Override
+ public void addReturnValueHandlers(List returnValueHandlers) {
+ returnValueHandlers.add(new ModelAttributeMethodProcessor(true));
+ }
+
+ @Override
+ public void configureHandlerExceptionResolvers(List exceptionResolvers) {
+ exceptionResolvers.add(new SimpleMappingExceptionResolver());
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new LocaleChangeInterceptor());
+ }
+
+ @SuppressWarnings("serial")
+ @Override
+ public MessageCodesResolver getMessageCodesResolver() {
+ return new DefaultMessageCodesResolver() {
+ @Override
+ public String[] resolveMessageCodes(String errorCode, String objectName) {
+ return new String[] { "custom." + errorCode };
+ }
+ };
+ }
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/path");
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/resources/**").addResourceLocations("src/test/java");
+ }
+
+ @Override
+ public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
+ configurer.enable("default");
+ }
+
+ }
+
+}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
index bc1b2adca42..3c5ad6c7739 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
@@ -21,64 +21,44 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
-import org.springframework.beans.DirectFieldAccessor;
-import org.springframework.beans.TestBean;
import org.springframework.core.convert.ConversionService;
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.core.io.FileSystemResourceLoader;
-import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.FormattingConversionService;
-import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.stereotype.Controller;
-import org.springframework.validation.BeanPropertyBindingResult;
-import org.springframework.validation.DefaultMessageCodesResolver;
-import org.springframework.validation.Errors;
-import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
-import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
-import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.support.StaticWebApplicationContext;
-import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
-import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
-import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
-import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
- * A test fixture for {@link WebMvcConfigurationSupport}.
+ * A test fixture with an {@link WebMvcConfigurationSupport} instance.
*
* @author Rossen Stoyanchev
*/
public class WebMvcConfigurationSupportTests {
- private TestWebMvcConfiguration mvcConfiguration;
+ private WebMvcConfigurationSupport mvcConfiguration;
@Before
public void setUp() {
- mvcConfiguration = new TestWebMvcConfiguration();
+ mvcConfiguration = new WebMvcConfigurationSupport();
}
@Test
@@ -157,8 +137,6 @@ public class WebMvcConfigurationSupportTests {
Validator validator = initializer.getValidator();
assertNotNull(validator);
assertTrue(validator instanceof LocalValidatorFactoryBean);
-
- assertEquals(false, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));
}
@Test
@@ -173,94 +151,6 @@ public class WebMvcConfigurationSupportTests {
assertEquals(expectedResolvers.size(), compositeResolver.getExceptionResolvers().size());
}
- @Test
- public void webMvcConfigurerExtensionHooks() throws Exception {
-
- StaticWebApplicationContext appCxt = new StaticWebApplicationContext();
- appCxt.setServletContext(new MockServletContext(new FileSystemResourceLoader()));
- appCxt.registerSingleton("controller", TestController.class);
-
- WebConfig webConfig = new WebConfig();
- webConfig.setApplicationContext(appCxt);
- webConfig.setServletContext(appCxt.getServletContext());
-
- String actual = webConfig.mvcConversionService().convert(new TestBean(), String.class);
- assertEquals("converted", actual);
-
- MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.json");
- NativeWebRequest webRequest = new ServletWebRequest(request);
- ContentNegotiationManager manager = webConfig.requestMappingHandlerMapping().getContentNegotiationManager();
- assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(webRequest));
-
- request.setRequestURI("/foo.xml");
- assertEquals(Arrays.asList(MediaType.APPLICATION_XML), manager.resolveMediaTypes(webRequest));
-
- request.setRequestURI("/foo.rss");
- assertEquals(Arrays.asList(MediaType.valueOf("application/rss+xml")), manager.resolveMediaTypes(webRequest));
-
- request.setRequestURI("/foo.atom");
- assertEquals(Arrays.asList(MediaType.APPLICATION_ATOM_XML), manager.resolveMediaTypes(webRequest));
-
- request.setRequestURI("/foo");
- request.setParameter("f", "json");
- assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(webRequest));
-
- RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter();
- assertEquals(1, adapter.getMessageConverters().size());
-
- ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
- assertNotNull(initializer);
-
- BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(null, "");
- initializer.getValidator().validate(null, bindingResult);
- assertEquals("invalid", bindingResult.getAllErrors().get(0).getCode());
-
- String[] codes = initializer.getMessageCodesResolver().resolveMessageCodes("invalid", null);
- assertEquals("custom.invalid", codes[0]);
-
- @SuppressWarnings("unchecked")
- List argResolvers= (List)
- new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers");
- assertEquals(1, argResolvers.size());
-
- @SuppressWarnings("unchecked")
- List handlers = (List)
- new DirectFieldAccessor(adapter).getPropertyValue("customReturnValueHandlers");
- assertEquals(1, handlers.size());
-
- HandlerExceptionResolverComposite composite = (HandlerExceptionResolverComposite) webConfig.handlerExceptionResolver();
- assertEquals(1, composite.getExceptionResolvers().size());
-
- RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping();
- rmHandlerMapping.setApplicationContext(appCxt);
- rmHandlerMapping.afterPropertiesSet();
- HandlerExecutionChain chain = rmHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/"));
- assertNotNull(chain.getInterceptors());
- assertEquals(2, chain.getInterceptors().length);
- assertEquals(LocaleChangeInterceptor.class, chain.getInterceptors()[0].getClass());
- assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass());
-
- AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) webConfig.viewControllerHandlerMapping();
- handlerMapping.setApplicationContext(appCxt);
- assertNotNull(handlerMapping);
- assertEquals(1, handlerMapping.getOrder());
- HandlerExecutionChain handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/path"));
- assertNotNull(handler.getHandler());
-
- handlerMapping = (AbstractHandlerMapping) webConfig.resourceHandlerMapping();
- handlerMapping.setApplicationContext(appCxt);
- assertNotNull(handlerMapping);
- assertEquals(Integer.MAX_VALUE-1, handlerMapping.getOrder());
- handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/resources/foo.gif"));
- assertNotNull(handler.getHandler());
-
- handlerMapping = (AbstractHandlerMapping) webConfig.defaultServletHandlerMapping();
- handlerMapping.setApplicationContext(appCxt);
- assertNotNull(handlerMapping);
- assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
- handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/anyPath"));
- assertNotNull(handler.getHandler());
- }
@Controller
private static class TestController {
@@ -270,96 +160,4 @@ public class WebMvcConfigurationSupportTests {
}
}
- private static class TestWebMvcConfiguration extends WebMvcConfigurationSupport {
-
- }
-
- /**
- * Since WebMvcConfigurationSupport does not implement WebMvcConfigurer, the purpose
- * of this test class is also to ensure the two are in sync with each other. Effectively
- * that ensures that application config classes that use the combo {@code @EnableWebMvc}
- * plus WebMvcConfigurer can switch to extending WebMvcConfigurationSupport directly for
- * more advanced configuration needs.
- */
- private class WebConfig extends WebMvcConfigurationSupport implements WebMvcConfigurer {
-
- @Override
- public void addFormatters(FormatterRegistry registry) {
- registry.addConverter(new Converter() {
- public String convert(TestBean source) {
- return "converted";
- }
- });
- }
-
- @Override
- public void configureMessageConverters(List> converters) {
- converters.add(new MappingJackson2HttpMessageConverter());
- }
-
- @Override
- public Validator getValidator() {
- return new Validator() {
- public void validate(Object target, Errors errors) {
- errors.reject("invalid");
- }
- public boolean supports(Class> clazz) {
- return true;
- }
- };
- }
-
- @Override
- public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
- configurer.setFavorParameter(true).setParameterName("f");
- }
-
- @Override
- public void addArgumentResolvers(List argumentResolvers) {
- argumentResolvers.add(new ModelAttributeMethodProcessor(true));
- }
-
- @Override
- public void addReturnValueHandlers(List returnValueHandlers) {
- returnValueHandlers.add(new ModelAttributeMethodProcessor(true));
- }
-
- @Override
- public void configureHandlerExceptionResolvers(List exceptionResolvers) {
- exceptionResolvers.add(new SimpleMappingExceptionResolver());
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new LocaleChangeInterceptor());
- }
-
- @SuppressWarnings("serial")
- @Override
- public MessageCodesResolver getMessageCodesResolver() {
- return new DefaultMessageCodesResolver() {
- @Override
- public String[] resolveMessageCodes(String errorCode, String objectName) {
- return new String[] { "custom." + errorCode };
- }
- };
- }
-
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/path");
- }
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/resources/**").addResourceLocations("src/test/java");
- }
-
- @Override
- public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable("default");
- }
-
- }
-
}
diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-async-support.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-async-support.xml
new file mode 100644
index 00000000000..ed902a56c15
--- /dev/null
+++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-async-support.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+