2 Replies Latest reply on Nov 30, 2016 4:02 AM by maciekjboss

    Can Weld Cdi omit @Inject annotation in favour of HK2

    maciekjboss

      Hello

      Discussion is moved from here. I really wanted to make things simple but it seems that it is not possible to not give more details.

       

      I am operating on glassfish 4.1.1 using WELD-000900: 2.2.13 (Final), developing JAX-RS endpoint with Jersey.

      Having class:

       

      @Path(/test)

      public class A {
        
      @Inject B hk2object;
        
      @Inject C cdiObject;
      }

       

      I found out that @Inject annotation is also used by HK2 DI engine avaliable on glassfish -  jerseyExample HK2example

      I also read that Cdi (JSR-299 Context and Dependency Injection for Java) in Weld is just more complex version of JSR 330: Dependency Injection for Java in HK2.

      I thought I can take advantage of this and create HK2 Factory to produce my B object example

      and thereafter inject it using @Inject.

      The problem is that when deploying *.war Weld checks all @Inject annotations and determines wheather it is able to perform injection.

      Assume I have my HK2 factory ready and I dont want to mangle it to Cdi Producer method.

       

      Then when implementing solution from referenced stackoverflow post:

       

      public CustomInjection(InjectionTarget<T> originalInjectionTarget, BeanManager beanManager) {
         this.wrappedInjectionTarget = originalInjectionTarget;
         this.beanManager = beanManager;
      }

       

      @Override
                  public void inject(T instance, CreationalContext<T> ctx) {
        l.trace("Injecting into {}", instance);
      //....create my own HK2 object. Can it be just new B() for example ?!  
        locator =ServiceLocatorUtilities.createAndPopulateServiceLocator();  
        B b = locator.createAndInitialize(B.class);
      
        l.trace("First injecting standard dependencies {}", instance);
        wrappedInjectionTarget.inject(instance, ctx);
         // dispose created by CDI B type object ?! - seems messy but works 
        manageBViaReflection((x, y, z) -> x.set(y, z), instance, b);
      }
      

      line 8 injects B object produced by Cdi not HK2 into bean instance.

      Next I have to dispose it manually (probably that is not elegant) because B type object has to be disposed from the definition and next set field B b of bean instance of type A to Object B produced by HK2.

       

      Actually this is not a problem - I can handle producing B object using CDI. I was just wondering wheather can I use @Inject connected to HK2 engine not Weld.

       

       

       

       

        • 1. Re: Can Weld Cdi omit @Inject annotation in favour of HK2
          mkouba

          Hi maciek,

          this is a little bit tangled. So the lifecycle of the JAX-RS endpoint is managed by Jersey. I assume that Jersey treats the endpoint as a CDI bean and so if you want to make use of HK2 injection you have to do perform HK2 injection manually. From my point of view, the simplest thing to do is to create a CDI producer method for B:

          @Vetoed // Instruct CDI not to create a bean for B, another way would be for example ProcessBeanAttributes.veto()
          class B {
          }
          
          class BProducer {
            
            // Instruct CDI to use the return value of this method for any injection point with required type B and default qualifier
            @Dependent
            @Produces
            B produceB() {
              return ServiceLocatorUtilities.createAndPopulateServiceLocator().createAndInitialize(B.class);
            }
          }
          
          • 2. Re: Can Weld Cdi omit @Inject annotation in favour of HK2
            maciekjboss

            I gave it a try and its that what I wanted. Very good and swift solution.