Because of some reason, I need create RequestMappingHandlerMapping (using anonymous inner class instead here, need override some method(s)) myself, and need using AspectJ, when my defined RequestMappingHandlerMapping intercepted by AOP, my defined RequestMappingHandlerMapping will throw NullPointerException when getHandler called, you can re-create this issue using below code (create any RESTful Controller for testing)
I checked, it because logger is null, but it works fine if I remove Aspect code.
line 416: if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
error details:
Caused by: java.lang.NullPointerException: null at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:416) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE] at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1232) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1015) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE] ... 26 common frames omitted
depends and codes below:
Spring boot version and dependencies:
springBootVersion = '2.1.5.RELEASE'
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-aop'
compile 'org.apache.tomcat.embed:tomcat-embed-jasper'
compile 'javax.servlet:jstl'
compile 'com.google.guava:guava:23.0'
testCompile 'org.springframework.boot:spring-boot-starter-test'
}
java codes:
package com.mdx.myboot.web.config;
@Configuration
public class MyWebMVCConfiguration extends WebMvcConfigurationSupport {
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new RequestMappingHandlerMapping() {
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
}
};
}
}
package com.mdx.myboot.config;
@Component
@Aspect
public class MyAspect {
@Pointcut("execution(* com.mdx..*.*(..))")
public void loggingPointCut() {
}
@Around("loggingPointCut()")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
System.err.println("executing " + joinPoint.getSignature());
return joinPoint.proceed();
}
}
Comment From: rstoyanchev
Please, provide a sample that demonstrates the issue.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: mdxShrimp
please see the sample code in below project: SpringIssue you can try this request: http://localhost:8080/hello Spring Boot main class: com.mdx.myboot.MySpringApplication And you can remove(or keep) the class com.mdx.myboot.aspect.MyAspect to check the issue when enable Aspectj
Comment From: rstoyanchev
Thanks for the sample.
I think the problem is related to the following messages on startup:
2020-01-03 12:21:04.169 INFO 12621 --- [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final org.springframework.web.servlet.HandlerExecutionChain org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(javax.servlet.http.HttpServletRequest) throws java.lang.Exception] because it is marked as final: Consider using interface-based JDK proxies instead!
2020-01-03 12:21:04.170 INFO 12621 --- [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.web.context.support.WebApplicationObjectSupport.setServletContext(javax.servlet.ServletContext)] because it is marked as final: Consider using interface-based JDK proxies instead!
2020-01-03 12:21:04.172 INFO 12621 --- [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(org.springframework.context.ApplicationContext) throws org.springframework.beans.BeansException] because it is marked as final: Consider using interface-based JDK proxies instead!
Proxy by class (extension) can't work here because those methods are final. I experimented that switching to proxy by interface with the below property (based on AopAutoConfiguration) makes it work:
spring:
aop:
proxy-target-class: false
There may be other side effects depending on whether something else in your application depends on proxy by class vs proxy by interface. Nevertheless, the point remains that you can't proxy RequestMappingHandlerMapping by class.
In addition keep in mind that creating your own WebMvcConfigurationSupport overrides the auto config from Boot. If that is what you want, fine. If not consider declaring a WebMvcRegistrations component to provide the RequestMappingHandlerMapping without overriding the rest of the Boot auto config. See https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration.
Comment From: mdxShrimp
Thanks rstoyanchev, it works now!