DATAREST-268, DATAREST-267 - Controllers now ignore URI template variables submitted.
When parsing the id value from a URI we now pipe the obtained segment through Spring HATEOAS' UriTemplate to potentially remove optional tempalte variables. These variables might make it into the URI by clients that do not properly expanding URI templates before submitting requests. This is effectively a backport of parts of the fix for DATAREST-155 in master.
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.data.rest.webmvc;
|
||||
import static org.springframework.data.rest.core.support.DomainObjectMerger.NullHandlingPolicy.*;
|
||||
import static org.springframework.http.HttpMethod.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||
import org.springframework.data.rest.core.mapping.SearchResourceMappings;
|
||||
import org.springframework.data.rest.core.support.DomainObjectMerger;
|
||||
import org.springframework.data.rest.core.support.DomainObjectMerger.NullHandlingPolicy;
|
||||
import org.springframework.data.rest.webmvc.support.BackendId;
|
||||
import org.springframework.data.web.PagedResourcesAssembler;
|
||||
import org.springframework.hateoas.EntityLinks;
|
||||
import org.springframework.hateoas.Link;
|
||||
@@ -56,7 +58,6 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -187,7 +188,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
*/
|
||||
@RequestMapping(value = BASE_MAPPING + "/{id}", method = RequestMethod.GET)
|
||||
public ResponseEntity<Resource<?>> getSingleEntity(RootResourceInformation resourceInformation,
|
||||
@PathVariable String id) throws HttpRequestMethodNotSupportedException {
|
||||
@BackendId Serializable id) throws HttpRequestMethodNotSupportedException {
|
||||
|
||||
resourceInformation.verifySupportedMethod(HttpMethod.GET, ResourceType.ITEM);
|
||||
|
||||
@@ -217,7 +218,8 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
*/
|
||||
@RequestMapping(value = BASE_MAPPING + "/{id}", method = RequestMethod.PUT)
|
||||
public ResponseEntity<? extends ResourceSupport> putEntity(RootResourceInformation resourceInformation,
|
||||
PersistentEntityResource<Object> payload, @PathVariable String id) throws HttpRequestMethodNotSupportedException {
|
||||
PersistentEntityResource<Object> payload, @BackendId Serializable id)
|
||||
throws HttpRequestMethodNotSupportedException {
|
||||
|
||||
resourceInformation.verifySupportedMethod(HttpMethod.PUT, ResourceType.ITEM);
|
||||
|
||||
@@ -247,8 +249,8 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
*/
|
||||
@RequestMapping(value = BASE_MAPPING + "/{id}", method = RequestMethod.PATCH)
|
||||
public ResponseEntity<ResourceSupport> patchEntity(RootResourceInformation resourceInformation,
|
||||
PersistentEntityResource<Object> payload, @PathVariable String id) throws HttpRequestMethodNotSupportedException,
|
||||
ResourceNotFoundException {
|
||||
PersistentEntityResource<Object> payload, @BackendId Serializable id)
|
||||
throws HttpRequestMethodNotSupportedException, ResourceNotFoundException {
|
||||
|
||||
resourceInformation.verifySupportedMethod(HttpMethod.PATCH, ResourceType.ITEM);
|
||||
|
||||
@@ -271,7 +273,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
* @throws HttpRequestMethodNotSupportedException
|
||||
*/
|
||||
@RequestMapping(value = BASE_MAPPING + "/{id}", method = RequestMethod.DELETE)
|
||||
public ResponseEntity<?> deleteEntity(final RootResourceInformation resourceInformation, @PathVariable final String id)
|
||||
public ResponseEntity<?> deleteEntity(final RootResourceInformation resourceInformation, @BackendId Serializable id)
|
||||
throws ResourceNotFoundException, HttpRequestMethodNotSupportedException {
|
||||
|
||||
resourceInformation.verifySupportedMethod(HttpMethod.DELETE, ResourceType.ITEM);
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.rest.webmvc;
|
||||
import static org.springframework.data.rest.webmvc.ControllerUtils.*;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.data.rest.core.invoke.RepositoryInvoker;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMapping;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||
import org.springframework.data.rest.core.util.Function;
|
||||
import org.springframework.data.rest.webmvc.support.BackendId;
|
||||
import org.springframework.data.web.PagedResourcesAssembler;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
@@ -102,7 +104,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
|
||||
@RequestMapping(value = BASE_MAPPING, method = RequestMethod.GET)
|
||||
public ResponseEntity<ResourceSupport> followPropertyReference(final RootResourceInformation repoRequest,
|
||||
@PathVariable String id, @PathVariable String property) throws Exception {
|
||||
@BackendId Serializable id, @PathVariable String property) throws Exception {
|
||||
|
||||
final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
@@ -150,7 +152,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
|
||||
@RequestMapping(value = BASE_MAPPING, method = RequestMethod.DELETE)
|
||||
public ResponseEntity<? extends ResourceSupport> deletePropertyReference(final RootResourceInformation repoRequest,
|
||||
@PathVariable String id, @PathVariable String property) throws Exception {
|
||||
@BackendId Serializable id, @PathVariable String property) throws Exception {
|
||||
|
||||
final RepositoryInvoker repoMethodInvoker = repoRequest.getInvoker();
|
||||
|
||||
@@ -190,7 +192,8 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
|
||||
@RequestMapping(value = BASE_MAPPING + "/{propertyId}", method = RequestMethod.GET)
|
||||
public ResponseEntity<ResourceSupport> followPropertyReference(final RootResourceInformation repoRequest,
|
||||
@PathVariable String id, @PathVariable String property, final @PathVariable String propertyId) throws Exception {
|
||||
@BackendId Serializable id, @PathVariable String property, final @PathVariable String propertyId)
|
||||
throws Exception {
|
||||
|
||||
final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
@@ -242,7 +245,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
@RequestMapping(value = BASE_MAPPING, method = RequestMethod.GET, produces = {
|
||||
"application/x-spring-data-compact+json", "text/uri-list" })
|
||||
public ResponseEntity<ResourceSupport> followPropertyReferenceCompact(RootResourceInformation repoRequest,
|
||||
@PathVariable String id, @PathVariable String property) throws Exception {
|
||||
@BackendId Serializable id, @PathVariable String property) throws Exception {
|
||||
|
||||
ResponseEntity<ResourceSupport> response = followPropertyReference(repoRequest, id, property);
|
||||
|
||||
@@ -293,7 +296,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
@ResponseBody
|
||||
public ResponseEntity<? extends ResourceSupport> createPropertyReference(
|
||||
final RootResourceInformation resourceInformation, final HttpMethod requestMethod,
|
||||
final @RequestBody Resources<Object> incoming, @PathVariable String id, @PathVariable String property)
|
||||
final @RequestBody Resources<Object> incoming, @BackendId Serializable id, @PathVariable String property)
|
||||
throws Exception {
|
||||
|
||||
final RepositoryInvoker invoker = resourceInformation.getInvoker();
|
||||
@@ -371,7 +374,8 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
@RequestMapping(value = BASE_MAPPING + "/{propertyId}", method = RequestMethod.DELETE)
|
||||
@ResponseBody
|
||||
public ResponseEntity<ResourceSupport> deletePropertyReferenceId(final RootResourceInformation repoRequest,
|
||||
@PathVariable String id, @PathVariable String property, final @PathVariable String propertyId) throws Exception {
|
||||
@BackendId Serializable id, @PathVariable String property, final @PathVariable String propertyId)
|
||||
throws Exception {
|
||||
|
||||
final RepositoryInvoker invoker = repoRequest.getInvoker();
|
||||
|
||||
@@ -433,8 +437,8 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro
|
||||
return conversionService.convert(id, type);
|
||||
}
|
||||
|
||||
private ResourceSupport doWithReferencedProperty(RootResourceInformation repoRequest, String id, String propertyPath,
|
||||
Function<ReferencedProperty, ResourceSupport> handler, HttpMethod method) throws Exception {
|
||||
private ResourceSupport doWithReferencedProperty(RootResourceInformation repoRequest, Serializable id,
|
||||
String propertyPath, Function<ReferencedProperty, ResourceSupport> handler, HttpMethod method) throws Exception {
|
||||
|
||||
RepositoryInvoker invoker = repoRequest.getInvoker();
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter;
|
||||
import org.springframework.data.rest.webmvc.json.Jackson2DatatypeHelper;
|
||||
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module;
|
||||
import org.springframework.data.rest.webmvc.json.PersistentEntityToJsonSchemaConverter;
|
||||
import org.springframework.data.rest.webmvc.support.BackendIdHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.rest.webmvc.support.HttpMethodHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.rest.webmvc.support.JpaHelper;
|
||||
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
|
||||
@@ -247,6 +248,11 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
return new ResourceMetadataHandlerMethodArgumentResolver(repositories(), resourceMappings());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BackendIdHandlerMethodArgumentResolver backendIdHandlerMethodArgumentResolver() {
|
||||
return new BackendIdHandlerMethodArgumentResolver(resourceMetadataHandlerMethodArgumentResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* A special {@link org.springframework.hateoas.EntityLinks} implementation that takes repository and current
|
||||
* configuration into account when generating links.
|
||||
@@ -481,7 +487,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
private List<HandlerMethodArgumentResolver> defaultMethodArgumentResolvers() {
|
||||
return Arrays.asList(pageableResolver(), sortResolver(), serverHttpRequestMethodArgumentResolver(),
|
||||
repoRequestArgumentResolver(), persistentEntityArgumentResolver(),
|
||||
resourceMetadataHandlerMethodArgumentResolver(), HttpMethodHandlerMethodArgumentResolver.INSTANCE);
|
||||
resourceMetadataHandlerMethodArgumentResolver(), HttpMethodHandlerMethodArgumentResolver.INSTANCE,
|
||||
backendIdHandlerMethodArgumentResolver());
|
||||
}
|
||||
|
||||
private ObjectMapper basicObjectMapper() {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2014 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.data.rest.webmvc.support;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to bind the backend id of an entity.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface BackendId {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2014 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.data.rest.webmvc.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||
import org.springframework.data.rest.webmvc.ResourceMetadataHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.rest.webmvc.util.UriUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* {@link HandlerMethodArgumentResolver} to resolve entity ids for injection int handler method arguments annotated with
|
||||
* {@link BackendId}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class BackendIdHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final ResourceMetadataHandlerMethodArgumentResolver resourceMetadataResolver;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BackendIdHandlerMethodArgumentResolver} for the given {@link BackendIdConverter}s and
|
||||
* {@link ResourceMetadataHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @param resourceMetadataResolver the resolver to obtain {@link ResourceMetadata} from.
|
||||
*/
|
||||
public BackendIdHandlerMethodArgumentResolver(ResourceMetadataHandlerMethodArgumentResolver resourceMetadataResolver) {
|
||||
|
||||
Assert.notNull(resourceMetadataResolver, "ResourceMetadata resolver must not be null!");
|
||||
|
||||
this.resourceMetadataResolver = resourceMetadataResolver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(BackendId.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
|
||||
*/
|
||||
@Override
|
||||
public String resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
Class<?> parameterType = parameter.getParameterType();
|
||||
|
||||
if (!parameterType.equals(Serializable.class)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Method parameter for @%s must be of type %s! Got %s for method %s.", BackendId.class.getSimpleName(),
|
||||
Serializable.class.getSimpleName(), parameterType.getSimpleName(), parameter.getMethod()));
|
||||
}
|
||||
|
||||
ResourceMetadata metadata = resourceMetadataResolver.resolveArgument(parameter, mavContainer, request,
|
||||
binderFactory);
|
||||
|
||||
if (metadata == null) {
|
||||
throw new IllegalArgumentException("Could not obtain ResourceMetadata for request " + request);
|
||||
}
|
||||
|
||||
return UriUtils.findMappingVariable("id", parameter, request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2014 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.data.rest.webmvc.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.hateoas.UriTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* Utility methods to work with requests and URIs.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class UriUtils {
|
||||
|
||||
private static final UrlPathHelper URL_PATH_HELPER = new UrlPathHelper();
|
||||
|
||||
private UriUtils() {}
|
||||
|
||||
/**
|
||||
* Returns the value for the mapping variable with the given name.
|
||||
*
|
||||
* @param variable must not be {@literal null} or empty.
|
||||
* @param parameter
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String findMappingVariable(String variable, MethodParameter parameter, NativeWebRequest request) {
|
||||
|
||||
Assert.hasText(variable, "Variable name must not be null or empty!");
|
||||
Assert.notNull(parameter, "Method parameter must not be null!");
|
||||
Assert.notNull(request, "Request must not be null!");
|
||||
|
||||
String lookupPath = getCleanLookupPath(request);
|
||||
RequestMapping annotation = parameter.getMethodAnnotation(RequestMapping.class);
|
||||
|
||||
for (String mapping : annotation.value()) {
|
||||
|
||||
Map<String, String> variables = new org.springframework.web.util.UriTemplate(mapping).match(lookupPath);
|
||||
String value = variables.get(variable);
|
||||
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getCleanLookupPath(NativeWebRequest request) {
|
||||
|
||||
HttpServletRequest httpServletRequest = request.getNativeRequest(HttpServletRequest.class);
|
||||
String lookupPath = URL_PATH_HELPER.getLookupPathForRequest(httpServletRequest);
|
||||
return new UriTemplate(lookupPath).expand().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2014 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.data.rest.webmvc.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.rest.webmvc.AbstractControllerIntegrationTests;
|
||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link BackendIdHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
public class BackendIdConverterHandlerMethodArgumentResolverIntegrationTests extends AbstractControllerIntegrationTests {
|
||||
|
||||
@Autowired BackendIdHandlerMethodArgumentResolver resolver;
|
||||
|
||||
/**
|
||||
* @see DATAREST-267, DATAREST-268
|
||||
*/
|
||||
@Test
|
||||
public void stripsUriTemplateVariablesFromUri() throws Exception {
|
||||
|
||||
Method method = ReflectionUtils.findMethod(SampleController.class, "resolveId", Serializable.class);
|
||||
MethodParameter parameter = new MethodParameter(method, 0);
|
||||
NativeWebRequest request = new ServletWebRequest(new MockHttpServletRequest("GET", "/books/5{?projection}"));
|
||||
|
||||
Object resolvedId = resolver.resolveArgument(parameter, null, request, null);
|
||||
|
||||
assertThat(resolvedId, is((Object) "5"));
|
||||
}
|
||||
|
||||
static class SampleController {
|
||||
|
||||
@RequestMapping("/{repository}/{id}")
|
||||
void resolveId(@BackendId Serializable backendId) {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user