diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMapping.java index 1318c7030..6acef065f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMapping.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMapping.java @@ -45,10 +45,12 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.Part; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; @@ -168,7 +170,10 @@ public class BasePathAwareHandlerMapping extends RequestMappingHandlerMapping { */ @Override protected boolean isHandler(Class beanType) { - return beanType.getAnnotation(BasePathAwareController.class) != null; + + Class type = ClassUtils.getUserClass(beanType); + + return type.isAnnotationPresent(BasePathAwareController.class); } /* diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java index 8d3f9c0ea..5318ec001 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java @@ -39,6 +39,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.StringValueResolver; @@ -169,7 +170,10 @@ public class RepositoryRestHandlerMapping extends BasePathAwareHandlerMapping { */ @Override protected boolean isHandler(Class beanType) { - return AnnotationUtils.findAnnotation(beanType, RepositoryRestController.class) != null; + + Class type = ClassUtils.getUserClass(beanType); + + return AnnotationUtils.findAnnotation(type, RepositoryRestController.class) != null; } /* diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMappingUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMappingUnitTests.java new file mode 100644 index 000000000..3489ff9e8 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BasePathAwareHandlerMappingUnitTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017 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; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import org.junit.Test; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.data.rest.core.config.RepositoryRestConfiguration; +import org.springframework.util.ClassUtils; + +/** + * Unit tests for {@link BasePathAwareHandlerMapping}. + * + * @author Oliver Gierke + */ +public class BasePathAwareHandlerMappingUnitTests { + + RepositoryRestConfiguration configuration = mock(RepositoryRestConfiguration.class); + HandlerMappingStub mapping = new HandlerMappingStub(configuration); + + @Test // DATAREST-1132 + public void detectsAnnotationsOnProxies() { + + Class type = createProxy(new SomeController()); + + assertThat(mapping.isHandler(type)).isTrue(); + } + + @Test // DATAREST-1132 + public void doesNotConsiderMetaAnnotation() { + + Class type = createProxy(new RepositoryController()); + + assertThat(mapping.isHandler(type)).isFalse(); + } + + private static Class createProxy(Object source) { + + ProxyFactory factory = new ProxyFactory(source); + Object proxy = factory.getProxy(); + + assertThat(ClassUtils.isCglibProxy(proxy)).isTrue(); + + return proxy.getClass(); + } + + @BasePathAwareController + static class SomeController {} + + @RepositoryRestController + static class RepositoryController {} + + static class HandlerMappingStub extends BasePathAwareHandlerMapping { + + public HandlerMappingStub(RepositoryRestConfiguration configuration) { + super(configuration); + } + + @Override + public boolean isHandler(Class beanType) { + return super.isHandler(beanType); + } + } +} diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java index cb597c479..e1bf9c311 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java @@ -26,6 +26,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.aop.framework.ProxyFactory; import org.springframework.data.domain.Sort; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.Path; @@ -39,6 +40,7 @@ import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguratio import org.springframework.data.rest.webmvc.support.DefaultedPageable; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockServletContext; +import org.springframework.util.ClassUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.method.HandlerMethod; @@ -256,4 +258,40 @@ public class RepositoryRestHandlerMappingUnitTests { public void twoArgumentConstructorDoesNotThrowException() { new RepositoryRestHandlerMapping(mappings, configuration); } + + @Test // DATAREST-1132 + public void detectsAnnotationsOnProxies() { + + Class type = createProxy(new SomeController()); + + HandlerMappingStub mapping = new HandlerMappingStub(mock(ResourceMappings.class), + mock(RepositoryRestConfiguration.class)); + + assertThat(mapping.isHandler(type)).isTrue(); + } + + private static Class createProxy(Object source) { + + ProxyFactory factory = new ProxyFactory(source); + Object proxy = factory.getProxy(); + + assertThat(ClassUtils.isCglibProxy(proxy)).isTrue(); + + return proxy.getClass(); + } + + @RepositoryRestController + static class SomeController {} + + static class HandlerMappingStub extends RepositoryRestHandlerMapping { + + public HandlerMappingStub(ResourceMappings mappings, RepositoryRestConfiguration configuration) { + super(mappings, configuration); + } + + @Override + public boolean isHandler(Class beanType) { + return super.isHandler(beanType); + } + } }