gpt4 book ai didi

java - Spring + SessionScope + CompletableFuture = 错误

转载 作者:太空宇宙 更新时间:2023-11-04 10:23:38 26 4
gpt4 key购买 nike

我们的应用程序有非常奇怪的 react 。该应用程序有一个(单例)服务 - 让我们称之为 singletonService 。以及在 session 范围内运行的其他服务。 sessionService .

singletonService有一个像这样的方法 CompletableFuture<String> longTask(String param)在漫长的任务之后,singletonService必须调用sessionService (对于方法 String transform(String param) )。

当我们写longTask()时就像示例 1 一样,一切正常。transform方法按预期运行。

示例1.1

public CompletableFuture<String> longTask(String param) {
CompletableFuture<String> future = startLongTask(param);
future.thenApply(sessionService::transform);
return future;
}

示例1.2

public CompletableFuture<String> longTask(String param) {
CompletableFuture<String> future = startLongTask(param);
future.thenApplyAsync(sessionService::transform, asyncExecutor);
return future;
}

但是这样我们就不用等待transform方法。最好像示例2那样写。

示例2.1

public CompletableFuture<String> longTask(String param) {
return startTaskLongTask(param).thenApply(sessionService::transform);
}

示例2.2

public CompletableFuture<String> longTask(String param) {
return startTaskLongTask(param).thenApplyAsync(sessionService::transform, asyncExecutor);
}

但是示例 2 总是会异常完成。它抛出 org.springframework.beans.factory.BeanCreationException 。整个异常:

Scope 'session' 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: 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.

有没有人提示,我们必须在哪里寻找问题?

附加信息

startLongTask()的签名是这样的:private CompletableFuture<String> startLongTask(String param) 。为了简单起见,我这样写了该方法。实际上,它是调用 RESTful-api 的改进。

asyncExecutor是 Spring 的 bean 。

/**
* Creates a context aware {@link Runnable} that wraps the original one.
*
* @param task The original {@link Runnable}
* @return The wrapper
*/
private Runnable getRunnable(final Runnable task) {
try {
final RequestAttributes attr = RequestContextHolder.currentRequestAttributes();
return () -> {
try {
RequestContextHolder.setRequestAttributes(attr);
} catch (final Exception ignored) {
}
task.run();
try {
RequestContextHolder.resetRequestAttributes();
} catch (final Exception ignored) {
}
};
} catch (final Exception ignored) {
return task;
}
}

transform() 的签名是 String transform(String param) 。该函数使用 session 相关数据(当前用户的区域设置)。

最佳答案

根据您的输入:

示例 1(效果很好):

public CompletableFuture<String> longTask(String param) {
CompletableFuture<String> future = startLongTask(param);
future.thenApply(sessionService::transform);
return future;
}

示例 2(不起作用):

public CompletableFuture<String> longTask(String param) {
CompletableFuture<String> future = startLongTask(param);
return future.thenApply(sessionService::transform);
}

正如您所看到的,这两个示例中的唯一区别是,在示例 1 中,您将返回您创建的 CompletableFuture ,而在示例 2 中,您将返回 then.Apply() 方法;

thenApply 方法的 Oracle 文档:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#thenApply-java.util.function.Function-

public <U> CompletableFuture<U> thenApply(Function<? super T,? extendsU> fn)

Description copied from interface: CompletionStage Returns anew CompletionStage that, when this stage completes normally, isexecuted with this stage's result as the argument to the suppliedfunction. See the CompletionStage documentation for rules coveringexceptional completion.

Specified by: thenApply in interface CompletionStage<T>

Type Parameters: U - the function's return type

Parameters: fn - the function to use to compute the value of thereturned CompletionStage

Returns: the new CompletionStage

问题中的错误描述如下:

If you are actually operating within a web request and still receivethis message, your code is probably running outside ofDispatcherServlet/DispatcherPortlet.

这可能就是这里的原因,由 thenApply 创建的 CompletableFuture 对象位于 DispatcherServlet/DispatcherPortlet 之外。

希望你现在就明白了。 :)

关于java - Spring + SessionScope + CompletableFuture = 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50814390/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com