Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ static class BooksHtmlController {
void someMethod(@PathVariable String id) {}
}

@RepositoryRestController
@RepositoryRestController(path = {"orders", "orders/v2"})
static class OrdersJsonController {

@RequestMapping(value = "/orders/search/sort", method = RequestMethod.POST, produces = "application/hal+json")
@RequestMapping(value = {"/search/sort","/search/sorted"}, method = RequestMethod.POST, produces = "application/hal+json")
void someMethodWithArgs(Sort sort, Pageable pageable, DefaultedPageable defaultedPageable) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,13 @@ void exectuesCustomQuerySearchThatTakesAMappedSortProperty() throws Exception {
andExpect(client.hasLinkWithRel(IanaLinkRelations.SELF));
}

@Test // DATAREST-910
@Test // DATAREST-910 DATAREST-2088
void callUnmappedCustomRepositoryController() throws Exception {

mvc.perform(post("/orders/v3/search/sort")).andExpect(status().isNotFound());
mvc.perform(post("/orders/search/sort")).andExpect(status().isOk());
mvc.perform(post("/orders/search/sorted")).andExpect(status().isOk());
mvc.perform(post("/orders/v2/search/sort")).andExpect(status().isOk());
mvc.perform(post("/orders/v2/search/sorted")).andExpect(status().isOk());
mvc.perform(post("/orders/search/sort?sort=type&page=1&size=10")).andExpect(status().isOk());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

/**
Expand All @@ -34,4 +35,9 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
public @interface BasePathAwareController {
@AliasFor("path")
String[] value() default {};

@AliasFor("value")
String[] path() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
Expand All @@ -41,6 +38,8 @@
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import static org.springframework.core.annotation.AnnotatedElementUtils.*;

/**
* A {@link RequestMappingHandlerMapping} that augments the request mappings
*
Expand All @@ -51,6 +50,8 @@ public class BasePathAwareHandlerMapping extends RequestMappingHandlerMapping {
private static final String AT_REQUEST_MAPPING_ON_TYPE = "Spring Data REST controller %s must not use @RequestMapping on class level as this would cause double registration with Spring MVC!";
private final RepositoryRestConfiguration configuration;

private final String baseUri;

/**
* Creates a new {@link BasePathAwareHandlerMapping} using the given {@link RepositoryRestConfiguration}.
*
Expand All @@ -61,16 +62,7 @@ public BasePathAwareHandlerMapping(RepositoryRestConfiguration configuration) {
Assert.notNull(configuration, "RepositoryRestConfiguration must not be null!");

this.configuration = configuration;

String baseUri = configuration.getBasePath().toString();

if (StringUtils.hasText(baseUri)) {

Map<String, Predicate<Class<?>>> prefixes = new HashMap<>();
prefixes.put(baseUri, it -> true);

this.setPathPrefixes(prefixes);
}
this.baseUri = configuration.getBasePath().toString();
}

/*
Expand Down Expand Up @@ -128,11 +120,24 @@ protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handler
ProducesRequestCondition producesCondition = customize(info.getProducesCondition());
Set<MediaType> mediaTypes = producesCondition.getProducibleMediaTypes();

BasePathAwareController mergedAnnotation = findMergedAnnotation(handlerType, BasePathAwareController.class);
if (mergedAnnotation != null) {
info = appendPathPrefix(info, mergedAnnotation.value());
}
info = appendPathPrefix(info, new String[]{this.baseUri});
return info.mutate()
.produces(mediaTypes.stream().map(MediaType::toString).toArray(String[]::new))
.build();
}

private RequestMappingInfo appendPathPrefix(RequestMappingInfo info, String[] pathPrefix) {
if (pathPrefix.length > 0) {
String[] paths = this.resolveEmbeddedValuesInPatterns(pathPrefix);
return info.mutate().paths(paths).build().combine(info);
}
return info;
}

/**
* Customize the given {@link ProducesRequestCondition}. Default implementation returns the condition as is.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerMapping;
Expand All @@ -46,4 +47,9 @@
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@BasePathAwareController
public @interface RepositoryRestController {
@AliasFor("path")
String[] value() default {};

@AliasFor("value")
String[] path() default {};
}