Integrate suggested support for creating MVC URLs
The key contract is MvcUrls. An instance is automatically created with the Spring MVC namespace and the MVC Java config but can also be easily created in any configuration. Some example tests can be found in DefaultMvcUrlsTests. Issue: SPR-10665, SPR-8826
This commit is contained in:
@@ -56,6 +56,8 @@ import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
|
||||
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
|
||||
@@ -76,11 +78,14 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.support.MvcUrls;
|
||||
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
|
||||
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
|
||||
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.servlet.mvc.support.MvcUrlUtils.*;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
@@ -108,7 +113,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testDefaultConfig() throws Exception {
|
||||
loadBeanDefinitions("mvc-config.xml", 12);
|
||||
loadBeanDefinitions("mvc-config.xml", 13);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -147,11 +152,26 @@ public class MvcNamespaceTests {
|
||||
|
||||
adapter.handle(request, response, handlerMethod);
|
||||
assertTrue(handler.recordedValidationError);
|
||||
|
||||
// MvcUrls
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
|
||||
try {
|
||||
Date now = new Date();
|
||||
TestController testController = controller(TestController.class);
|
||||
testController.testBind(now, null, null);
|
||||
MvcUrls mvcUrls = this.appContext.getBean(MvcUrls.class);
|
||||
UriComponents uriComponents = mvcUrls.linkToMethodOn(testController);
|
||||
|
||||
assertEquals("http://localhost/?date=2013-10-21", uriComponents.toUriString());
|
||||
}
|
||||
finally {
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=TypeMismatchException.class)
|
||||
public void testCustomConversionService() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-custom-conversion-service.xml", 12);
|
||||
loadBeanDefinitions("mvc-config-custom-conversion-service.xml", 13);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -177,7 +197,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testCustomValidator() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-custom-validator.xml", 12);
|
||||
loadBeanDefinitions("mvc-config-custom-validator.xml", 13);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -199,7 +219,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testInterceptors() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-interceptors.xml", 17);
|
||||
loadBeanDefinitions("mvc-config-interceptors.xml", 18);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -328,7 +348,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testBeanDecoration() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-bean-decoration.xml", 14);
|
||||
loadBeanDefinitions("mvc-config-bean-decoration.xml", 15);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -349,7 +369,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testViewControllers() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-view-controllers.xml", 15);
|
||||
loadBeanDefinitions("mvc-config-view-controllers.xml", 16);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -409,7 +429,7 @@ public class MvcNamespaceTests {
|
||||
/** WebSphere gives trailing servlet path slashes by default!! */
|
||||
@Test
|
||||
public void testViewControllersOnWebSphere() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-view-controllers.xml", 15);
|
||||
loadBeanDefinitions("mvc-config-view-controllers.xml", 16);
|
||||
|
||||
SimpleUrlHandlerMapping mapping2 = appContext.getBean(SimpleUrlHandlerMapping.class);
|
||||
SimpleControllerHandlerAdapter adapter = appContext.getBean(SimpleControllerHandlerAdapter.class);
|
||||
@@ -462,7 +482,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testContentNegotiationManager() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 12);
|
||||
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 13);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
ContentNegotiationManager manager = mapping.getContentNegotiationManager();
|
||||
@@ -474,7 +494,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testAsyncSupportOptions() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-async-support.xml", 13);
|
||||
loadBeanDefinitions("mvc-config-async-support.xml", 14);
|
||||
|
||||
RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class);
|
||||
assertNotNull(adapter);
|
||||
|
||||
@@ -16,28 +16,33 @@
|
||||
|
||||
package org.springframework.web.servlet.config.annotation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
|
||||
@@ -49,6 +54,11 @@ import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExc
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.support.MvcUrls;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.servlet.mvc.support.MvcUrlUtils.*;
|
||||
|
||||
/**
|
||||
* A test fixture with an {@link WebMvcConfigurationSupport} instance.
|
||||
@@ -57,27 +67,26 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
|
||||
*/
|
||||
public class WebMvcConfigurationSupportTests {
|
||||
|
||||
private WebMvcConfigurationSupport mvcConfiguration;
|
||||
|
||||
private StaticWebApplicationContext wac;
|
||||
private WebApplicationContext wac;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.wac = new StaticWebApplicationContext();
|
||||
this.mvcConfiguration = new WebMvcConfigurationSupport();
|
||||
this.mvcConfiguration.setApplicationContext(wac);
|
||||
|
||||
AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext();
|
||||
cxt.setServletContext(new MockServletContext());
|
||||
cxt.register(TestConfig.class);
|
||||
cxt.refresh();
|
||||
|
||||
this.wac = cxt;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerMapping() throws Exception {
|
||||
this.wac.registerSingleton("controller", TestController.class);
|
||||
|
||||
RequestMappingHandlerMapping handlerMapping = mvcConfiguration.requestMappingHandlerMapping();
|
||||
RequestMappingHandlerMapping handlerMapping = this.wac.getBean(RequestMappingHandlerMapping.class);
|
||||
assertEquals(0, handlerMapping.getOrder());
|
||||
|
||||
handlerMapping.setApplicationContext(this.wac);
|
||||
handlerMapping.afterPropertiesSet();
|
||||
HandlerExecutionChain chain = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/"));
|
||||
assertNotNull(chain.getInterceptors());
|
||||
assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[0].getClass());
|
||||
@@ -85,7 +94,10 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
public void emptyViewControllerHandlerMapping() {
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.viewControllerHandlerMapping();
|
||||
|
||||
AbstractHandlerMapping handlerMapping = this.wac.getBean(
|
||||
"viewControllerHandlerMapping", AbstractHandlerMapping.class);
|
||||
|
||||
assertNotNull(handlerMapping);
|
||||
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
|
||||
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping"));
|
||||
@@ -93,16 +105,13 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
public void beanNameHandlerMapping() throws Exception {
|
||||
StaticWebApplicationContext cxt = new StaticWebApplicationContext();
|
||||
cxt.registerSingleton("/controller", TestController.class);
|
||||
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/controller");
|
||||
|
||||
BeanNameUrlHandlerMapping handlerMapping = mvcConfiguration.beanNameHandlerMapping();
|
||||
BeanNameUrlHandlerMapping handlerMapping = this.wac.getBean(BeanNameUrlHandlerMapping.class);
|
||||
assertEquals(2, handlerMapping.getOrder());
|
||||
|
||||
handlerMapping.setApplicationContext(cxt);
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/testController");
|
||||
HandlerExecutionChain chain = handlerMapping.getHandler(request);
|
||||
|
||||
assertNotNull(chain.getInterceptors());
|
||||
assertEquals(2, chain.getInterceptors().length);
|
||||
assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass());
|
||||
@@ -110,8 +119,10 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
public void emptyResourceHandlerMapping() {
|
||||
mvcConfiguration.setApplicationContext(new StaticWebApplicationContext());
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.resourceHandlerMapping();
|
||||
|
||||
AbstractHandlerMapping handlerMapping = this.wac.getBean(
|
||||
"resourceHandlerMapping", AbstractHandlerMapping.class);
|
||||
|
||||
assertNotNull(handlerMapping);
|
||||
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
|
||||
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping"));
|
||||
@@ -119,8 +130,10 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
public void emptyDefaultServletHandlerMapping() {
|
||||
mvcConfiguration.setServletContext(new MockServletContext());
|
||||
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.defaultServletHandlerMapping();
|
||||
|
||||
AbstractHandlerMapping handlerMapping = this.wac.getBean(
|
||||
"defaultServletHandlerMapping", AbstractHandlerMapping.class);
|
||||
|
||||
assertNotNull(handlerMapping);
|
||||
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
|
||||
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping"));
|
||||
@@ -128,11 +141,10 @@ public class WebMvcConfigurationSupportTests {
|
||||
|
||||
@Test
|
||||
public void requestMappingHandlerAdapter() throws Exception {
|
||||
RequestMappingHandlerAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter();
|
||||
|
||||
List<HttpMessageConverter<?>> expectedConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
mvcConfiguration.addDefaultHttpMessageConverters(expectedConverters);
|
||||
assertEquals(expectedConverters.size(), adapter.getMessageConverters().size());
|
||||
RequestMappingHandlerAdapter adapter = this.wac.getBean(RequestMappingHandlerAdapter.class);
|
||||
|
||||
assertEquals(9, adapter.getMessageConverters().size());
|
||||
|
||||
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
|
||||
assertNotNull(initializer);
|
||||
@@ -146,10 +158,27 @@ public class WebMvcConfigurationSupportTests {
|
||||
assertTrue(validator instanceof LocalValidatorFactoryBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mvcUrls() throws Exception {
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
|
||||
try {
|
||||
DateTime now = DateTime.now();
|
||||
MvcUrls mvcUrls = this.wac.getBean(MvcUrls.class);
|
||||
UriComponents uriComponents = mvcUrls.linkToMethodOn(controller(
|
||||
TestController.class).methodWithTwoPathVariables(1, now));
|
||||
|
||||
assertEquals("/foo/1/bar/" + ISODateTimeFormat.date().print(now), uriComponents.getPath());
|
||||
}
|
||||
finally {
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlerExceptionResolver() throws Exception {
|
||||
|
||||
HandlerExceptionResolverComposite compositeResolver =
|
||||
(HandlerExceptionResolverComposite) mvcConfiguration.handlerExceptionResolver();
|
||||
this.wac.getBean("handlerExceptionResolver", HandlerExceptionResolverComposite.class);
|
||||
|
||||
assertEquals(0, compositeResolver.getOrder());
|
||||
|
||||
@@ -164,12 +193,28 @@ public class WebMvcConfigurationSupportTests {
|
||||
}
|
||||
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
public static class TestConfig {
|
||||
|
||||
@Bean(name={"/testController"})
|
||||
public TestController testController() {
|
||||
return new TestController();
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
private static class TestController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public void handle() {
|
||||
}
|
||||
|
||||
@RequestMapping("/foo/{id}/bar/{date}")
|
||||
public HttpEntity<Void> methodWithTwoPathVariables(@PathVariable Integer id,
|
||||
@DateTimeFormat(iso = ISO.DATE) @PathVariable DateTime date) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.hypermedia;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.AnnotationAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationMappingDiscoverer}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AnnotationMappingDiscovererUnitTests {
|
||||
|
||||
AnnotationMappingDiscoverer discoverer = new AnnotationMappingDiscoverer(
|
||||
RequestMapping.class);
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullAnnotationType() {
|
||||
new AnnotationMappingDiscoverer((Class<? extends Annotation>) null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullAnnotationAttribute() {
|
||||
new AnnotationMappingDiscoverer((AnnotationAttribute) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversTypeLevelMapping() {
|
||||
assertThat(discoverer.getMapping(MyController.class), is("/type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversMethodLevelMapping() throws Exception {
|
||||
Method method = MyController.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method), is("/type/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullForNonExistentTypeLevelMapping() {
|
||||
assertThat(discoverer.getMapping(ControllerWithoutTypeLevelMapping.class),
|
||||
is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesMethodLevelMappingWithoutTypeLevelMapping() throws Exception {
|
||||
|
||||
Method method = ControllerWithoutTypeLevelMapping.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method), is("/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesMethodLevelMappingWithSlashRootMapping() throws Exception {
|
||||
|
||||
Method method = SlashRootMapping.class.getMethod("method");
|
||||
assertThat(discoverer.getMapping(method), is("/method"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #46
|
||||
*/
|
||||
@Test
|
||||
public void treatsMissingMethodMappingAsEmptyMapping() throws Exception {
|
||||
|
||||
Method method = MyController.class.getMethod("noMethodMapping");
|
||||
assertThat(discoverer.getMapping(method), is("/type"));
|
||||
}
|
||||
|
||||
@RequestMapping("/type")
|
||||
interface MyController {
|
||||
|
||||
@RequestMapping("/method")
|
||||
void method();
|
||||
|
||||
@RequestMapping
|
||||
void noMethodMapping();
|
||||
}
|
||||
|
||||
interface ControllerWithoutTypeLevelMapping {
|
||||
|
||||
@RequestMapping("/method")
|
||||
void method();
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
interface SlashRootMapping {
|
||||
|
||||
@RequestMapping("/method")
|
||||
void method();
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.hypermedia;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.hypermedia.MvcUriComponentsBuilderUnitTests.PersonControllerImpl;
|
||||
import org.springframework.web.servlet.hypermedia.MvcUriComponentsBuilderUnitTests.PersonsAddressesController;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.servlet.hypermedia.MvcUriComponentsBuilder.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MvcUriComponentsBuilderFactory}.
|
||||
*
|
||||
* @author Ricardo Gladwell
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MvcUriComponentsBuilderFactoryUnitTests extends TestUtils {
|
||||
|
||||
List<UriComponentsContributor> contributors = Collections.emptyList();
|
||||
|
||||
MvcUriComponentsBuilderFactory factory = new MvcUriComponentsBuilderFactory(
|
||||
contributors);
|
||||
|
||||
@Test
|
||||
public void createsLinkToControllerRoot() {
|
||||
|
||||
URI link = factory.from(PersonControllerImpl.class).build().toUri();
|
||||
|
||||
assertPointsToMockServer(link);
|
||||
assertThat(link.toString(), endsWith("/people"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsLinkToParameterizedControllerRoot() {
|
||||
|
||||
URI link = factory.from(PersonsAddressesController.class, 15).build().toUri();
|
||||
|
||||
assertPointsToMockServer(link);
|
||||
assertThat(link.toString(), endsWith("/people/15/addresses"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appliesParameterValueIfContributorConfigured() {
|
||||
|
||||
List<? extends UriComponentsContributor> contributors = Arrays.asList(new SampleUriComponentsContributor());
|
||||
MvcUriComponentsBuilderFactory factory = new MvcUriComponentsBuilderFactory(
|
||||
contributors);
|
||||
|
||||
SpecialType specialType = new SpecialType();
|
||||
specialType.parameterValue = "value";
|
||||
|
||||
URI link = factory.from(
|
||||
methodOn(SampleController.class).sampleMethod(1L, specialType)).build().toUri();
|
||||
assertPointsToMockServer(link);
|
||||
assertThat(link.toString(), endsWith("/sample/1?foo=value"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #57
|
||||
*/
|
||||
@Test
|
||||
public void usesDateTimeFormatForUriBinding() {
|
||||
|
||||
DateTime now = DateTime.now();
|
||||
|
||||
MvcUriComponentsBuilderFactory factory = new MvcUriComponentsBuilderFactory(
|
||||
contributors);
|
||||
URI link = factory.from(methodOn(SampleController.class).sampleMethod(now)).build().toUri();
|
||||
assertThat(link.toString(),
|
||||
endsWith("/sample/" + ISODateTimeFormat.date().print(now)));
|
||||
}
|
||||
|
||||
static interface SampleController {
|
||||
|
||||
@RequestMapping("/sample/{id}")
|
||||
HttpEntity<?> sampleMethod(@PathVariable("id") Long id, SpecialType parameter);
|
||||
|
||||
@RequestMapping("/sample/{time}")
|
||||
HttpEntity<?> sampleMethod(
|
||||
@PathVariable("time") @DateTimeFormat(iso = ISO.DATE) DateTime time);
|
||||
}
|
||||
|
||||
static class SampleUriComponentsContributor implements UriComponentsContributor {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return SpecialType.class.equals(parameter.getParameterType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enhance(UriComponentsBuilder builder, MethodParameter parameter,
|
||||
Object value) {
|
||||
builder.queryParam("foo", ((SpecialType) value).parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
static class SpecialType {
|
||||
|
||||
String parameterValue;
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.hypermedia;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.servlet.hypermedia.MvcUriComponentsBuilder.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MvcUriComponentsBuilder}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Dietrich Schulten
|
||||
*/
|
||||
public class MvcUriComponentsBuilderUnitTests extends TestUtils {
|
||||
|
||||
@Test
|
||||
public void createsLinkToControllerRoot() {
|
||||
|
||||
URI link = from(PersonControllerImpl.class).build().toUri();
|
||||
assertThat(link.toString(), Matchers.endsWith("/people"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsLinkToParameterizedControllerRoot() {
|
||||
|
||||
URI link = from(PersonsAddressesController.class, 15).build().toUri();
|
||||
assertThat(link.toString(), endsWith("/people/15/addresses"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #70
|
||||
*/
|
||||
@Test
|
||||
public void createsLinkToMethodOnParameterizedControllerRoot() {
|
||||
|
||||
URI link = from(
|
||||
methodOn(PersonsAddressesController.class, 15).getAddressesForCountry(
|
||||
"DE")).build().toUri();
|
||||
assertThat(link.toString(), endsWith("/people/15/addresses/DE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsLinkToSubResource() {
|
||||
|
||||
URI link = from(PersonControllerImpl.class).pathSegment("something").build().toUri();
|
||||
assertThat(link.toString(), endsWith("/people/something"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsControllerWithMultipleMappings() {
|
||||
from(InvalidController.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsLinkToUnmappedController() {
|
||||
|
||||
URI link = from(UnmappedController.class).build().toUri();
|
||||
assertThat(link.toString(), is("http://localhost/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendingNullIsANoOp() {
|
||||
|
||||
URI link = from(PersonControllerImpl.class).path(null).build().toUri();
|
||||
assertThat(link.toString(), endsWith("/people"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToMethod() {
|
||||
|
||||
URI link = from(methodOn(ControllerWithMethods.class).myMethod(null)).build().toUri();
|
||||
assertPointsToMockServer(link);
|
||||
assertThat(link.toString(), endsWith("/something/else"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToMethodWithPathVariable() {
|
||||
|
||||
URI link = from(methodOn(ControllerWithMethods.class).methodWithPathVariable("1")).build().toUri();
|
||||
assertPointsToMockServer(link);
|
||||
assertThat(link.toString(), endsWith("/something/1/foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #33
|
||||
*/
|
||||
@Test
|
||||
public void usesForwardedHostAsHostIfHeaderIsSet() {
|
||||
|
||||
request.addHeader("X-Forwarded-Host", "somethingDifferent");
|
||||
|
||||
URI link = from(PersonControllerImpl.class).build().toUri();
|
||||
assertThat(link.toString(), startsWith("http://somethingDifferent"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #26, #39
|
||||
*/
|
||||
@Test
|
||||
public void linksToMethodWithPathVariableAndRequestParams() {
|
||||
|
||||
URI link = from(
|
||||
methodOn(ControllerWithMethods.class).methodForNextPage("1", 10, 5)).build().toUri();
|
||||
|
||||
UriComponents components = toComponents(link);
|
||||
assertThat(components.getPath(), is("/something/1/foo"));
|
||||
|
||||
MultiValueMap<String, String> queryParams = components.getQueryParams();
|
||||
assertThat(queryParams.get("limit"), contains("5"));
|
||||
assertThat(queryParams.get("offset"), contains("10"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #26, #39
|
||||
*/
|
||||
@Test
|
||||
public void linksToMethodWithPathVariableAndMultiValueRequestParams() {
|
||||
|
||||
URI link = from(
|
||||
methodOn(ControllerWithMethods.class).methodWithMultiValueRequestParams(
|
||||
"1", Arrays.asList(3, 7), 5)).build().toUri();
|
||||
|
||||
UriComponents components = toComponents(link);
|
||||
assertThat(components.getPath(), is("/something/1/foo"));
|
||||
|
||||
MultiValueMap<String, String> queryParams = components.getQueryParams();
|
||||
assertThat(queryParams.get("limit"), contains("5"));
|
||||
assertThat(queryParams.get("items"), containsInAnyOrder("3", "7"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #90
|
||||
*/
|
||||
@Test
|
||||
public void usesForwardedHostAndPortFromHeader() {
|
||||
|
||||
request.addHeader("X-Forwarded-Host", "foobar:8088");
|
||||
|
||||
URI link = from(PersonControllerImpl.class).build().toUri();
|
||||
assertThat(link.toString(), startsWith("http://foobar:8088"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #90
|
||||
*/
|
||||
@Test
|
||||
public void usesFirstHostOfXForwardedHost() {
|
||||
|
||||
request.addHeader("X-Forwarded-Host", "barfoo:8888, localhost:8088");
|
||||
|
||||
URI link = from(PersonControllerImpl.class).build().toUri();
|
||||
assertThat(link.toString(), startsWith("http://barfoo:8888"));
|
||||
}
|
||||
|
||||
private static UriComponents toComponents(URI link) {
|
||||
return UriComponentsBuilder.fromUri(link).build();
|
||||
}
|
||||
|
||||
static class Person {
|
||||
|
||||
Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/people")
|
||||
interface PersonController {
|
||||
|
||||
}
|
||||
|
||||
class PersonControllerImpl implements PersonController {
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/people/{id}/addresses")
|
||||
static class PersonsAddressesController {
|
||||
|
||||
@RequestMapping("/{country}")
|
||||
public HttpEntity<Void> getAddressesForCountry(@PathVariable String country) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping({ "/persons", "/people" })
|
||||
class InvalidController {
|
||||
|
||||
}
|
||||
|
||||
class UnmappedController {
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/something")
|
||||
static class ControllerWithMethods {
|
||||
|
||||
@RequestMapping("/else")
|
||||
HttpEntity<Void> myMethod(@RequestBody Object payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping("/{id}/foo")
|
||||
HttpEntity<Void> methodWithPathVariable(@PathVariable String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{id}/foo")
|
||||
HttpEntity<Void> methodForNextPage(@PathVariable String id,
|
||||
@RequestParam Integer offset, @RequestParam Integer limit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{id}/foo")
|
||||
HttpEntity<Void> methodWithMultiValueRequestParams(@PathVariable String id,
|
||||
@RequestParam List<Integer> items, @RequestParam Integer limit) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 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.hypermedia;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class RecordedInvocationUtilsUnitTests extends TestUtils {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
MvcUriComponentsBuilder.from(RecordedInvocationUtils.methodOn(SampleController.class).someMethod(
|
||||
1L));
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/sample")
|
||||
static class SampleController {
|
||||
|
||||
@RequestMapping("/{id}/foo")
|
||||
HttpEntity<Void> someMethod(@PathVariable("id") Long id) {
|
||||
return new ResponseEntity<Void>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.hypermedia;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Utility class to ease tesing.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class TestUtils {
|
||||
|
||||
protected MockHttpServletRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||
}
|
||||
|
||||
protected void assertPointsToMockServer(URI link) {
|
||||
assertThat(link.toString(), startsWith("http://localhost"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.mvc.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.web.servlet.mvc.support.MvcUrlUtils.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultMvcUrls}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Dietrich Schulten
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class DefaultMvcUrlsTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MvcUrls mvcUrls;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.request = new MockHttpServletRequest();
|
||||
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||
|
||||
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
|
||||
resolvers.add(new PathVariableMethodArgumentResolver());
|
||||
resolvers.add(new RequestParamMethodArgumentResolver(null, false));
|
||||
|
||||
this.mvcUrls = new DefaultMvcUrls(resolvers, null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void linkToControllerRoot() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(PersonControllerImpl.class).build();
|
||||
assertThat(uriComponents.toUriString(), Matchers.endsWith("/people"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToParameterizedControllerRoot() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(
|
||||
PersonsAddressesController.class).buildAndExpand(15);
|
||||
|
||||
assertThat(uriComponents.toUriString(), endsWith("/people/15/addresses"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodOnParameterizedControllerRoot() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethodOn(
|
||||
controller(PersonsAddressesController.class, 15).getAddressesForCountry("DE"));
|
||||
|
||||
assertThat(uriComponents.toUriString(), endsWith("/people/15/addresses/DE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToSubResource() {
|
||||
UriComponents uriComponents =
|
||||
this.mvcUrls.linkToController(PersonControllerImpl.class).pathSegment("something").build();
|
||||
|
||||
assertThat(uriComponents.toUriString(), endsWith("/people/something"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToControllerWithMultipleMappings() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(InvalidController.class).build();
|
||||
assertThat(uriComponents.toUriString(), is("http://localhost/persons"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToControllerNotMapped() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(UnmappedController.class).build();
|
||||
assertThat(uriComponents.toUriString(), is("http://localhost/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodRefWithPathVar() throws Exception {
|
||||
Method method = ControllerWithMethods.class.getDeclaredMethod("methodWithPathVariable", String.class);
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethod(method, new Object[] { "1" });
|
||||
|
||||
assertThat(uriComponents.toUriString(), is("http://localhost/something/1/foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodRefWithTwoPathVars() throws Exception {
|
||||
DateTime now = DateTime.now();
|
||||
Method method = ControllerWithMethods.class.getDeclaredMethod(
|
||||
"methodWithTwoPathVariables", Integer.class, DateTime.class);
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethod(method, new Object[] { 1, now });
|
||||
|
||||
assertThat(uriComponents.getPath(), is("/something/1/foo/" + ISODateTimeFormat.date().print(now)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodRefWithPathVarAndRequestParam() throws Exception {
|
||||
Method method = ControllerWithMethods.class.getDeclaredMethod("methodForNextPage", String.class, Integer.class, Integer.class);
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethod(method, new Object[] {"1", 10, 5});
|
||||
|
||||
assertThat(uriComponents.getPath(), is("/something/1/foo"));
|
||||
|
||||
MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
|
||||
assertThat(queryParams.get("limit"), contains("5"));
|
||||
assertThat(queryParams.get("offset"), contains("10"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethod() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethodOn(
|
||||
controller(ControllerWithMethods.class).myMethod(null));
|
||||
|
||||
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
|
||||
assertThat(uriComponents.toUriString(), endsWith("/something/else"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodWithPathVar() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethodOn(
|
||||
controller(ControllerWithMethods.class).methodWithPathVariable("1"));
|
||||
|
||||
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
|
||||
assertThat(uriComponents.toUriString(), endsWith("/something/1/foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodWithPathVarAndRequestParams() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethodOn(
|
||||
controller(ControllerWithMethods.class).methodForNextPage("1", 10, 5));
|
||||
|
||||
assertThat(uriComponents.getPath(), is("/something/1/foo"));
|
||||
|
||||
MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
|
||||
assertThat(queryParams.get("limit"), contains("5"));
|
||||
assertThat(queryParams.get("offset"), contains("10"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkToMethodWithPathVarAndMultiValueRequestParams() {
|
||||
UriComponents uriComponents = this.mvcUrls.linkToMethodOn(
|
||||
controller(ControllerWithMethods.class).methodWithMultiValueRequestParams(
|
||||
"1", Arrays.asList(3, 7), 5));
|
||||
|
||||
assertThat(uriComponents.getPath(), is("/something/1/foo"));
|
||||
|
||||
MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
|
||||
assertThat(queryParams.get("limit"), contains("5"));
|
||||
assertThat(queryParams.get("items"), containsInAnyOrder("3", "7"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesForwardedHostAsHostIfHeaderIsSet() {
|
||||
this.request.addHeader("X-Forwarded-Host", "somethingDifferent");
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(PersonControllerImpl.class).build();
|
||||
|
||||
assertThat(uriComponents.toUriString(), startsWith("http://somethingDifferent"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesForwardedHostAndPortFromHeader() {
|
||||
request.addHeader("X-Forwarded-Host", "foobar:8088");
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(PersonControllerImpl.class).build();
|
||||
|
||||
assertThat(uriComponents.toUriString(), startsWith("http://foobar:8088"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesFirstHostOfXForwardedHost() {
|
||||
request.addHeader("X-Forwarded-Host", "barfoo:8888, localhost:8088");
|
||||
UriComponents uriComponents = this.mvcUrls.linkToController(PersonControllerImpl.class).build();
|
||||
|
||||
assertThat(uriComponents.toUriString(), startsWith("http://barfoo:8888"));
|
||||
}
|
||||
|
||||
|
||||
static class Person {
|
||||
|
||||
Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/people")
|
||||
interface PersonController {
|
||||
|
||||
}
|
||||
|
||||
class PersonControllerImpl implements PersonController {
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/people/{id}/addresses")
|
||||
static class PersonsAddressesController {
|
||||
|
||||
@RequestMapping("/{country}")
|
||||
public HttpEntity<Void> getAddressesForCountry(@PathVariable String country) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping({ "/persons", "/people" })
|
||||
class InvalidController {
|
||||
|
||||
}
|
||||
|
||||
class UnmappedController {
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/something")
|
||||
static class ControllerWithMethods {
|
||||
|
||||
@RequestMapping("/else")
|
||||
HttpEntity<Void> myMethod(@RequestBody Object payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping("/{id}/foo")
|
||||
HttpEntity<Void> methodWithPathVariable(@PathVariable String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping("/{id}/foo/{date}")
|
||||
HttpEntity<Void> methodWithTwoPathVariables(
|
||||
@PathVariable Integer id, @DateTimeFormat(iso = ISO.DATE) @PathVariable DateTime date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{id}/foo")
|
||||
HttpEntity<Void> methodForNextPage(@PathVariable String id,
|
||||
@RequestParam Integer offset, @RequestParam Integer limit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{id}/foo")
|
||||
HttpEntity<Void> methodWithMultiValueRequestParams(@PathVariable String id,
|
||||
@RequestParam List<Integer> items, @RequestParam Integer limit) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.mvc.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.servlet.mvc.support.MvcUrlUtils.ControllerMethodValues;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link MvcUrlUtils}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MvcUrlUtilsTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.request = new MockHttpServletRequest();
|
||||
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodOn() {
|
||||
HttpEntity<Void> result = MvcUrlUtils.controller(SampleController.class).someMethod(1L);
|
||||
|
||||
assertTrue(result instanceof ControllerMethodValues);
|
||||
assertEquals("someMethod", ((ControllerMethodValues) result).getControllerMethod().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeLevelMapping() {
|
||||
assertThat(MvcUrlUtils.getTypeLevelMapping(MyController.class), is("/type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeLevelMappingNone() {
|
||||
assertThat(MvcUrlUtils.getTypeLevelMapping(ControllerWithoutTypeLevelMapping.class), is("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodLevelMapping() throws Exception {
|
||||
Method method = MyController.class.getMethod("method");
|
||||
assertThat(MvcUrlUtils.getMethodMapping(method), is("/type/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodLevelMappingWithoutTypeLevelMapping() throws Exception {
|
||||
Method method = ControllerWithoutTypeLevelMapping.class.getMethod("method");
|
||||
assertThat(MvcUrlUtils.getMethodMapping(method), is("/method"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodMappingWithControllerMappingOnly() throws Exception {
|
||||
Method method = MyController.class.getMethod("noMethodMapping");
|
||||
assertThat(MvcUrlUtils.getMethodMapping(method), is("/type"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/sample")
|
||||
static class SampleController {
|
||||
|
||||
@RequestMapping("/{id}/foo")
|
||||
HttpEntity<Void> someMethod(@PathVariable("id") Long id) {
|
||||
return new ResponseEntity<Void>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/type")
|
||||
interface MyController {
|
||||
|
||||
@RequestMapping("/method")
|
||||
void method();
|
||||
|
||||
@RequestMapping
|
||||
void noMethodMapping();
|
||||
}
|
||||
|
||||
interface ControllerWithoutTypeLevelMapping {
|
||||
|
||||
@RequestMapping("/method")
|
||||
void method();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user