0

BeforeAspect.java

@Aspect
@Component
@EnableAsync
public class BeforeAspect {

    @Pointcut("@annotation(com.example.demo.api.EventLog)")
    public void eventLogControllers() {}

    @Before("eventLogControllers()")
    @Async
    public void beforeController(JoinPoint BeforeJoinPoint){
        HttpServletRequest requestAttributes=((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        System.out.println("Before LocalName: "+requestAttributes.getLocalName());
        System.out.println("Before Request URL: "+requestAttributes.getRequestURL());
    }
}

Controller.java

@RequestMapping("employee")
@RestController
public class Controller {
    EmployeeService empser;
    @Autowired
    public Controller(EmployeeService empser) {
        this.empser = empser;
    }

    @GetMapping
    @EventLog
    public List<Employee> selectemployees(){
        return empser.findallemployees();
    }
}

EventLog.java

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface EventLog {
}

When I run the application I get below error

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at com.example.demo.EventAspects.BeforeAspect.beforeController(BeforeAspect.java:37) ~[classes/:na]
    at com.example.demo.EventAspects.BeforeAspect$$FastClassBySpringCGLIB$$e508b82a.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) ~[spring-aop-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

I get the above error when trying to access the employee api. My requirement is I needed to create the AOP before advice(Aspectj) as asynchronous and access request details in the asynchronous before method. The method works fine if it is not asynchronous. Is there a way I can pass RequestContextHolder as argument to the before method? or is there any other way to access it.

Alison
  • 31
  • 3

1 Answers1

0

I am not a Spring user, but sometimes try to help Spring AOP users with my AOP knowledge. This is more about Spring's @Async feature, so I am not very knowledgeable there.

Here is some general information about asynchronous AOP advice with extra information about @Around, which does not seem to be your focus. but maybe you can extract something helpful from my answer anyway.

As for your use case, you are obviously forcing something to be asynchronous which is meant to be synchronous. You only said that you want the advice to run asynchronously, but did not explain why. It works fine synchronously, why bother breaking a working system? Is your aspect so super slow? Go optimise it!

If you insist to have it asynchronous, why don't you follow the advice given in the error message? Quote:

No thread-bound request found:

Are you referring to request attributes outside of an actual web request,
or processing a request outside of the originally receiving thread?

If you are actually operating within a web request and still receive this
message, your code is probably running outside of DispatcherServlet:
In this case, use RequestContextListener or RequestContextFilter to expose
the current request.
kriegaex
  • 63,017
  • 15
  • 111
  • 202