java.lang.IllegalStateException: No thread-bound request found, exception in aspect

97,828

Solution 1

You shouldn't autowire a HttpServletRequest in your aspect as this will tie your aspect to be only runnable for classes that are called from within an executing HttpServletRequest.

Instead use the RequestContextHolder to get the request when you need one.

private String getRemoteAddress() {
    RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
    if (attribs instanceof NativeWebRequest) {
        HttpServletRequest request = (HttpServletRequest) ((NativeWebRequest) attribs).getNativeRequest();
        return request.getRemoteAddr();
    }
    return null;
}

Solution 2

@M. Deinum answer doesn't work for me. I use these code instead

RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
if (RequestContextHolder.getRequestAttributes() != null) {
    HttpServletRequest request = ((ServletRequestAttributes) attributes).getRequest();
    return request.getRemoteAddr();
}

Solution 3

Create bean for RequestContextListener. I got the same error for autowiring HttpServletRequest And the following two lines of code works for me

@Bean
public RequestContextListener requestContextListener() {
    return new RequestContextListener();
}

Solution 4

As the error message said: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

To fix it, register a RequestContextListener listener in web.xml file.

<web-app ...>
   <listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
   </listener>
</web-app>

Solution 5

With your pointcut expression, you're basically proxying every bean and applying that advice. Some beans exist and operate outside the context of an HttpServletRequest. This means it cannot be retrieved.

You can only inject the HttpServletRequest in places where a Servlet container request handling thread will pass through.

Share:
97,828
hrishikeshp19
Author by

hrishikeshp19

Engineer

Updated on May 10, 2021

Comments

  • hrishikeshp19
    hrishikeshp19 about 3 years

    Following is my aspect:

        @Configurable
        @Aspect
        public class TimingAspect {
    
            @Autowired
            private HttpServletRequest httpServletRequest;
    
            // Generic performance logger for any mothod
            private Object logPerfomanceInfo(ProceedingJoinPoint joinPoint, String remoteAddress) {
                StringBuilder tag = new StringBuilder();
                if (joinPoint.getTarget() != null) {
                    tag.append(joinPoint.getTarget().getClass().getName());
                    tag.append(".");
                }
                tag.append(joinPoint.getSignature().getName());
                StopWatch stopWatch = new StopWatch(tag.toString());
                Object result = joinPoint.proceed(); // continue on the intercepted method
                stopWatch.stop();
    
                PerformanceUtils.logInPerf4jFormat(stopWatch.getStartTime(), stopWatch.getElapsedTime(), stopWatch.getTag(), stopWatch.getMessage(), remoteAddress);
                return result;
            }
    
            @Around("execution(* $$$.$$$.$$$.api.controller.*.*(..))")
            public Object logAroundApis(ProceedingJoinPoint joinPoint) throws Throwable {
                String remoteAddress = null;
                if (httpServletRequest != null) {
                   remoteAddress = httpServletRequest.getRemoteAddr();
                }
                return logPerfomanceInfo(joinPoint, remoteAddress);
            }
    
            @Around("execution(* $$$.$$$.$$$.$$$.$$$.$$$.*(..))")
            public Object logAroundService(ProceedingJoinPoint joinPoint) throws Throwable {
                String remoteAddress = null;
                if (httpServletRequest != null) {
                    remoteAddress = httpServletRequest.getRemoteAddr();
                }
                return logPerfomanceInfo(joinPoint, remoteAddress);
            }
    

    I do not get any compile time errors but I do following exception when I start my jetty server:

    nested exception is 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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

    One thing to note here is, if I remove "logAroundService" method, I do not get any exceptions.

  • hrishikeshp19
    hrishikeshp19 almost 10 years
    all the methods intercepted by all pointcuts are called in the same servlet container request handling thread.
  • hrishikeshp19
    hrishikeshp19 almost 10 years
    If it cannot be retrieved, it should be null, why illegalstate?
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @riship89 Post your full stack trace to prove it. The other possibility is that you have your aspect loaded by the ContextLoaderListener ApplicationContext rather than the DispatcherServlet's.
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @riship89 With @Autowired you are setting an injection target. You are saying I want this to be managed by Spring. Well, in this case, Spring can't manage it so it crashes.
  • hrishikeshp19
    hrishikeshp19 almost 10 years
    Okay, I get it now. many of my beans are in application context and not in servlet context. Now, how can I expose httpservlet request in my whole application?
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @riship89 Depends. Say you had a background job bean that was working in parallel with the rest of your application but not in the context of a request. Your Aspect would currently be advising it but would fail right away. What request should it inject? There's none running.
  • hrishikeshp19
    hrishikeshp19 almost 10 years
    Would it help if servlet context is in application context? Currently, my servlet context is outside my application context.
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @riship89 Sorry, but that doesn't make much sense. The application context is one context. It contains beans that are should be shared by the whole application. This is loaded by the ContextLoaderListener. The servlet context contains beans that should only be relevant to the servlet, ie. the DispatcherServlet. Since the servlet is part of the application, it has access to the application context, but not vice versa. Can you clarify?
  • hrishikeshp19
    hrishikeshp19 almost 10 years
    makes sense, ignore my comment. Let us say that I do not have any background processes running, and only thing that is running is server, how can I expose httpservletrequest to application context beans?
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @riship89 Almost everything in an ApplicationContext is a bean, even if you didn't declare. In other words, even the Spring infrastructure components are beans. Your Aspect applies to them as well. But the ApplicationContext is initialized outside of a request, so your aspect would try to run for any method on any of those beans outside of a request context. Your only solutions are to restrict your aspect or don't inject the HttpServletRequest.
  • hrishikeshp19
    hrishikeshp19 almost 10 years
    is there any easy way to move all the beans in request scope. Or is there a way to assign scope="request" to all the beans in application context?
  • M. Deinum
    M. Deinum almost 10 years
    Please add your final solution to your question for future reference.
  • fl4l
    fl4l over 8 years
    Remember to add the following listener in the web.xml (otherwise attribs will be null): <listener> <listener-class>org.springframework.web.context.request.Req‌​uestContextListener<‌​/listener-class> </listener>
  • Andrea Bergia
    Andrea Bergia over 6 years
    This worked for me in weblogic 10.3.6 with a relatively recent version of spring boot (1.4)
  • OmriYaHoo
    OmriYaHoo about 4 years
    I had the same issue and this fixes it for me. Thanks!