1 Reply Latest reply on Mar 13, 2012 4:38 PM by dastraub

    JBoss 7 CDI in a custom login module..

    andersbohn

      Unable to get JBoss 7 to inject beans into my custom login module, I found a trick to do programmatic injection:

       

      http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e5286

       

      In my module i put:

       

      {code}

      public class CustomLoginModule extends AbstractServerLoginModule {

       

        @Inject

        AuthService authService;

       

        @Override

        public boolean login() throws LoginException {

          if (authService == null) {

            CdiHelper.programmaticInjection(CustomLoginModule.class, this);

          }

       

         authService.authenticate()...

      {code}

      The helper:

       

      {code}

      import javax.enterprise.context.spi.CreationalContext;

      import javax.enterprise.inject.spi.AnnotatedType;

      import javax.enterprise.inject.spi.BeanManager;

      import javax.enterprise.inject.spi.InjectionTarget;

      import javax.naming.InitialContext;

      import javax.naming.NamingException;

       

      public class CdiHelper {

        // Nicked from: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e5286

        public static  void programmaticInjection(Class clazz, T injectionObject) throws NamingException {

          InitialContext initialContext = new InitialContext();

          Object lookup = initialContext.lookup("java:comp/BeanManager");

          BeanManager beanManager = (BeanManager) lookup;

          AnnotatedType annotatedType = beanManager.createAnnotatedType(clazz);

          InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);

          CreationalContext creationalContext = beanManager.createCreationalContext(null);

          injectionTarget.inject(injectionObject, creationalContext);

          creationalContext.release();

        }

      }

      {code}

       

      This appears to work whereever the container misses my classes. Not sure if it's kosher, thou - any comments welcome.

        • 1. Re: JBoss 7 CDI in a custom login module..
          dastraub

          I've implemented something similar (today ) :

          - I created a JBoss Extension that dynamically installs/register login modules (I found them via a custom annotation). But you can do the same stuff also in a CDI-Extension. For creating and registering login modules, see source code of jboss-as-security.

          So my login module looks like this :

           

           

          @LoginDomain(name = "test1", principal = TestPrincipal.class)
          @LoginModuleDescription(flag = FlagType.REQUIRED)
          public class Test1LoginModule implements LoginModule {
          
          
                  @Inject BeanForLoginModule beanForLoginModule;
          
                  @Override
                  public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
          
                         ...
          
          

           

          - for the Loginmodule-Class itself I use the delegate pattern, that means instead of registering the login module I register a wrapper.

          - in the "initalize" method of the wrapper I create the original login module bean progammatically, and get a full intialized instance from cdi :

           

           

          public class CdiDelegatingLoginModule implements LoginModule {
          
          
                  private LoginModule delegate;
          
                  public void initialize(Subject subject, CallbackHandler callbackHandler,
                                  Map<String, ?> sharedState, Map<String, ?> options) {
          
                          String lmClassName = (String) options.get("code");
                          delegate = createCdiInstance(lmClassName);
                          delegate.initialize(subject, callbackHandler, sharedState, options);
                  }
          
          
                  private LoginModule createCdiInstance(String className) {
                          try {
                                  Class<?> loginModuleClass = Thread.currentThread().getContextClassLoader().loadClass(className);
                                  BeanManager beanManager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
                                  Bean<LoginModule> loginModuleBean = (Bean<LoginModule>) beanManager.getBeans(loginModuleClass).iterator().next();
                                  return (LoginModule) beanManager.getReference(loginModuleBean, 
                                                  loginModuleClass, beanManager.createCreationalContext(loginModuleBean));
                          } catch (Exception x) {
                                  throw new IllegalStateException(x);
                          }
                  }
          
          ...
          
          
          

           

          It's currently in draft status ...

           

          But your solution looks good for everything what's need injection, thanks for the hint !