我们希望使用CDI来实现一些交叉功能,例如记录审核信息,授权等。为此,我们需要一些bean,其中包含当前用户的注入点,如下所示:
class AuditLogger {
@Inject
private Instance<User> currentUser;
public void log(Whatever data) {
User userWhoTriggeredIt = currentUser.get();
...
}
}
此外,我们有一个会话范围内的用户管理器bean,其中包含一个生产者方法:
@SessionScoped
class UserManager {
@Produces
@Current
public User getCurrentUser() {
//get and return the user
}
}
只要我们有一个会话上下文并且正在运行(即在我们的Web应用程序中),它就可以正常工作。但是,在某些情况下没有会话上下文,即当某些Web服务或MBean被调用时。在这种情况下,我们希望有一个备用生产者来提供通用的“应用程序”用户。
因此,基本上,在
AuditLogger
中,我们希望从会话范围UserManager
中获取用户,除非我们在会话外部运行,在这种情况下,我们将使用后备“应用程序”用户。但是,使用Weld 1.x似乎有点困难(我们正在JBoss 7.2中运行,并且现在无法升级,尽管我们认为如果CDI 1.2提供了解决方案)。
到目前为止,我们尝试了几种选择:
使用
Instance.select( new AnnotationLiteral<Current>() {}).isUnsatisfied()
检查是否有生产者。但是,这似乎返回false,因此,当我们尝试调用get()
时,仍然会得到ContextNotActiveException
遍历实例(即
for( User u : currentUser )
),但是由于没有限定符信息,因此当我们进行会话时很难区分正确的信息(更新:测试有误导性,我们在这里也遇到了异常)尚未尝试,但似乎有些怪异:捕获该异常并尝试后备
关于规范/最少hacky /容易出错的方法有什么想法吗?
最佳答案
如Obtaining the active Context for a scope中所述,您可以编写:
@Inject
BeanManager bm;
Context context = bm.getContext(SessionScoped.class);
不幸的是,如果范围类型不存在活动上下文对象,则这仅允许检索活动上下文并抛出
ContextNotActiveException
异常。因此,即使存在
Context.isActive()
方法,也不能不依赖ContextNotActiveException
异常机制来可靠地检查上下文是否处于活动状态。