简体   繁体   中英

CDI producer fallback (ContextNotActiveException)

We'd like to use CDI to implement some cross cutting functionality like logging audit information, authorization etc. In order to do that we'd have some bean that contains an injection point for the current user like this:

class AuditLogger {
  @Inject
  private Instance<User> currentUser;

  public void log(Whatever data) {
    User userWhoTriggeredIt = currentUser.get();
    ...
  }
}

Additionally we have a session scoped user manager bean that contains a producer method:

@SessionScoped
class UserManager {
  @Produces
  @Current
  public User getCurrentUser() {
    //get and return the user
  }
}

This works fine as long as we have a session context up and running (ie within our web application). However, there are situations in which there is no session context, ie when certain web services or MBeans are called. In those situations we'd like to have a fallback producer that provides a generic "application" user.

So basically in AuditLogger we'd like to get the user from the session scoped UserManager unless we're running outside a session in which case we'd use the fallback "application" user.

However, this seems to be somewhat hard using Weld 1.x (we're running in a JBoss 7.2 and can't upgrade right now, although we'd consider that if CDI 1.2 provides a solution).

A few options that we tried so far:

  • use Instance.select( new AnnotationLiteral<Current>() {}).isUnsatisfied() to check whether there is a producer available. This seems to return false, however, so when we try to call get() we still get the ContextNotActiveException
  • iterate over Instance, ie for( User u : currentUser ) , but since there is no qualifier information it's hard to distinguish the correct one when we have a session (Update: the tests were misleading, we get that exception here as well)
  • not tried but it seems possible though somewhat hacky: catch that exception and try the fallback

Any ideas on the canonical/least hacky/error prone way to do this?

As documented in Obtaining the active Context for a scope , you can write:

@Inject
BeanManager bm;

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

Unfortunately, this only permits to retrieve the active context and throws a ContextNotActiveException exception if no active context object exists for the scope type.

Thus, even though the Context.isActive() method exists, it is not possible to reliably check whether a context is active without relying on the ContextNotActiveException exception mechanism.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM