question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@Around advice doesn't work with OncePerRequestFilter

See original GitHub issue

Affects: Spring Boot 2.5.6 (Both AOP and Web are 2.5.6)

Greetings,

I’m relatively new to Spring, but after a bit of Googling this seems like an issue with interconnection between different Spring components. Or maybe I’m just using them wrong? Please advise if so, otherwise this just might be an unfortunate bug?

I’m trying to add a traceId entry to our logs via MDC.

I’ve created a filter that extends OncePerRequestFilter which doesn’t really do anything, except serves as a place to attach an advice to.

@Component
class TraceIdFilter : OncePerRequestFilter() {

    @Traceable
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        filterChain.doFilter(request, response)
    }
}

I have an @Around advice:

@Aspect
@Component
class TraceableRequestAspect(private val uuid: () -> UUID) {

    @Around("@annotation(Traceable)")
    fun advice(joinPoint: ProceedingJoinPoint) {
        try {
            MDC.put(LogstashField.TRACE_ID, "${uuid()}")
            joinPoint.proceed()
        } finally {
            MDC.remove(LogstashField.TRACE_ID)
        }
    }
}

I expect that the Around advice will ‘wrap’ the filter method and attach an MDC entry to all HTTP request logs and then clean up after itself.

In reality, this is what I’m seeing:

2022-01-20 14:42:54.147  INFO 23739 --- [           main] o.s.aop.framework.CglibAopProxy          : Unable to proxy interface-implementing method [public final void org.springframework.web.filter.OncePerRequestFilter.doFilter(javax.servlet.ServletRequest,javax.servlet.ServletResponse,javax.servlet.FilterChain) throws javax.servlet.ServletException,java.io.IOException] because it is marked as final: Consider using interface-based JDK proxies instead!
2022-01-20 14:42:54.147  INFO 23739 --- [           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!
2022-01-20 14:42:54.211 ERROR 23739 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Exception starting filter [traceIdFilter]

java.lang.NullPointerException: null
	at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:241)
	at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:270)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4613)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:450)
	at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:199)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
	at net.leoncorp.ft.integration.ApplicationKt.main(Application.kt:14)

2022-01-20 14:42:54.212 ERROR 23739 --- [           main] o.apache.catalina.core.StandardContext   : One or more Filters failed to start. Full details will be found in the appropriate container log file
2022-01-20 14:42:54.212 ERROR 23739 --- [           main] o.apache.catalina.core.StandardContext   : Context [] startup failed due to previous errors
2022-01-20 14:42:54.254  INFO 23739 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

I’m not sure whether I can follow the advice the error message throws as none of the code responsible for this is under my purview.

Thanks in advance for any assistance.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
sbrannencommented, Jan 26, 2022

Your @Around aspect is written not entirely correct. You always must return the result of joinpoint.proceed() and the return type must be Object not void. If you don’t you will be actually destroying the result of the method execution and always return null.

You aren’t the first to run into this, I’ve answered many questions on stack overflow on this. It might be worthwhile to improve the documentation on this that that is a must.

I opened #27980 to address this.

0reactions
kriegaexcommented, Jul 23, 2022

For reference: This question has been asked again lately on Stack Overflow, and here is my answer explaining the situation in more detail, also linking back to @mdeinum’s reply here. The more general issue with trying to advise final methods accessing instance fields is explained here. My answer on SO also contains sample pointcuts for users who want to do advise filters using native AspectJ.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to manage exceptions thrown in filters in Spring?
I come across this issue myself and I performed the steps below to reuse my ExceptionController that is annotated with @ControllerAdvise for Exceptions ......
Read more >
OncePerRequestFilter (Spring Framework 6.0.2 API)
Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container.
Read more >
How to add a filter in Spring Boot | Java Development Journal
A quick and practical guide on how to add a filter in Spring Boot and what are the options to configure these filters...
Read more >
Provide a way to handle RequestRejectedException #5007
throw new RequestRejectedException("The request was rejected because the URL was not normalized."); will finally be caught by the Tomcat ...
Read more >
WatchOut : SpringBoot GlobalExceptionHandler won't handle ...
Everything was working fine until I thrown an Exception from a Filter class. I had a OncePerRequestFilter class where I validated the JWT...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found