Search code examples
javajavabeanscdiinjectqualifiers

Passing parameter while injecting and retrieving using InjectionPoint


This is relevant to one asked in Pass Parameter to Instance of @Inject Bean

but i need some different approach for my implemenation.

For passing parameter while injecting, a custom qualifier can be created like :

@Qualifier
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface SendInject{
    @Nonbinding
    int value() default 0; // int value will be store here
}

The class to be injected need to be annotated with @SendInject as:

@SendInject
public class Receiver{

   int in;

   private int extractValue(InjectionPoint ip) {
        for (Annotation annotation : ip.getQualifiers()) {
            if (annotation.annotationType().equals(SendInject.class))
                return ((SendInject) annotation).value();
       }
       throw new IllegalStateException("No @Initialized on InjectionPoint");
   }

   @Inject
   public Receiver(InjectionPoint ip) {
        this.in= extractValue(ip);
   }
   ..........
  }

And while injecting Receiver all the members needs to use the custom qualifier @SendInject . like:

  public class Sender{

      @Inject
      @SendInject(9)
      Receiver receiver;
   ..................

    }

I do not want to use @SendInject everytime i inject Receiver because its not necessary to pass parameter at few points for my implementation. Is there any way that i can customize the custom qualifier while injecting Recevier so that it can be used only when some parameter need to be passed?

I tried doing it so, but getting Ambiguous dependency error while deploying my component.


Solution

  • That means you want to have two types of Receiver (one is @SendInject and one is non-@SendInject) . You should let CDI to know how to create them.

    For example , you can use a producer method to create @SendInjectReceiver and use bean 's constructor to create non-@SendInject Receiver :

    public class Receiver {
    
        int in;
    
        public Receiver() {
        }
    
        public Receiver(int in) {
            this.in = in;
        }
    
        private static int extractValue(InjectionPoint ip) {
            for (Annotation annotation : ip.getQualifiers()) {
                if (annotation.annotationType().equals(SendInject.class))
                    return ((SendInject) annotation).value();
            }
        }
    
        @Produces
        @SendInject
        public static Receiver createSendInjectReceiver(InjectionPoint ip) {
            int in = extractValue(ip);
            return new Receiver(in);
        }
    }
    

    And inject different Receiver type as usual :

    public class Client{
          /************************************
           This receiver is created by constructor
          **************************************/
          @Inject
          Receiver receiver1;
    
          /************************************
          This receiver is created by producer method  
           **************************************/
          @Inject
          @SendInject(999)
          Receiver receiver2;
    }