java - quarkus: IllegalStateException: 您试图在 IO 线程上执行阻塞操作。这是不允许的,因为阻塞了 IO 线程
问题描述
我无法理解 quarkus 的一件事。我将 JPA 与 Oracle 一起使用。所以我有错误 IllegalStateException: 你试图在 IO 线程上执行阻塞操作。这是不允许的,因为阻塞了 IO 线程,我在 Quarkus 文档中查看了如何在没有这个困难的情况下进行 JPA 调用。但所有示例和文档都使用 PostgreSQL 或 MariaDB 和响应式客户端。但我还没有找到任何经典的 JDBC 客户端。
我找到了一个部分有效的解决方案。
Uni.cretaFrom().Items(() -> MyBlokingIOCall());
事实上,我不再有例外。但是 MyBlokingIOCall 方法可以引发异常。我想我可以使用 Uni 的 onFailure 但我们不能将引发异常的方法传递给
Uni.cretaFrom().Items
事实上,这个方法有一个供应商作为参数,因此必须捕获异常。在这个解决方案中使用 Uni 的 onFailure 是不可能的。如果我在命令模式下使用当前代码
try {
Response.ok (myService ());
} catch (throwable e) {
Response.status (555, e.getMessage ());
}
我徒劳地试图以反应形式做到这一点,但我没有找到解决方案。我没有找到任何帮助。我想象过类似的东西。
Uni.createFrom().Items(() -> myService())
.onItem().apply(data -> Response.ok(data))
.onFailure().apply(err -> Response.status(555, err.getMessage()))
但这会导致编译错误。实际上 myService 方法不能在 Supplier 中使用,因为它会引发异常。因此必须将其捕获。但是后来我们不再进入 Uni 的 onFailure 并且我们无法追踪我们捕获的错误。
我认为我想太多关于穿着我的命令式代码而不是不同的想法。
但是我无论如何都找不到看起来像这样的文档或示例。我想有一种做事的方式(如果不是 Quarkus 就不会存在)。我认为当你用正确的方法考虑它时,你必须找到文档,但是当你不知道去哪里时,它就更复杂了。我没有找到它,因为我不知道我在寻找什么。
我想我必须封装产生 Uni 或 Multi 的 JPA 调用,该调用由将实体转换为 DTO 的处理器消耗,然后将其传输到将 DTO 转换为响应的资源 Rest 层。JPA 调用也必须能够在处理器和资源层产生错误
因此,有必要在每个步骤中捕获这些错误以通过 Uni 或 Multi 传播它们
但是怎么做呢?
解决方案
通过简单地提供lambda实现(或方法引用)作为方法调用参数,这是一种已知的lambda限制。
同时,可以通过在预期的Functional Interface周围实现扩展来简单地解决它,在您的情况下Supplier<T>
,它将捕获任何 **checked** 异常并抛出未经检查的异常:
/**
* A Supplier sub-interface that catches any thrown exception
* and translates to an unchecked one.
*
* <p>This is a functional interface whose functional method is
* {@link #getChecked()}.
*/
@FunctionalInterface
public interface CheckedSupplier<T> extends Supplier<T> {
@Override
default T get() {
try {
return getChecked();
} catch (final Exception e) {
// Your common exception handling logic here..
throw new RuntimeException(e);
}
}
/**
* Gets a result.
*
* @return a result
* @throws Exception
*/
T getChecked() throws Exception;
}
请注意,功能接口签名不再是#get()而是#getChecked()。但这对编译器没有任何影响,它将尝试根据预期的签名检查功能签名,即:
返回 T 类型对象的方法
然后,您可以在任何需要 a (或类似)的地方使用显式转换来简单地使用新CheckedSupplier
接口:Supplier<T>
Uni.createFrom().item((CheckedSupplier<DataType>) MutinyTest::findOne)
.onItem()
.apply(i-> Response.ok(i))
.onFailure()
.apply(e-> Response.status(555, e.getMessage()));
推荐阅读
- python - 在scrapy中重定向中间件不起作用
- laravel - Vue / Vuetify / Laravel - 存储多个文件输入
- ios - 导航栏“hidesBarOnSwipe”的动画延迟
- sparql - 使用 SPARQL 查询具有特定主题的属性
- reactjs - 更改 reactbootstrap 导航栏切换图标。(样式化组件)
- webgl - 在 WebGL 中实现阴影的问题
- r - data.table:通过具有多个分组变量的组选择具有最大值的行
- javascript - django链接表行查看
- node.js - TypeError:message.channel.sendMessage 不是函数
- sql - 获取每个月数据的差异