启动 CDI 对话并将 @ConversationScoped bean 注入无状态会话 bean
Starting a CDI conversation and injecting @ConversationScoped bean into stateless session bean
有人问过类似的问题,但没有完全解决我想做的事情。我们有一个较旧的基于 Seam 2.x 的应用程序,它带有我们正在转换为 CDI 的批处理作业框架。作业框架使用 Seam 上下文对象来发起对话。作业框架还加载一个特定于作业的数据持有者(基本上是一个 Map),然后可以通过 Seam Contexts 对象访问链下的任何服务,包括来自 SLSB 的数据持有者。其中一些服务可以更新地图,以便作业状态可以更改并在记录之间进行检测。
看起来在 CDI 中,作业将 @Inject
一个 CDI 对话对象,并手动 begin/end 对话。我们还将定义一个新的 ConversationScoped
bean 来保存 Map (MapBean
)。我不清楚的是两件事:
首先,该作业还需要@Inject MapBean
,以便它可以在调用 Conversation.begin() 方法之前加载特定于作业的数据。容器会知道将此实例传递给调用链下的服务吗?
与此相关,根据这个问题Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? 应该可以将ConservationScoped
bean 注入到SLSB 中,但这似乎有点神奇。如果 SLSB 被不同的进程(工作、UI 调用等)使用,它是否为每个调用获得单独的实例?
为澄清和简化 class 结构而编辑:
MapBean
需要是一个 ConversationScoped
对象,包含特定 instance/run 作业的数据。
@ConversationScoped
public class MapBean implements Serializable {
private Map<String, Object> data;
// accessors
public Object getData(String key) {
return data.get(key);
}
public void setData(String key, Object value) {
data.put(key, value);
}
}
这份工作是 ConversationScoped
:
@ConversationScoped
public class BatchJob {
@Inject private MapBean mapBean;
@Inject private Conversation conversation;
@Inject private JobProcessingBean jobProcessingBean;
public void runJob() {
try {
conversation.begin();
mapBean.setData("key", "value"); // is this MapBean instance now bound to the conversation?
jobProcessingBean.doWork();
} catch (Exception e) {
// catch something
} finally {
conversation.end();
}
}
}
作业可能会调用 SLSB,MapBean
的当前对话范围实例需要可用:
@Stateless
public class JobProcessingBean {
@Inject private MapBean mapBean;
public void doWork() {
// when this is called, is "mapBean" the current conversation instance?
Object value = mapBean.getData("key");
}
}
我们的工作和 SLSB 框架非常复杂,SLSB 可以调用许多其他服务或本地实例化的业务逻辑 classes,并且每个都需要访问对话范围 MapBean
.
没有任何代码示例,我将不得不做一些猜测,所以让我们看看我是否猜对了。
Would the container know to pass this instance to services down the call chain?
如果您打算在调用的其他地方使用相同的实例,那么可以通过将 MapBean
设为 @ApplicationScoped
bean(或者,EJB @Singleton
).
it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical.
这里我认为它看起来神奇的原因是 SLSB 在 CDI 方面是一个 @Dependent
bean。您可能知道,CDI 总是为依赖 bean 注入点创建新实例。例如。是的,每次调用都会得到一个不同的 SLS/Dependent bean 实例。
也许其他一些范围更适合您?喜欢 @RequestScoped
或 @SessionScoped
?没有更多细节很难说。
First, the job needs to also @Inject
the MapBean
so that it can be loaded with job-specific data before the Conversation.begin()
method is called. Would the container know to pass this instance to services down the call chain?
是的,因为 MapBean
是 @ConversationScoped
,它在从 conversation.begin()
到 conversation.end()
的持续时间内绑定到调用链。您可以将 @ConversationScoped
(以及 @RequestScoped
和 @SessionScoped
)视为 ThreadLocal
中的实例 - 虽然每个线程都存在它们的一个实例,但每个实例都与该单个实例相关联线程。
Related to that, according to this question Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? it should be possible to inject a @ConservationScoped
bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
如果你看到这个图案和我上面解释的一样,那就没有你想象的那么神奇了。 SLSB 确实获得了一个单独的实例,但不仅仅是任何实例,该实例属于调用 SLSB 的范围。
除了您发布的 link,另请参阅 。
我测试了与您发布的代码类似的代码,它按预期工作 - MapBean
与在整个调用过程中注入的代码相同。请注意两件事:
BatchJob
也是 @ConversationScoped
但没有实现 Serializable
,这将不允许 bean 钝化。
data
没有初始化,所以你会在runJob()
. 中得到一个NPE
有人问过类似的问题,但没有完全解决我想做的事情。我们有一个较旧的基于 Seam 2.x 的应用程序,它带有我们正在转换为 CDI 的批处理作业框架。作业框架使用 Seam 上下文对象来发起对话。作业框架还加载一个特定于作业的数据持有者(基本上是一个 Map),然后可以通过 Seam Contexts 对象访问链下的任何服务,包括来自 SLSB 的数据持有者。其中一些服务可以更新地图,以便作业状态可以更改并在记录之间进行检测。
看起来在 CDI 中,作业将 @Inject
一个 CDI 对话对象,并手动 begin/end 对话。我们还将定义一个新的 ConversationScoped
bean 来保存 Map (MapBean
)。我不清楚的是两件事:
首先,该作业还需要@Inject MapBean
,以便它可以在调用 Conversation.begin() 方法之前加载特定于作业的数据。容器会知道将此实例传递给调用链下的服务吗?
与此相关,根据这个问题Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? 应该可以将ConservationScoped
bean 注入到SLSB 中,但这似乎有点神奇。如果 SLSB 被不同的进程(工作、UI 调用等)使用,它是否为每个调用获得单独的实例?
为澄清和简化 class 结构而编辑:
MapBean
需要是一个 ConversationScoped
对象,包含特定 instance/run 作业的数据。
@ConversationScoped
public class MapBean implements Serializable {
private Map<String, Object> data;
// accessors
public Object getData(String key) {
return data.get(key);
}
public void setData(String key, Object value) {
data.put(key, value);
}
}
这份工作是 ConversationScoped
:
@ConversationScoped
public class BatchJob {
@Inject private MapBean mapBean;
@Inject private Conversation conversation;
@Inject private JobProcessingBean jobProcessingBean;
public void runJob() {
try {
conversation.begin();
mapBean.setData("key", "value"); // is this MapBean instance now bound to the conversation?
jobProcessingBean.doWork();
} catch (Exception e) {
// catch something
} finally {
conversation.end();
}
}
}
作业可能会调用 SLSB,MapBean
的当前对话范围实例需要可用:
@Stateless
public class JobProcessingBean {
@Inject private MapBean mapBean;
public void doWork() {
// when this is called, is "mapBean" the current conversation instance?
Object value = mapBean.getData("key");
}
}
我们的工作和 SLSB 框架非常复杂,SLSB 可以调用许多其他服务或本地实例化的业务逻辑 classes,并且每个都需要访问对话范围 MapBean
.
没有任何代码示例,我将不得不做一些猜测,所以让我们看看我是否猜对了。
Would the container know to pass this instance to services down the call chain?
如果您打算在调用的其他地方使用相同的实例,那么可以通过将 MapBean
设为 @ApplicationScoped
bean(或者,EJB @Singleton
).
it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical.
这里我认为它看起来神奇的原因是 SLSB 在 CDI 方面是一个 @Dependent
bean。您可能知道,CDI 总是为依赖 bean 注入点创建新实例。例如。是的,每次调用都会得到一个不同的 SLS/Dependent bean 实例。
也许其他一些范围更适合您?喜欢 @RequestScoped
或 @SessionScoped
?没有更多细节很难说。
First, the job needs to also
@Inject
theMapBean
so that it can be loaded with job-specific data before theConversation.begin()
method is called. Would the container know to pass this instance to services down the call chain?
是的,因为 MapBean
是 @ConversationScoped
,它在从 conversation.begin()
到 conversation.end()
的持续时间内绑定到调用链。您可以将 @ConversationScoped
(以及 @RequestScoped
和 @SessionScoped
)视为 ThreadLocal
中的实例 - 虽然每个线程都存在它们的一个实例,但每个实例都与该单个实例相关联线程。
Related to that, according to this question Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? it should be possible to inject a
@ConservationScoped
bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
如果你看到这个图案和我上面解释的一样,那就没有你想象的那么神奇了。 SLSB 确实获得了一个单独的实例,但不仅仅是任何实例,该实例属于调用 SLSB 的范围。
除了您发布的 link,另请参阅
我测试了与您发布的代码类似的代码,它按预期工作 - MapBean
与在整个调用过程中注入的代码相同。请注意两件事:
BatchJob
也是@ConversationScoped
但没有实现Serializable
,这将不允许 bean 钝化。data
没有初始化,所以你会在runJob()
. 中得到一个NPE