ejb-3.0 - 我可以将这个 EJB 的资源传递给另一个 EJB 吗?
问题描述
这更像是一个概念问题。
假设您有两个 EJB,A
并且B
.
首先A
获取一些资源。它可以是任何东西:
- 注入
@Resource
; - 通过
JNDI
(new InitialContext()...
) 获得的东西; javax.naming.Context
(也许A
'InitialContext
指向 ' 以外的树B
)InitialContext
;EJB
在数据库中找到(或创建)的实体;- 引用第三个 EJB
C
; - 数据库连接;
- 数据库
ResultSet
(实时或缓存); - 打开流(到文件,到套接字);
Socket
;File
;- [有创意]。
然后它调用B
,将这些资源作为参数传递(直接或打包在其他对象中)。
这甚至合法吗?
让我们忽略Remote
接口,因为其中许多资源无论如何都不能序列化。
但是对于本地接口呢?这是否违反规范?
为什么这很重要?
具体目标是创建一个通用@Stateless
会话 bean 来执行@FunctionalInterface
,如下所示:
@Stateless
public class FunctionalEJB {
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public <R> R executeInTransaction(Supplier<R> supplier) {
return supplier.get();
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void executeInTransaction(Runnable runnable) {
runnable.run();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public <R> R executeInNewTransaction(Supplier<R> supplier) {
return supplier.get();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void executeInNewTransaction(Runnable runnable) {
runnable.run();
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public <R> R executeOutsideTransaction(Supplier<R> supplier) {
return supplier.get();
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void executeOutsideTransaction(Runnable runnable) {
runnable.run();
}
}
那么这个 EJB 可以这样使用:
public class SomeClient extends SomeSuperClient {
@Inject
private FunctionalEJB ejb;
// ...
public method() {
// ... many things before
// open a special transaction to execute part of the logic
ejb.executeInNewTransaction(() => {
/***
Everything done here is executed in a new transaction.
This object (implicitly created by arrow function syntax)
carries a lot of state as closure; this code here can access:
- `SomeClient` fields
- `SomeClient` methods (defined either in `SomeClient` itself, or `SomeSuperClient`, or some other subclass of `SomeClient`);
- any variable defined in `method` before creating this transaction (as long as it is final, or effectively final).
****/
});
// ... many things after (the special transaction is already closed)
}
// ...
}
来自EJB 3.2 规范的引用
我从规范中收集了一些引用(查找“参数”)。其中一些为传递 - 至少 - 对其他会话 bean 的引用提供了理由。
尽管没有明确允许,但我列出的大多数情况(1-10,除了 4)在通过本地接口或无接口视图传递时似乎是合法的。
情况 4 稍微复杂一点,因为在一个事务中获得的实体 bean 可能在另一个事务中不可用(并且跨越会话 bean 边界可能会暂停当前事务 - 一个现有事务 - 并且可能创建另一个事务)。
【重点是我加的,不是出处】
3.2.3 在本地或远程客户端视图之间进行选择
“远程调用涉及按值传递。这种复制语义在调用者和被调用者之间提供了一层隔离,并防止数据的意外修改。客户端和 bean 可以被编程为假设此参数复制。”
“作为远程调用参数传递的对象必须是可序列化的。”
“本地调用涉及传递引用。客户端和 bean 可能被编程为依赖传递引用语义。例如,客户端可能有一个大文档,它想传递给 bean 进行修改,并且 bean 进一步传递。在本地编程模型中,状态共享是可能的。另一方面,当 bean 想向客户端返回数据结构但 bean 不希望客户端修改它时,bean在返回之前显式地复制数据结构,而在远程编程模型中,bean 不会复制数据结构,因为它假设系统会进行复制。”
“由于本地调用涉及传递引用,本地客户端和提供本地客户端视图的企业 bean 是并置的。”
“本地编程模型所需要的搭配意味着企业 bean 不能部署在与其客户端不同的节点上,从而限制了组件的分布。”
3.4.3 Session Bean的业务接口
- "对会话 bean 的业务接口的引用可以作为参数或业务接口方法的返回值传递。如果引用是对会话 bean 的本地业务接口,则该引用只能作为参数或返回值传递本地业务接口方法或无接口视图方法。”
3.4.4 Session Bean的无接口视图
- "对无接口视图的引用可以作为任何本地业务接口或无接口视图方法的参数或返回值传递。 "
3.4.5 会话对象生命周期的客户端视图
“具有对会话对象的业务接口的引用的客户端然后可以在接口上调用业务方法和/或将引用作为参数或业务接口方法的返回值传递。[4]”
“[4] 请注意,EJB 3.x 会话 bean 业务接口不是 EJBObject。通过 bean 的远程组件接口传递对远程业务接口的引用是无效的。”
3.6.5.2 对会话对象本地组件接口的引用
- “具有对会话对象的本地组件接口的引用的客户端可以执行以下任何操作:[...]将引用作为参数或本地组件接口方法的返回值传递。[...]”
解决方案
推荐阅读
- arrays - 使用 JSON 自定义数组格式?
- c++ - 将类添加到相同类型的向量会导致错误。已弃用
- apollo-server - 需要多个 ApolloServer 来实现连接到 REST API 的网关?
- ios - 在 pkg-config 搜索路径中找不到通过 Homebrew 安装的软件包
- javascript - 添加到购物车时如何在 Wordpress/Woocommerce/Js 中禁用“滚动到顶部”动画/效果?
- html - HTML 行并排显示,而不是在列中垂直显示
- python - Pandas Plotting:如何在不手动绘制的情况下绘制多条线?
- magento2 - 将 UPC 属性添加到产品页面
- rust - 虽然 Rust 的 char 支持非英文字符,但很多文章推荐使用 string 来存储非英文字符,而不是 char。为什么?
- c++ - 将模板指针转换为 char 指针时 C++ 不执行代码