upon configuring actuator to start up on a distinct port, the app fails with the following stacktrace:
java.lang.NullPointerException: null
at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:241) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:270) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4528) [tomcat-embed-core-9.0.37.jar:9.0.37]
aop issues the following info warning:
2020-08-16 10:01:11.240 INFO 83848 --- [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.web.filter.GenericFilterBean.init(javax.servlet.FilterConfig) throws javax.servlet.ServletException] because it is marked as final: Consider using interface-based JDK proxies instead!
here are my gradle dependencies:
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
...
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.5.RELEASE'
implementation 'org.springframework.security:spring-security-jwt:1.0.10.RELEASE'
we do have one @Aspect annotated class:
...
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.stereotype.Component;
...
@Aspect
@Component
@Slf4j
public class MyFilter {
@Around("execution(public void org.springframework.security.web.FilterChainProxy.doFilter(..))")
public void handleRequestRejectedException (ProceedingJoinPoint pjp) throws Throwable {
try {
pjp.proceed();
} catch (RequestRejectedException exception) {
...
}
}
}
i have found a few issues discussing this problem, having something to do with aop, but i have as of yet failed to find a solution.
any/all help appreciated.
After the OP has updated the question with some sample code, I see that the problem is not a pointcut which is too generic, capturing too many classes like in the other question I linked to in my comment but something else:
James, you are targeting method FilterChainProxy.doFilter(..)
, i.e. directly a Spring framework class. The problem is, as you can also see in the error message you get in your log:
o.s.aop.framework.CglibAopProxy:
Unable to proxy interface-implementing method [
public final void org.springframework.web.filter.GenericFilterBean.init(javax.servlet.FilterConfig)
throws javax.servlet.ServletException
]
because it is marked as final:
Consider using interface-based JDK proxies instead!
The problem is that the target class is derived from GenericFilterBean
where the init(..)
method is marked as final
. CGLIB works via subclassing and overriding non-private methods, but a final method cannot be overridden. Thus, Spring AOP complains.
The error message also hints you towards a solution for the problem: Instead of using a CGLIB proxy for the target, you could use a JDK proxy which works by implementing interfaces. Luckily, doFilter
is an interface method, more precisely an implementation of JavaEE method Filter.doFilter(..)
.
Now the next problem is that you are not using plain vanilla Spring but Spring Boot, which is known for having a combination of presets which seem to make it impossible to switch to JDK proxies, even though in plain Spring that is even the default. But Boot wants to be too user-friendly and smart, leaving you in this trap. I do not remember the Spring Boot ticket dealing with this problem, but last time I checked it was unresolved.
One way to avoid the whole situation is to use full AspectJ instead of just Spring AOP for your aspect, thus freeing you of the proxy-based "AOP lite" approach and enabling you to directly modify the target class or to alternatively weave your aspect not into the target class but into all calling classes instead via call()
pointcut (not supported by Spring AOP).
Another solution would be to hook into another, less problematic target class/method with your aspect, not directly into a Spring framework class with final methods.
P.S.: I am not a Spring user, I just happen to know a few details from answering AOP-related questions here. Actually, I am surprised that CGLIB proxying as implemented by Spring is not more lenient with regard to final methods, just ignoring them and logging a warning instead of trying to override them and producing an error. Maybe there is some configuration option for that, but I leave it up to the Spring folks to answer that question, I have no clue here.
I cannot answer more precisely because I would need to see a full MCVE, ideally a Maven or Gradle project on GitHub, in order to further analyse your situation. I just wanted to explain some basics here.