Getting Request Object in Spring Webflux elastic thread

2.4k Views Asked by At

I am facing one issue. I am calling some API's in parallel using Spring Webflux. If any child thread faces any issue, it needs to log the request. Now the issue is , for logging a normal POJO class in which there is a static method which gets a bean via ApplicationContent and store the data in a Queue.

Now the issue is, I want to access request params like Request URL / Controller etc. I tried

ServletRequestAttributes sra = 
        (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
                    logger.error("====="+sra);
                    HttpServletRequest httpRequest = sra.getRequest();

but In this case, sra is null. I tried adding the following code,

@Configuration
public class InheritableRequestContextListener extends RequestContextListener {
    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
        InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";

    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        System.out.println("111111111111111111");
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes, true);
    }
}

but this is not helping. Can anyone help. I am using springboot version ; 2.0.2.RELEASE.

1

There are 1 best solutions below

2
Toerktumlare On

There are several reasons as to why your implementation does not work.

Webflux is thread agnostic, which means that any thread can deal with anything at anytime in the application. If the application finds it efficiant to switch the current executing thread, it will do so.

Servlet applications on the other hand assigns one thread to each request and sticks with that thread throughtout execution.

ApplicationContext uses as you can see ServletRequests, so it is not usable in a Webflux application. It in turn uses threadlocal to store the request object to the designated thread.

In webflux you cant use threadlocal, bucase as soon as the application switches threads everything in threadlocal is gone. Thats why you get null.

So how do you pass data from thread to thread.

What you need to do is to implement a filter that intercepts the request, extracs the information you want and places it in the reactive context object.

https://projectreactor.io/docs/core/release/reference/#context

Here is a post that addresses the problem.

https://developpaper.com/implementation-of-requestcontextholder-in-spring-boot-webflux/