BridgeMethodResolver properly resolves all declared interfaces
Issue: SPR-16288
This commit is contained in:
parent
ea73ec5c41
commit
121f9e3734
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
|
|
@ -196,7 +196,10 @@ public abstract class BridgeMethodResolver {
|
|||
return method;
|
||||
}
|
||||
else {
|
||||
return searchInterfaces(ifc.getInterfaces(), bridgeMethod);
|
||||
method = searchInterfaces(ifc.getInterfaces(), bridgeMethod);
|
||||
if (method != null) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
|
|
@ -31,8 +31,10 @@ import java.net.URISyntaxException;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Principal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
|
@ -44,6 +46,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
|
@ -1224,13 +1227,22 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
getServlet().service(request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bridgeMethodsWithMultipleInterfaces() throws Exception {
|
||||
initServletWithControllers(ArticleController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/method");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParamMap() throws Exception {
|
||||
initServletWithControllers(RequestParamMapController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/map");
|
||||
request.addParameter("key1", "value1");
|
||||
request.addParameter("key2", new String[]{"value21", "value22"});
|
||||
request.addParameter("key2", new String[] {"value21", "value22"});
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
getServlet().service(request, response);
|
||||
|
|
@ -1249,7 +1261,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/map");
|
||||
request.addHeader("Content-Type", "text/html");
|
||||
request.addHeader("Custom-Header", new String[]{"value21", "value22"});
|
||||
request.addHeader("Custom-Header", new String[] {"value21", "value22"});
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
getServlet().service(request, response);
|
||||
|
|
@ -2591,7 +2603,6 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "deprecation", "rawtypes"})
|
||||
public void render(@Nullable Map model, HttpServletRequest request, HttpServletResponse response)
|
||||
|
|
@ -3106,6 +3117,78 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(path = ApiConstants.ARTICLES_PATH)
|
||||
public static class ArticleController implements ApiConstants, ResourceEndpoint<Article, ArticlePredicate> {
|
||||
|
||||
@GetMapping(params = "page")
|
||||
public Collection<Article> find(String pageable, ArticlePredicate predicate) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Article> find(boolean sort, ArticlePredicate predicate) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
interface ApiConstants {
|
||||
|
||||
String API_V1 = "/v1";
|
||||
|
||||
String ARTICLES_PATH = API_V1 + "/articles";
|
||||
}
|
||||
|
||||
public interface ResourceEndpoint<E extends Entity, P extends EntityPredicate> {
|
||||
|
||||
Collection<E> find(String pageable, P predicate) throws IOException;
|
||||
|
||||
List<E> find(boolean sort, P predicate) throws IOException;
|
||||
}
|
||||
|
||||
public static abstract class Entity {
|
||||
|
||||
public UUID id;
|
||||
|
||||
public String createdBy;
|
||||
|
||||
public Instant createdDate;
|
||||
}
|
||||
|
||||
public static class Article extends Entity {
|
||||
|
||||
public String slug;
|
||||
|
||||
public String title;
|
||||
|
||||
public String content;
|
||||
}
|
||||
|
||||
public static abstract class EntityPredicate<E extends Entity> {
|
||||
|
||||
public String createdBy;
|
||||
|
||||
public Instant createdBefore;
|
||||
|
||||
public Instant createdAfter;
|
||||
|
||||
public boolean accept(E entity) {
|
||||
return (createdBy == null || createdBy.equals(entity.createdBy)) &&
|
||||
(createdBefore == null || createdBefore.compareTo(entity.createdDate) >= 0) &&
|
||||
(createdAfter == null || createdAfter.compareTo(entity.createdDate) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArticlePredicate extends EntityPredicate<Article> {
|
||||
|
||||
public String query;
|
||||
|
||||
@Override
|
||||
public boolean accept(Article entity) {
|
||||
return super.accept(entity) && (query == null || (entity.title.contains(query) || entity.content.contains(query)));
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class RequestParamMapController {
|
||||
|
||||
|
|
@ -3277,7 +3360,6 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
|
||||
private String name;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
@ -3325,16 +3407,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
}
|
||||
|
||||
@RequestMapping("/singleString")
|
||||
public void processMultipart(@RequestParam("content") String content,
|
||||
HttpServletResponse response) throws IOException {
|
||||
|
||||
public void processMultipart(@RequestParam("content") String content, HttpServletResponse response)
|
||||
throws IOException {
|
||||
response.getWriter().write(content);
|
||||
}
|
||||
|
||||
@RequestMapping("/stringArray")
|
||||
public void processMultipart(@RequestParam("content") String[] content,
|
||||
HttpServletResponse response) throws IOException {
|
||||
|
||||
public void processMultipart(@RequestParam("content") String[] content, HttpServletResponse response)
|
||||
throws IOException {
|
||||
response.getWriter().write(StringUtils.arrayToDelimitedString(content, "-"));
|
||||
}
|
||||
}
|
||||
|
|
@ -3458,7 +3538,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
|||
|
||||
@RequestMapping(value = "empty", method = RequestMethod.POST)
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public HttpHeaders createNoHeader() throws URISyntaxException {
|
||||
public HttpHeaders createNoHeader() {
|
||||
return new HttpHeaders();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue