DATAREST-292 - Fixed application of configured base URI.
Major overhaul of mapping detection in RepositoryRestHandlerMapping. We now correctly map URIs if a base URI is configured via RepositoryRestConfiguration. Additional tweaks needed for the back-port.
This commit is contained in:
@@ -31,7 +31,7 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("deprecation")
|
||||
public class RepositoryRestConfiguration {
|
||||
|
||||
private URI baseUri = null;
|
||||
private URI baseUri = URI.create("");
|
||||
private int defaultPageSize = 20;
|
||||
private int maxPageSize = 1000;
|
||||
private String pageParamName = "page";
|
||||
|
||||
@@ -31,8 +31,11 @@ import org.springframework.data.rest.webmvc.support.JpaHelper;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* {@link RequestMappingHandlerMapping} implementation that will only find a handler method if a
|
||||
@@ -111,24 +114,28 @@ public class RepositoryRestHandlerMapping extends RequestMappingHandlerMapping {
|
||||
|
||||
HttpServletRequest request = new DefaultAcceptTypeHttpServletRequest(origRequest, acceptType);
|
||||
|
||||
String requestUri = lookupPath;
|
||||
if (requestUri.startsWith("/")) {
|
||||
requestUri = requestUri.substring(1);
|
||||
}
|
||||
|
||||
if (!hasText(requestUri)) {
|
||||
if (!hasText(lookupPath)) {
|
||||
return super.lookupHandlerMethod(lookupPath, request);
|
||||
}
|
||||
|
||||
String[] parts = requestUri.split("/");
|
||||
// Strip base URI
|
||||
UriComponents components = UriComponentsBuilder.fromPath(lookupPath).build();
|
||||
List<String> segments = components.getPathSegments();
|
||||
String baseUri = config.getBaseUri().toString();
|
||||
int repositoryIndex = !segments.isEmpty() && segments.get(0).equals(baseUri) ? 1 : 0;
|
||||
segments = segments.subList(repositoryIndex, segments.size());
|
||||
|
||||
if (parts.length == 0) {
|
||||
// Root request
|
||||
return super.lookupHandlerMethod(lookupPath, request);
|
||||
String uri = "/".concat(StringUtils.collectionToDelimitedString(segments, "/"));
|
||||
|
||||
request = new DefaultAcceptTypeHttpServletRequest(origRequest, acceptType, uri);
|
||||
|
||||
// Root request
|
||||
if (uri.equals("/")) {
|
||||
return super.lookupHandlerMethod(uri, request);
|
||||
}
|
||||
|
||||
if (mappings.exportsTopLevelResourceFor(parts[0])) {
|
||||
return super.lookupHandlerMethod(lookupPath, request);
|
||||
if (mappings.exportsTopLevelResourceFor(segments.get(0))) {
|
||||
return super.lookupHandlerMethod(uri, request);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -159,10 +166,16 @@ public class RepositoryRestHandlerMapping extends RequestMappingHandlerMapping {
|
||||
private static class DefaultAcceptTypeHttpServletRequest extends HttpServletRequestWrapper {
|
||||
|
||||
private final String defaultAcceptType;
|
||||
private final String requestUri;
|
||||
|
||||
private DefaultAcceptTypeHttpServletRequest(HttpServletRequest request, String defaultAcceptType) {
|
||||
this(request, defaultAcceptType, null);
|
||||
}
|
||||
|
||||
private DefaultAcceptTypeHttpServletRequest(HttpServletRequest request, String defaultAcceptType, String requestUri) {
|
||||
super(request);
|
||||
this.defaultAcceptType = defaultAcceptType;
|
||||
this.requestUri = requestUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,5 +187,14 @@ public class RepositoryRestHandlerMapping extends RequestMappingHandlerMapping {
|
||||
return super.getHeader(name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.servlet.http.HttpServletRequestWrapper#getRequestURI()
|
||||
*/
|
||||
@Override
|
||||
public String getRequestURI() {
|
||||
return requestUri != null ? requestUri : super.getRequestURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
*/
|
||||
@Bean
|
||||
public PersistentEntityToJsonSchemaConverter jsonSchemaConverter() {
|
||||
return new PersistentEntityToJsonSchemaConverter(repositories(), resourceMappings(),
|
||||
return new PersistentEntityToJsonSchemaConverter(repositories(), resourceMappings(), config(),
|
||||
resourceDescriptionMessageSourceAccessor());
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.SimpleAssociationHandler;
|
||||
import org.springframework.data.mapping.SimplePropertyHandler;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.core.mapping.ResourceDescription;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMapping;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMappings;
|
||||
@@ -55,6 +56,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
private final ResourceMappings mappings;
|
||||
private final Repositories repositories;
|
||||
private final MessageSourceAccessor accessor;
|
||||
private final RepositoryRestConfiguration config;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PersistentEntityToJsonSchemaConverter} for the given {@link Repositories} and
|
||||
@@ -65,13 +67,16 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
* @param accessor
|
||||
*/
|
||||
public PersistentEntityToJsonSchemaConverter(Repositories repositories, ResourceMappings mappings,
|
||||
MessageSourceAccessor accessor) {
|
||||
RepositoryRestConfiguration config, MessageSourceAccessor accessor) {
|
||||
|
||||
Assert.notNull(repositories, "Repositories must not be null!");
|
||||
Assert.notNull(mappings, "ResourceMappings must not be null!");
|
||||
Assert.notNull(config, "RepositoryRestConfiguration must not be null!");
|
||||
|
||||
this.repositories = repositories;
|
||||
this.mappings = mappings;
|
||||
this.config = config;
|
||||
|
||||
this.accessor = accessor;
|
||||
|
||||
for (Class<?> domainType : repositories) {
|
||||
@@ -155,7 +160,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
|
||||
return;
|
||||
}
|
||||
|
||||
RepositoryLinkBuilder builder = new RepositoryLinkBuilder(metadata, null).slash("{id}");
|
||||
RepositoryLinkBuilder builder = new RepositoryLinkBuilder(metadata, config.getBaseUri()).slash("{id}");
|
||||
maybeAddAssociationLink(builder, mappings, persistentProperty, links);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -19,10 +19,9 @@ import java.net.URI;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||
import org.springframework.data.rest.webmvc.RepositoryController;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.core.LinkBuilderSupport;
|
||||
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
public class RepositoryLinkBuilder extends LinkBuilderSupport<RepositoryLinkBuilder> {
|
||||
@@ -41,8 +40,12 @@ public class RepositoryLinkBuilder extends LinkBuilderSupport<RepositoryLinkBuil
|
||||
|
||||
private static UriComponentsBuilder prepareBuilder(URI baseUri, ResourceMetadata metadata) {
|
||||
|
||||
UriComponentsBuilder builder = baseUri != null ? UriComponentsBuilder.fromUri(baseUri) : ControllerLinkBuilder
|
||||
.linkTo(RepositoryController.class).toUriComponentsBuilder();
|
||||
UriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentServletMapping();
|
||||
|
||||
if (baseUri != null) {
|
||||
builder = builder.path(baseUri.toString());
|
||||
}
|
||||
|
||||
return builder.path(metadata.getPath().toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -51,7 +52,7 @@ public class RepositoryRestHandlerMappingUnitTests {
|
||||
RepositoryRestConfiguration configuration;
|
||||
RepositoryRestHandlerMapping handlerMapping;
|
||||
MockHttpServletRequest mockRequest;
|
||||
Method listEntitiesMethod;
|
||||
Method listEntitiesMethod, rootHandlerMethod;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -66,6 +67,7 @@ public class RepositoryRestHandlerMappingUnitTests {
|
||||
|
||||
listEntitiesMethod = RepositoryEntityController.class.getMethod("listEntities", RootResourceInformation.class,
|
||||
Pageable.class, Sort.class);
|
||||
rootHandlerMethod = RepositoryController.class.getMethod("listRepositories");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -100,4 +102,38 @@ public class RepositoryRestHandlerMappingUnitTests {
|
||||
assertThat(method, is(notNullValue()));
|
||||
assertThat(method.getMethod(), is(listEntitiesMethod));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-292
|
||||
*/
|
||||
@Test
|
||||
public void returnsRepositoryHandlerMethodWithBaseUriConfigured() throws Exception {
|
||||
|
||||
when(mappings.exportsTopLevelResourceFor("people")).thenReturn(true);
|
||||
mockRequest = new MockHttpServletRequest("GET", "/base/people");
|
||||
|
||||
configuration.setBaseUri(URI.create("base"));
|
||||
|
||||
HandlerMethod method = handlerMapping.lookupHandlerMethod("/base/people", mockRequest);
|
||||
|
||||
assertThat(method, is(notNullValue()));
|
||||
assertThat(method.getMethod(), is(listEntitiesMethod));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-292
|
||||
*/
|
||||
@Test
|
||||
public void returnsRootHandlerMethodWithBaseUriConfigured() throws Exception {
|
||||
|
||||
when(mappings.exportsTopLevelResourceFor("people")).thenReturn(true);
|
||||
mockRequest = new MockHttpServletRequest("GET", "/base");
|
||||
|
||||
configuration.setBaseUri(URI.create("base"));
|
||||
|
||||
HandlerMethod method = handlerMapping.lookupHandlerMethod("/base", mockRequest);
|
||||
|
||||
assertThat(method, is(notNullValue()));
|
||||
assertThat(method.getMethod(), is(rootHandlerMethod));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.rest.webmvc.PersistentEntityResource;
|
||||
import org.springframework.data.rest.webmvc.WebTestUtils;
|
||||
import org.springframework.data.rest.webmvc.jpa.LineItem;
|
||||
import org.springframework.data.rest.webmvc.jpa.Order;
|
||||
import org.springframework.data.rest.webmvc.jpa.OrderRepository;
|
||||
@@ -74,6 +75,7 @@ public class PersistentEntitySerializationTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
WebTestUtils.initWebTest();
|
||||
linkDiscoverer = new HalLinkDiscoverer();
|
||||
}
|
||||
|
||||
@@ -212,7 +214,7 @@ public class PersistentEntitySerializationTests {
|
||||
|
||||
assertThat(mapper.writeValueAsString(persistentEntityResource),
|
||||
is("{\"_embedded\":{\"orders\":[{\"lineItems\":[{\"name\":\"first\"},{\"name\":\"second\"}],\"price\":2.5"
|
||||
+ ",\"_links\":{\"creator\":{\"href\":\"http://localhost:8080/orders/1/creator\"}}}]},\""
|
||||
+ ",\"_links\":{\"creator\":{\"href\":\"http://localhost/orders/1/creator\"}}}]},\""
|
||||
+ "page\":{\"size\":1,\"totalElements\":10,\"totalPages\":10,\"number\":0}}"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.json;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -72,8 +70,6 @@ public class RepositoryTestsConfig {
|
||||
config.setResourceMappingForRepository(PersonRepository.class).setRel("people").setPath("people")
|
||||
.addResourceMappingFor("findByFirstName").setRel("firstname").setPath("firstname");
|
||||
|
||||
config.setBaseUri(URI.create("http://localhost:8080"));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user