Внедрение произвольного перечисления с помощью WELD CDI

Я пытаюсь предоставить возможность ввести произвольное перечисление с учетом точки инъекции и строкового значения (которое получается в методе Produces)

Произвольный означает, что если у меня есть enum My и enum Your, я хотел бы внедрить их оба или любой другой с тем же методом производителя.

Поэтому я попробовал несколько подходов: 1.

@Produces
@MyConfigAnnotation
Enum getArbitraryEnum(InjectionPoint point) {
    ...
    // get string representation, 
    // instantiate enum using point
    return Enum.valueOf((Class<Enum>)injectionPoint.getAnnotated().getClass(), enumValue);
}

2. Я изменил возвращаемый тип на Object.

В обоих случаях я получаю следующее исключение, вызванное: org.jboss.weld.exceptions.DeploymentException: WELD-001408: неудовлетворенные зависимости для типа TestEnum с квалификаторами @X в точке внедрения [BackedAnnotatedField] @Inject @X pathToMyField.testEnum2

Итак, есть ли способ создать метод Produces, который сможет создавать произвольное перечисление.


person Anjenson    schedule 25.05.2015    source источник
comment
Можете ли вы предоставить больше информации о вашем методе производителя? Какой контейнер у вас запущен?   -  person John Ament    schedule 26.05.2015
comment
@JohnAment Я добавил способ создания экземпляра enum. Но это вряд ли имеет значение, поскольку кажется, что приложение не работает. Что касается контейнера, я использую Jboss Weld, или вы имели в виду другое?   -  person Anjenson    schedule 26.05.2015


Ответы (1)


Вам понадобятся уникальные комбинации экземпляра и квалификатора, поскольку без квалификатора weld не знает, какого производителя вызвать.

Есть способ достижения динамической привязки перечисления, я нашел его в комментариях к этой статье: http://www.ocpsoft.org/java/how-to-inject-enum-values-into-cdi-beans/

public class InjectedObject {
   private MyEnum e1;
   private MyEnum e2;
   private MyEnum e3;

   @Inject
   public InjectedObject(@Config("ONE") MyEnum e1, @Config("TWO") MyEnum e2,     @Config("THREE") MyEnum e3)   {
      this.e1 = e1;
      this.e2 = e2;
      this.e3 = e3;
   }


   /**
    * A producer is required in order to {@link Inject} an Enum
    */
   @Produces
   @Config
   public static MyEnum getEnum(InjectionPoint ip) {
       String name = null;

       /**
        * Iterate over all Qualifiers of the Injection Point to find our configuration and save the config value
        */
       for(Annotation a : ip.getQualifiers()) {
           if(a instanceof Config) {
               name = ((Config) a).value();
           }
       }

       /**
        * Iterate over all enum values to match them against our configuration value
        */
       for(MyEnum me : MyEnum.values()) {
           if(me.toString().equals(name)) {
               return me;
           }
       }

      return null;
   }

    /**
    * Our enum
    */
   public enum MyEnum {      ONE, TWO, FOO   }

   @Qualifier
   @Target({ TYPE, METHOD, PARAMETER, FIELD })
   @Retention(RUNTIME)
   @Documented
   public @interface Config {
       @Nonbinding String value() default "";
   }
}

Интересной частью, конечно же, является настраиваемый квалификатор с необязательным значением, заставляющий CDI выбирать правильный метод производителя.

Все это сказано ... поскольку вам нужен дополнительный квалификатор, который каким-то образом содержит имя перечисления, которое вы хотите ввести ... зачем вообще вводить?

person Jan Galinski    schedule 27.05.2015
comment
Извините за вводящий в заблуждение код, но я действительно использую квалификатор (отредактированный вопрос). Конечно, спасибо за ответ, но ключевое слово вопроса - произвольное перечисление. Это означает, что независимо от того, какое перечисление вводится, оно вводится одним и тем же методом производителя. Однако в вашем примере вы создаете точный класс перечисления MyEnum - person Anjenson; 28.05.2015