Search code examples
javadependency-injectioncdiweld

How to find CDI beans with a custom annotation with parameters?


I have a Wildfly 10 application in which I have created a custom @Qualifer annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,METHOD,PARAMETER,TYPE})
@Qualifier
public @interface DbType {
    /**
     * If this DbType is part of the initialization process for an existing DB
     */
    boolean init() default false;
}

I then have a couple of producer methods:

@Produces
@DbType
public MyBean createBean1(){
  return new MyBean();
}

@Produces
@DbType(init=true)
public MyBean createBean2(){
  return new MyBean(true);
}

In my code, I want to programatically retrieve all beans with the given annotation, but not sure how.

    Instance<MyBean> configs = CDI.current().select(MyBean.class, new AnnotationLiteral<DbType >() {});

will return both beans.

How can I specify in my CDI.current().select() that I only want beans with the qualifer @MyType(init=true)?


Solution

  • You need create a class that extends AnnotationLiteral and implements your annotation. An example is given by the documentation of AnnotationLiteral:

    Supports inline instantiation of annotation type instances.

    An instance of an annotation type may be obtained by subclassing AnnotationLiteral.

    public abstract class PayByQualifier extends AnnotationLiteral<PayBy> implements PayBy {
    }
    
    PayBy payByCheque = new PayByQualifier() {
        public PaymentMethod value() {
            return CHEQUE;
        }
    };
    

    In your case, it might look something like:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({FIELD,METHOD,PARAMETER,TYPE})
    @Qualifier
    public @interface DbType {
        /**
         * If this DbType is part of the initialization process for an existing DB
         */
        boolean init() default false;
    
        class Literal extends AnnotationLiteral<DbType> implements DbType {
    
            public static Literal INIT = new Literal(true);
            public static Literal NO_INIT = new Literal(false);
    
            private final boolean init;
    
            private Literal(boolean init) {
                this.init = init;
            }
    
            @Override
            public boolean init() {
                return init;
            }
    
        }
    
    }
    

    And then use it:

    Instance<MyBean> configs = CDI.current().select(MyBean.class, DbType.Literal.INIT);