From 1a6cae4c7d66263a2cc53bc0d8edecd7a62f6a8f Mon Sep 17 00:00:00 2001 From: Josh Ghiloni Date: Sun, 20 Sep 2015 09:50:54 -0600 Subject: [PATCH 1/2] Issue #361: Add Support for Resolving Property Values in @RequestMapping(value) --- .../core/AnnotationMappingDiscoverer.java | 31 +++++- .../hateoas/mvc/ControllerLinkBuilder.java | 99 ++++++++++++++++++- .../mvc/ControllerLinkBuilderFactory.java | 23 ++++- .../AnnotationMappingDiscovererUnitTest.java | 41 ++++++++ .../ControllerLinkBuilderFactoryUnitTest.java | 47 ++++++++- .../mvc/ControllerLinkBuilderUnitTest.java | 35 +++++++ 6 files changed, 265 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java b/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java index b723877d2..7c3a1a2df 100644 --- a/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java +++ b/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java @@ -20,12 +20,15 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import org.springframework.core.env.Environment; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * {@link MappingDiscoverer} implementation that inspects mappings from a particular annotation. * * @author Oliver Gierke + * @author Josh Ghiloni */ public class AnnotationMappingDiscoverer implements MappingDiscoverer { @@ -62,6 +65,10 @@ public AnnotationMappingDiscoverer(Class annotation, Strin */ @Override public String getMapping(Class type) { + return getMapping(null, type); + } + + public String getMapping(Environment environment, Class type) { Assert.notNull(type, "Type must not be null!"); @@ -72,7 +79,7 @@ public String getMapping(Class type) { type.getName())); } - return mapping.length == 0 ? null : mapping[0]; + return mapping.length == 0 ? null : maybeResolveValue(environment, mapping[0]); } /* @@ -81,9 +88,12 @@ public String getMapping(Class type) { */ @Override public String getMapping(Method method) { - + return getMapping(method, null); + } + + public String getMapping(Method method, Environment environment) { Assert.notNull(method, "Method must not be null!"); - return getMapping(method.getDeclaringClass(), method); + return getMapping(method.getDeclaringClass(), method, environment); } /* @@ -92,6 +102,10 @@ public String getMapping(Method method) { */ @Override public String getMapping(Class type, Method method) { + return getMapping(type, method, null); + } + + public String getMapping(Class type, Method method, Environment environment) { Assert.notNull(type, "Type must not be null!"); Assert.notNull(method, "Method must not be null!"); @@ -109,7 +123,8 @@ public String getMapping(Class type, Method method) { return typeMapping; } - return typeMapping == null || "/".equals(typeMapping) ? mapping[0] : typeMapping + mapping[0]; + String returnValue = (typeMapping == null || "/".equals(typeMapping) ? mapping[0] : typeMapping + mapping[0]); + return maybeResolveValue(environment, returnValue); } private String[] getMappingFrom(Annotation annotation) { @@ -127,4 +142,12 @@ private String[] getMappingFrom(Annotation annotation) { throw new IllegalStateException(String.format( "Unsupported type for the mapping attribute! Support String and String[] but got %s!", value.getClass())); } + + private String maybeResolveValue(Environment environment, String value) { + if (environment != null && StringUtils.hasText(value)) { + value = environment.resolvePlaceholders(value); + } + + return value; + } } diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java index 1c760e9ff..be334a638 100755 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest; +import org.springframework.core.env.Environment; import org.springframework.hateoas.Link; import org.springframework.hateoas.core.AnnotationMappingDiscoverer; import org.springframework.hateoas.core.DummyInvocationUtils; @@ -43,6 +44,7 @@ * @author Oliver Gierke * @author Kamill Sokol * @author Greg Turnquist + * @author Josh Ghiloni */ public class ControllerLinkBuilder extends LinkBuilderSupport { @@ -66,7 +68,18 @@ public class ControllerLinkBuilder extends LinkBuilderSupport controller) { - return linkTo(controller, new Object[0]); + return linkTo(null, controller, new Object[0]); + } + + /** + * Creates a new {@link ControllerLinkBuilder} with a base of the mapping annotated to the given controller class. + * + * @param env If not {@literal null}, it will attempt to resolve placeholders in mappings + * @param controller the class to discover the annotation on, must not be {@literal null}. + * @return + */ + public static ControllerLinkBuilder linkTo(Environment environment, Class controller) { + return linkTo(environment, controller, new Object[0]); } /** @@ -79,11 +92,26 @@ public static ControllerLinkBuilder linkTo(Class controller) { * @return */ public static ControllerLinkBuilder linkTo(Class controller, Object... parameters) { + return linkTo(null, controller, parameters); + } + + /** + * Creates a new {@link ControllerLinkBuilder} with a base of the mapping annotated to the given controller class. The + * additional parameters are used to fill up potentially available path variables in the class scop request mapping. + * + * If the env parameter is non-null, it will attempt to resolve any placeholders found in mappings + * + * @param env + * @param controller + * @param parameters + * @return + */ + public static ControllerLinkBuilder linkTo(Environment env, Class controller, Object... parameters) { Assert.notNull(controller); ControllerLinkBuilder builder = new ControllerLinkBuilder(getBuilder()); - String mapping = DISCOVERER.getMapping(controller); + String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(env, controller); UriComponents uriComponents = UriComponentsBuilder.fromUriString(mapping == null ? "/" : mapping).build(); UriComponents expandedComponents = uriComponents.expand(parameters); @@ -95,18 +123,49 @@ public static ControllerLinkBuilder linkTo(Class controller, Object... parame * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...) */ public static ControllerLinkBuilder linkTo(Method method, Object... parameters) { - return linkTo(method.getDeclaringClass(), method, parameters); + return linkTo(null, method.getDeclaringClass(), method, parameters); + } + + /** + * Similar to {@link org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...)} + * but takes an optional {@link Environment} parameter. If it is non-null, it will attempt to resolve + * any placeholders in requestMappings that were found. + * + * @param env + * @param method + * @param parameters + * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...) + * @return + */ + public static ControllerLinkBuilder linkTo(Environment env, Method method, Object... parameters) { + return linkTo(env, method.getDeclaringClass(), method, parameters); } /* * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...) */ public static ControllerLinkBuilder linkTo(Class controller, Method method, Object... parameters) { + return linkTo(null, controller, method, parameters); + } + + /** + * Similar to {@link org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...)} + * but takes an optional {@link Environment} parameter. If it is non-null, it will attempt to resolve + * any placeholders in requestMappings that were found. + * + * @param env + * @param controller + * @param method + * @param parameters + * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...) + * @return + */ + public static ControllerLinkBuilder linkTo(Environment env, Class controller, Method method, Object... parameters) { Assert.notNull(controller, "Controller type must not be null!"); Assert.notNull(method, "Method must not be null!"); - UriTemplate template = new UriTemplate(DISCOVERER.getMapping(controller, method)); + UriTemplate template = new UriTemplate(((AnnotationMappingDiscoverer)DISCOVERER).getMapping(controller, method, env)); URI uri = template.expand(parameters); return new ControllerLinkBuilder(getBuilder()).slash(uri); @@ -135,7 +194,37 @@ public static ControllerLinkBuilder linkTo(Class controller, Method method, O * @return */ public static ControllerLinkBuilder linkTo(Object invocationValue) { - return FACTORY.linkTo(invocationValue); + return FACTORY.linkTo(null, invocationValue); + } + + /** + * Creates a {@link ControllerLinkBuilder} pointing to a controller method. Hand in a dummy method invocation result + * you can create via {@link #methodOn(Class, Object...)} or {@link DummyInvocationUtils#methodOn(Class, Object...)}. + * + *
+	 * @RequestMapping("/customers")
+	 * class CustomerController {
+	 * 
+	 *   @RequestMapping("/{id}/addresses")
+	 *   HttpEntity<Addresses> showAddresses(@PathVariable Long id) { … } 
+	 * }
+	 * 
+	 * Link link = linkTo(methodOn(CustomerController.class).showAddresses(2L)).withRel("addresses");
+	 * 
+ * + * If the {@link Environment} parameter is non-null, it will attempt to resolve any placeholders + * found in the mapping + * + * The resulting {@link Link} instance will point to {@code /customers/2/addresses} and have a rel of + * {@code addresses}. For more details on the method invocation constraints, see + * {@link DummyInvocationUtils#methodOn(Class, Object...)}. + * + * @param environment + * @param invocationValue + * @return + */ + public static ControllerLinkBuilder linkTo(Environment environment, Object invocationValue) { + return FACTORY.linkTo(environment, invocationValue); } /** diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java index 20fb052ed..7f8db77f5 100644 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java @@ -26,6 +26,7 @@ import java.util.Map; import org.springframework.core.MethodParameter; +import org.springframework.core.env.Environment; import org.springframework.hateoas.Link; import org.springframework.hateoas.MethodLinkBuilderFactory; import org.springframework.hateoas.core.AnnotationAttribute; @@ -84,6 +85,10 @@ public void setUriComponentsContributors(List controller) { return ControllerLinkBuilder.linkTo(controller); } + + public ControllerLinkBuilder linkTo(Environment env, Class controller) { + return ControllerLinkBuilder.linkTo(env, controller); + } /* * (non-Javadoc) @@ -93,6 +98,10 @@ public ControllerLinkBuilder linkTo(Class controller) { public ControllerLinkBuilder linkTo(Class controller, Object... parameters) { return ControllerLinkBuilder.linkTo(controller, parameters); } + + public ControllerLinkBuilder linkTo(Environment env, Class controller, Object... parameters) { + return ControllerLinkBuilder.linkTo(env, controller, parameters); + } /* * (non-Javadoc) @@ -102,6 +111,10 @@ public ControllerLinkBuilder linkTo(Class controller, Object... parameters) { public ControllerLinkBuilder linkTo(Class controller, Method method, Object... parameters) { return ControllerLinkBuilder.linkTo(controller, method, parameters); } + + public ControllerLinkBuilder linkTo(Environment env, Class controller, Method method, Object... parameters) { + return ControllerLinkBuilder.linkTo(env, controller, method, parameters); + } /* * (non-Javadoc) @@ -109,6 +122,10 @@ public ControllerLinkBuilder linkTo(Class controller, Method method, Object.. */ @Override public ControllerLinkBuilder linkTo(Object invocationValue) { + return linkTo(null, invocationValue); + } + + public ControllerLinkBuilder linkTo(Environment env, Object invocationValue) { Assert.isInstanceOf(LastInvocationAware.class, invocationValue); LastInvocationAware invocations = (LastInvocationAware) invocationValue; @@ -117,7 +134,7 @@ public ControllerLinkBuilder linkTo(Object invocationValue) { Iterator classMappingParameters = invocations.getObjectParameters(); Method method = invocation.getMethod(); - String mapping = DISCOVERER.getMapping(invocation.getTargetType(), method); + String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(invocation.getTargetType(), method, env); UriComponentsBuilder builder = ControllerLinkBuilder.getBuilder().path(mapping); UriTemplate template = new UriTemplate(mapping); @@ -148,6 +165,10 @@ public ControllerLinkBuilder linkTo(Object invocationValue) { public ControllerLinkBuilder linkTo(Method method, Object... parameters) { return ControllerLinkBuilder.linkTo(method, parameters); } + + public ControllerLinkBuilder linkTo(Environment env, Method method, Object... parameters) { + return ControllerLinkBuilder.linkTo(env, method, parameters); + } /** * Applies the configured {@link UriComponentsContributor}s to the given {@link UriComponentsBuilder}. diff --git a/src/test/java/org/springframework/hateoas/core/AnnotationMappingDiscovererUnitTest.java b/src/test/java/org/springframework/hateoas/core/AnnotationMappingDiscovererUnitTest.java index c45b4968c..46f5a9db7 100644 --- a/src/test/java/org/springframework/hateoas/core/AnnotationMappingDiscovererUnitTest.java +++ b/src/test/java/org/springframework/hateoas/core/AnnotationMappingDiscovererUnitTest.java @@ -19,8 +19,12 @@ import static org.junit.Assert.*; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; import org.junit.Test; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.StandardEnvironment; import org.springframework.web.bind.annotation.RequestMapping; /** @@ -96,6 +100,34 @@ public void includesTypeMappingFromChildClass() throws Exception { Method method = ParentWithMethod.class.getMethod("mapping"); assertThat(discoverer.getMapping(ChildWithTypeMapping.class, method), is("/child/parent")); } + + /** + * @see #361 + */ + @Test + public void resolvesVariablesInMappings() throws Exception { + Map source = new HashMap(); + source.put("test.variable", "/dynamicparent"); + source.put("test.child", "/dynamicchild"); + + StandardEnvironment env = new StandardEnvironment(); + env.getPropertySources().addLast(new MapPropertySource("mapping-env", source)); + + Method method = DynamicEndpointControllerWithMethod.class.getMethod("method"); + + // test regression first + assertThat(discoverer.getMapping(DynamicEndpointController.class), is("${test.variable}")); + assertThat(discoverer.getMapping(DynamicEndpointControllerWithMethod.class, method), + is("${test.variable}${test.child}")); + + // test new feature + AnnotationMappingDiscoverer concreteDiscoverer = (AnnotationMappingDiscoverer)discoverer; + assertThat(concreteDiscoverer.getMapping(env, DynamicEndpointController.class), + is("/dynamicparent")); + assertThat(concreteDiscoverer.getMapping(method, env), is("/dynamicparent/dynamicchild")); + assertThat(concreteDiscoverer.getMapping(DynamicEndpointControllerWithMethod.class, method, env), + is("/dynamicparent/dynamicchild")); + } @RequestMapping("/type") interface MyController { @@ -139,4 +171,13 @@ interface ParentWithMethod { @RequestMapping("/child") interface ChildWithTypeMapping extends ParentWithMethod {} + + @RequestMapping("${test.variable}") + interface DynamicEndpointController {} + + @RequestMapping("${test.variable}") + interface DynamicEndpointControllerWithMethod { + @RequestMapping("${test.child}") + void method(); + } } diff --git a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java index c8f11bcfe..3e2f60306 100644 --- a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactoryUnitTest.java @@ -15,11 +15,14 @@ */ package org.springframework.hateoas.mvc; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; +import java.lang.reflect.Method; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -27,6 +30,8 @@ import org.joda.time.format.ISODateTimeFormat; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.StandardEnvironment; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.hateoas.Link; @@ -159,9 +164,40 @@ public void createsLinkToControllerMethodWithMultiValueMapRequestParam() { assertThat(link.getHref(), endsWith("/sample/multivaluemapsupport?key1=value1a&key1=value1b&key2=value2a&key2=value2b")); } + + /** + * @see #361 + */ + @Test + public void createsLinkToControllerMethodWithDynamicMapping() throws Exception { + Map source = new HashMap(); + source.put("test.variable", "/dynamicparent"); + source.put("test.child", "/dynamicchild"); + source.put("dynamicendpoint", "foo"); + + StandardEnvironment env = new StandardEnvironment(); + env.getPropertySources().addLast(new MapPropertySource("mapping-env", source)); + + Link link = factory.linkTo(env, methodOn(SampleController.class).sampleMethodWithDynamicEndpoint()).withSelfRel(); + assertPointsToMockServer(link); + assertThat(link.getRel(), is(Link.REL_SELF)); + assertThat(link.getHref(), endsWith("/sample/foo")); + + Method method = DynamicEndpointControllerWithMethod.class.getMethod("method"); + + link = factory.linkTo(env, DynamicEndpointControllerWithMethod.class).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent")); + + // explicitly add new Object[0] here to avoid conflict with (env, Object invocationValue) + link = factory.linkTo(env, method, new Object[0]).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent/dynamicchild")); + + link = factory.linkTo(env, DynamicEndpointControllerWithMethod.class, method).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent/dynamicchild")); + } - static interface SampleController { + static interface SampleController { @RequestMapping("/sample/{id}") HttpEntity sampleMethod(@PathVariable("id") Long id, SpecialType parameter); @@ -173,6 +209,15 @@ static interface SampleController { @RequestMapping("/sample/multivaluemapsupport") HttpEntity sampleMethodWithMap(@RequestParam MultiValueMap queryParams); + + @RequestMapping("/sample/${dynamicendpoint}") + HttpEntity sampleMethodWithDynamicEndpoint(); + } + + @RequestMapping("${test.variable}") + interface DynamicEndpointControllerWithMethod { + @RequestMapping("${test.child}") + void method(); } static class SampleUriComponentsContributor implements UriComponentsContributor { diff --git a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java index 918ace863..5c4793b1e 100644 --- a/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java +++ b/src/test/java/org/springframework/hateoas/mvc/ControllerLinkBuilderUnitTest.java @@ -21,13 +21,17 @@ import java.lang.reflect.Method; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.StandardEnvironment; import org.springframework.hateoas.Identifiable; import org.springframework.hateoas.Link; import org.springframework.hateoas.TestUtils; @@ -456,6 +460,31 @@ public void mentionsRequiredUsageWithinWebRequestInException() { linkTo(methodOn(ControllerLinkBuilderUnitTest.PersonsAddressesController.class, 15).getAddressesForCountry("DE")) .withSelfRel(); } + + /** + * @see #361 + */ + @Test + public void linksToDynamicEndpoints() throws Exception { + Map source = new HashMap(); + source.put("test.variable", "/dynamicparent"); + source.put("test.child", "/dynamicchild"); + + StandardEnvironment env = new StandardEnvironment(); + env.getPropertySources().addLast(new MapPropertySource("mapping-env", source)); + + Method method = DynamicEndpointControllerWithMethod.class.getMethod("method"); + + Link link = linkTo(env, DynamicEndpointControllerWithMethod.class).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent")); + + // explicitly add new Object[0] here to avoid conflict with (env, Object invocationValue) + link = linkTo(env, method, new Object[0]).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent/dynamicchild")); + + link = linkTo(env, DynamicEndpointControllerWithMethod.class, method).withSelfRel(); + assertThat(link.getHref(), endsWith("/dynamicparent/dynamicchild")); + } private static UriComponents toComponents(Link link) { return UriComponentsBuilder.fromUriString(link.getHref()).build(); @@ -563,4 +592,10 @@ interface ParentControllerWithoutRootMapping { interface ChildControllerWithRootMapping extends ParentControllerWithoutRootMapping { } + + @RequestMapping("${test.variable}") + interface DynamicEndpointControllerWithMethod { + @RequestMapping("${test.child}") + void method(); + } } From 334de4ea8ccf7fa338538f5a51fbe554ca531d4a Mon Sep 17 00:00:00 2001 From: Josh Ghiloni Date: Mon, 21 Sep 2015 08:54:11 -0600 Subject: [PATCH 2/2] Incorporate Juergen's review comments - change Environment to PropertyResolver --- .../core/AnnotationMappingDiscoverer.java | 19 ++++++----- .../hateoas/mvc/ControllerLinkBuilder.java | 34 +++++++++---------- .../mvc/ControllerLinkBuilderFactory.java | 22 ++++++------ 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java b/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java index 7c3a1a2df..a7bec6113 100644 --- a/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java +++ b/src/main/java/org/springframework/hateoas/core/AnnotationMappingDiscoverer.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -68,7 +69,7 @@ public String getMapping(Class type) { return getMapping(null, type); } - public String getMapping(Environment environment, Class type) { + public String getMapping(PropertyResolver resolver, Class type) { Assert.notNull(type, "Type must not be null!"); @@ -79,7 +80,7 @@ public String getMapping(Environment environment, Class type) { type.getName())); } - return mapping.length == 0 ? null : maybeResolveValue(environment, mapping[0]); + return mapping.length == 0 ? null : maybeResolveValue(resolver, mapping[0]); } /* @@ -91,9 +92,9 @@ public String getMapping(Method method) { return getMapping(method, null); } - public String getMapping(Method method, Environment environment) { + public String getMapping(Method method, PropertyResolver resolver) { Assert.notNull(method, "Method must not be null!"); - return getMapping(method.getDeclaringClass(), method, environment); + return getMapping(method.getDeclaringClass(), method, resolver); } /* @@ -105,7 +106,7 @@ public String getMapping(Class type, Method method) { return getMapping(type, method, null); } - public String getMapping(Class type, Method method, Environment environment) { + public String getMapping(Class type, Method method, PropertyResolver resolver) { Assert.notNull(type, "Type must not be null!"); Assert.notNull(method, "Method must not be null!"); @@ -124,7 +125,7 @@ public String getMapping(Class type, Method method, Environment environment) } String returnValue = (typeMapping == null || "/".equals(typeMapping) ? mapping[0] : typeMapping + mapping[0]); - return maybeResolveValue(environment, returnValue); + return maybeResolveValue(resolver, returnValue); } private String[] getMappingFrom(Annotation annotation) { @@ -143,9 +144,9 @@ private String[] getMappingFrom(Annotation annotation) { "Unsupported type for the mapping attribute! Support String and String[] but got %s!", value.getClass())); } - private String maybeResolveValue(Environment environment, String value) { - if (environment != null && StringUtils.hasText(value)) { - value = environment.resolvePlaceholders(value); + private String maybeResolveValue(PropertyResolver resolver, String value) { + if (resolver != null && StringUtils.hasText(value)) { + value = resolver.resolvePlaceholders(value); } return value; diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java index be334a638..a6af029b2 100755 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilder.java @@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletRequest; -import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; import org.springframework.hateoas.Link; import org.springframework.hateoas.core.AnnotationMappingDiscoverer; import org.springframework.hateoas.core.DummyInvocationUtils; @@ -78,8 +78,8 @@ public static ControllerLinkBuilder linkTo(Class controller) { * @param controller the class to discover the annotation on, must not be {@literal null}. * @return */ - public static ControllerLinkBuilder linkTo(Environment environment, Class controller) { - return linkTo(environment, controller, new Object[0]); + public static ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller) { + return linkTo(resolver, controller, new Object[0]); } /** @@ -106,12 +106,12 @@ public static ControllerLinkBuilder linkTo(Class controller, Object... parame * @param parameters * @return */ - public static ControllerLinkBuilder linkTo(Environment env, Class controller, Object... parameters) { + public static ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller, Object... parameters) { Assert.notNull(controller); ControllerLinkBuilder builder = new ControllerLinkBuilder(getBuilder()); - String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(env, controller); + String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(resolver, controller); UriComponents uriComponents = UriComponentsBuilder.fromUriString(mapping == null ? "/" : mapping).build(); UriComponents expandedComponents = uriComponents.expand(parameters); @@ -128,17 +128,17 @@ public static ControllerLinkBuilder linkTo(Method method, Object... parameters) /** * Similar to {@link org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...)} - * but takes an optional {@link Environment} parameter. If it is non-null, it will attempt to resolve + * but takes an optional {@link PropertyResolver} parameter. If it is non-null, it will attempt to resolve * any placeholders in requestMappings that were found. * - * @param env + * @param resolver * @param method * @param parameters * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Method, Object...) * @return */ - public static ControllerLinkBuilder linkTo(Environment env, Method method, Object... parameters) { - return linkTo(env, method.getDeclaringClass(), method, parameters); + public static ControllerLinkBuilder linkTo(PropertyResolver resolver, Method method, Object... parameters) { + return linkTo(resolver, method.getDeclaringClass(), method, parameters); } /* @@ -150,22 +150,22 @@ public static ControllerLinkBuilder linkTo(Class controller, Method method, O /** * Similar to {@link org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...)} - * but takes an optional {@link Environment} parameter. If it is non-null, it will attempt to resolve + * but takes an optional {@link PropertyResolver} parameter. If it is non-null, it will attempt to resolve * any placeholders in requestMappings that were found. * - * @param env + * @param resolver * @param controller * @param method * @param parameters * @see org.springframework.hateoas.MethodLinkBuilderFactory#linkTo(Class, Method, Object...) * @return */ - public static ControllerLinkBuilder linkTo(Environment env, Class controller, Method method, Object... parameters) { + public static ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller, Method method, Object... parameters) { Assert.notNull(controller, "Controller type must not be null!"); Assert.notNull(method, "Method must not be null!"); - UriTemplate template = new UriTemplate(((AnnotationMappingDiscoverer)DISCOVERER).getMapping(controller, method, env)); + UriTemplate template = new UriTemplate(((AnnotationMappingDiscoverer)DISCOVERER).getMapping(controller, method, resolver)); URI uri = template.expand(parameters); return new ControllerLinkBuilder(getBuilder()).slash(uri); @@ -212,19 +212,19 @@ public static ControllerLinkBuilder linkTo(Object invocationValue) { * Link link = linkTo(methodOn(CustomerController.class).showAddresses(2L)).withRel("addresses"); * * - * If the {@link Environment} parameter is non-null, it will attempt to resolve any placeholders + * If the {@link PropertyResolver} parameter is non-null, it will attempt to resolve any placeholders * found in the mapping * * The resulting {@link Link} instance will point to {@code /customers/2/addresses} and have a rel of * {@code addresses}. For more details on the method invocation constraints, see * {@link DummyInvocationUtils#methodOn(Class, Object...)}. * - * @param environment + * @param resolver * @param invocationValue * @return */ - public static ControllerLinkBuilder linkTo(Environment environment, Object invocationValue) { - return FACTORY.linkTo(environment, invocationValue); + public static ControllerLinkBuilder linkTo(PropertyResolver resolver, Object invocationValue) { + return FACTORY.linkTo(resolver, invocationValue); } /** diff --git a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java index 7f8db77f5..0e2ac5110 100644 --- a/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java +++ b/src/main/java/org/springframework/hateoas/mvc/ControllerLinkBuilderFactory.java @@ -26,7 +26,7 @@ import java.util.Map; import org.springframework.core.MethodParameter; -import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; import org.springframework.hateoas.Link; import org.springframework.hateoas.MethodLinkBuilderFactory; import org.springframework.hateoas.core.AnnotationAttribute; @@ -86,8 +86,8 @@ public ControllerLinkBuilder linkTo(Class controller) { return ControllerLinkBuilder.linkTo(controller); } - public ControllerLinkBuilder linkTo(Environment env, Class controller) { - return ControllerLinkBuilder.linkTo(env, controller); + public ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller) { + return ControllerLinkBuilder.linkTo(resolver, controller); } /* @@ -99,8 +99,8 @@ public ControllerLinkBuilder linkTo(Class controller, Object... parameters) { return ControllerLinkBuilder.linkTo(controller, parameters); } - public ControllerLinkBuilder linkTo(Environment env, Class controller, Object... parameters) { - return ControllerLinkBuilder.linkTo(env, controller, parameters); + public ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller, Object... parameters) { + return ControllerLinkBuilder.linkTo(resolver, controller, parameters); } /* @@ -112,8 +112,8 @@ public ControllerLinkBuilder linkTo(Class controller, Method method, Object.. return ControllerLinkBuilder.linkTo(controller, method, parameters); } - public ControllerLinkBuilder linkTo(Environment env, Class controller, Method method, Object... parameters) { - return ControllerLinkBuilder.linkTo(env, controller, method, parameters); + public ControllerLinkBuilder linkTo(PropertyResolver resolver, Class controller, Method method, Object... parameters) { + return ControllerLinkBuilder.linkTo(resolver, controller, method, parameters); } /* @@ -125,7 +125,7 @@ public ControllerLinkBuilder linkTo(Object invocationValue) { return linkTo(null, invocationValue); } - public ControllerLinkBuilder linkTo(Environment env, Object invocationValue) { + public ControllerLinkBuilder linkTo(PropertyResolver resolver, Object invocationValue) { Assert.isInstanceOf(LastInvocationAware.class, invocationValue); LastInvocationAware invocations = (LastInvocationAware) invocationValue; @@ -134,7 +134,7 @@ public ControllerLinkBuilder linkTo(Environment env, Object invocationValue) { Iterator classMappingParameters = invocations.getObjectParameters(); Method method = invocation.getMethod(); - String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(invocation.getTargetType(), method, env); + String mapping = ((AnnotationMappingDiscoverer)DISCOVERER).getMapping(invocation.getTargetType(), method, resolver); UriComponentsBuilder builder = ControllerLinkBuilder.getBuilder().path(mapping); UriTemplate template = new UriTemplate(mapping); @@ -166,8 +166,8 @@ public ControllerLinkBuilder linkTo(Method method, Object... parameters) { return ControllerLinkBuilder.linkTo(method, parameters); } - public ControllerLinkBuilder linkTo(Environment env, Method method, Object... parameters) { - return ControllerLinkBuilder.linkTo(env, method, parameters); + public ControllerLinkBuilder linkTo(PropertyResolver resolver, Method method, Object... parameters) { + return ControllerLinkBuilder.linkTo(resolver, method, parameters); } /**