在servlet 3 async Controler中请求范围bean

时间:2017-05-29 20:59:47

标签: spring spring-mvc servlets spring-boot

我在Spring Boot应用程序中使用Servlet 3控制器。该控制器调用最终发出3个HTTP请求的服务。

@GetMapping("/nbasync/c/**")
public CompletableFuture<String> nonBlockingAsyncCall() throws Exception {
    CompletableFuture<String> result = service.call());

    CompletableFuture<Void> result2 = service2.call();
    CompletableFuture<Void> result3 = service3.call();

    return result
            .thenCombine(result2, this::keepFirst)
            .thenCombine(result3, this::keepFirst);
}

每次拨出电话均使用RestTemplate进行,并由ClientHttpRequestInterceptor拦截。在这个ClientHttpRequestInterceptor中,我需要一个(代理的)请求范围的bean(cf:How to enable request scope in async task executor和Runnable)。

如果我等待结果,这可以正常工作:

    CompletableFuture.allOf(result, result2, result3).join();
    return result.get();

在非阻塞方法中,它崩溃时出现以下异常:

java.util.concurrent.CompletionException: 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.requestCookieHelper': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is 
java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!

请参阅完整日志:https://gist.github.com/Skeebl/d0b19ebb9ab4d0d2a917203e4bd6fad5

似乎每次线程放开进程时,都会调用AbstractRequestAttributes.requestCompleted()(两次)。此方法设置this.requestActive = false;。虽然requestActive为false,但您无法访问请求范围的bean。

拦截器和请求范围的bean简化了方法签名。有没有办法在处理异步请求时保留这些内容?

0 个答案:

没有答案