java.lang.IllegalStateException: No thread-bound request found, exception in aspect
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.
Comments
-
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 almost 10 yearsall the methods intercepted by all pointcuts are called in the same servlet container request handling thread.
-
hrishikeshp19 almost 10 yearsIf it cannot be retrieved, it should be null, why illegalstate?
-
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 theDispatcherServlet
's. -
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 almost 10 yearsOkay, 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 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 almost 10 yearsWould it help if servlet context is in application context? Currently, my servlet context is outside my application context.
-
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. theDispatcherServlet
. Since the servlet is part of the application, it has access to the application context, but not vice versa. Can you clarify? -
hrishikeshp19 almost 10 yearsmakes 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 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 theApplicationContext
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 theHttpServletRequest
. -
hrishikeshp19 almost 10 yearsis 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 almost 10 yearsPlease add your final solution to your question for future reference.
-
fl4l over 8 yearsRemember to add the following listener in the web.xml (otherwise attribs will be null):
<listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
-
Andrea Bergia over 6 yearsThis worked for me in weblogic 10.3.6 with a relatively recent version of spring boot (1.4)
-
OmriYaHoo about 4 yearsI had the same issue and this fixes it for me. Thanks!