CDI生产者回退(ContextNotActiveException)

时间:2015-04-09 16:13:57

标签: java cdi

我们希望使用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时。在这些情况下,我们希望有一个后备制作人,提供一个通用的应用程序&#34;用户。

所以基本上在AuditLogger我们希望让用户从会话范围UserManager开始,除非我们在会话外运行,在这种情况下我们会使用后备&#34;应用&#34;用户。

然而,使用Weld 1.x似乎有些困难(我们现在正在JBoss 7.2中运行并且现在无法升级,尽管我们认为如果CDI 1.2提供了溶液)。

到目前为止我们尝试了几个选项:

  • 使用Instance.select( new AnnotationLiteral<Current>() {}).isUnsatisfied()检查是否有可用的生产者。但是,这似乎是错误的,所以当我们尝试致电get()时,我们仍然会得到ContextNotActiveException
  • 迭代实例,即for( User u : currentUser ),但由于没有限定符信息,当我们有一个会话时,很难区分正确的一个(更新:测试有误导性,我们在这里得到了这个例外) ())
  • 没有尝试,但似乎有可能虽然有点hacky:抓住那个例外并尝试后备

有关规范/最少hacky /错误的方法的任何想法吗?

1 个答案:

答案 0 :(得分:1)

Obtaining the active Context for a scope中所述,您可以写:

@Inject
BeanManager bm;

Context context = bm.getContext(SessionScoped.class);

不幸的是,这只允许检索活动上下文,如果作用域类型不存在活动的上下文对象,则会抛出ContextNotActiveException异常。

因此,即使存在Context.isActive()方法,也不可能在不依赖ContextNotActiveException异常机制的情况下可靠地检查上下文是否处于活动状态。