From 17d5b31af3d81d664d556ba90c1d1753d5821b10 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 14 Oct 2009 12:24:04 +0000 Subject: [PATCH] SPR-6206 - When looking up methods with @RequestMapping annotation, unannotated bridge methods are included --- .../CgLibProxyServletAnnotationTests.java | 131 ++++++++++++++++++ .../ServletAnnotationControllerTests.java | 29 ++++ .../support/HandlerMethodResolver.java | 4 +- 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/CgLibProxyServletAnnotationTests.java diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/CgLibProxyServletAnnotationTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/CgLibProxyServletAnnotationTests.java new file mode 100644 index 0000000000..1fddd934d0 --- /dev/null +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/CgLibProxyServletAnnotationTests.java @@ -0,0 +1,131 @@ +/* + * Copyright 2002-2009 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.web.servlet.mvc.annotation; + +import java.io.IOException; +import java.io.Writer; +import javax.servlet.ServletException; + +import static org.junit.Assert.*; +import org.junit.Test; + +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.aop.interceptor.SimpleTraceInterceptor; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletConfig; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * @author Arjen Poutsma + * @since 3.0 + */ +public class CgLibProxyServletAnnotationTests { + + private DispatcherServlet servlet; + + @Test + public void typeLevel() throws Exception { + initServlet(TypeLevelImpl.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("doIt", response.getContentAsString()); + } + + @Test + public void methodLevel() throws Exception { + initServlet(MethodLevelImpl.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("doIt", response.getContentAsString()); + } + + @Test + public void typeAndMethodLevel() throws Exception { + initServlet(TypeAndMethodLevelImpl.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/bookings"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + assertEquals("doIt", response.getContentAsString()); + } + + + private void initServlet(final Class controllerclass) throws ServletException { + servlet = new DispatcherServlet() { + @Override + protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) + throws BeansException { + GenericWebApplicationContext wac = new GenericWebApplicationContext(); + wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerclass)); + DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator(); + autoProxyCreator.setProxyTargetClass(true); + autoProxyCreator.setBeanFactory(wac.getBeanFactory()); + wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator); + wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor(true))); + wac.refresh(); + return wac; + } + }; + servlet.init(new MockServletConfig()); + } + + /* + * Controllers + */ + + @Controller + @RequestMapping("/test") + public static class TypeLevelImpl { + + @RequestMapping + public void doIt(Writer writer) throws IOException { + writer.write("doIt"); + } + } + + @Controller + public static class MethodLevelImpl { + + @RequestMapping("/test") + public void doIt(Writer writer) throws IOException { + writer.write("doIt"); + } + } + + @Controller + @RequestMapping("/hotels") + public static class TypeAndMethodLevelImpl { + + @RequestMapping("/bookings") + public void doIt(Writer writer) throws IOException { + writer.write("doIt"); + } + } + +} \ No newline at end of file diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java index 6fbf82713b..766218414e 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java @@ -1121,6 +1121,16 @@ public class ServletAnnotationControllerTests { assertEquals("myParam-42", response.getContentAsString()); } + @Test + public void bridgeMethods() throws Exception { + initServlet(TestControllerImpl.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/method"); + MockHttpServletResponse response = new MockHttpServletResponse(); + servlet.service(request, response); + } + + /* * Controllers @@ -1900,4 +1910,23 @@ public class ServletAnnotationControllerTests { } } + public interface TestController { + + ModelAndView method(T object); + } + + public static class MyEntity { + + } + + @Controller + public static class TestControllerImpl implements TestController { + + @RequestMapping("/method") + public ModelAndView method(MyEntity object) { + return new ModelAndView("/something"); + } + } + + } diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodResolver.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodResolver.java index e15350b2b0..816dd4b806 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodResolver.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodResolver.java @@ -77,7 +77,7 @@ public class HandlerMethodResolver { ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() { public void doWith(Method method) { Method specificMethod = ClassUtils.getMostSpecificMethod(method, currentHandlerType); - if (isHandlerMethod(specificMethod)) { + if (isHandlerMethod(method)) { handlerMethods.add(specificMethod); } else if (method.isAnnotationPresent(InitBinder.class)) { @@ -99,7 +99,7 @@ public class HandlerMethodResolver { } protected boolean isHandlerMethod(Method method) { - return AnnotationUtils.findAnnotation(method, RequestMapping.class) != null; + return method.isAnnotationPresent(RequestMapping.class); } -- GitLab