Пользовательские квалификаторы в интерфейсе не работают при внедрении

Проблема:

Привет, у меня проблема с java EE, я должен использовать аннотацию, такую ​​​​как @Inject @Stateless и т. д., но я не могу найти решение, после прочтения большого количества документации и примеров и т. д. кажется, что мой код должен работать, но точно нет. Итак, проблема в том, что у меня есть пользовательские квалификаторы на интерфейсе, подобном этому

 @Qualifier
 @Retention(RUNTIME)
 @Target({METHOD, FIELD, PARAMETER, TYPE})
 public @interface BudgetsDs {
 }

и я хочу ввести его в другой объект как поле члена, подобное этому

@Dependent
public class BudgetService  {

@BudgetsDs
@Inject
DataSource budgetsDS;

... some getter, setter , etcetc...

}

я прошел через это

https://docs.oracle.com/javaee/6/tutorial/doc/gjbck.html

и другой вид документации, подобный этому. Я пробовал с @EJB, @Stateless, но это не работает. Я думаю, что в настоящее время мне не хватает большой вещи в аннотации, поэтому, если у вас есть хорошие учебные пособия, хорошие советы или объяснения, я хочу их услышать. Я не прошу полного ответа, но я хотел бы иметь хоть какую-то подсказку. Любой может помочь.

Изменить: точная ошибка указана в строке

@BudgetsDs
@Inject
DataSource budgetsDS;

BudgetDS бросает неудовлетворенную зависимость: ни один bean-компонент не соответствует точке внедрения

Edit2: решение

1) Я реализовал новый класс ResourceProducer. Как предложил Джон Амент, я использую @Produces и @Resource(name="jdbc/myDataSource") для каждого источника данных, который мне нужен.

public class ResourceProducer {

@Produces
@BudgetsDs
@Resource(name="jdbc/BudgetsDs")
public DataSource budgetsDs;

@Produces
@OtherDs
@Resource(name="jdbc/OtherDs")
public DataSource otherDs;

...  

}

2) Различные настраиваемые квалификаторы для каждого подключения

 // In a file 
 @Qualifier
 @Retention(RUNTIME)
 @Target({METHOD, FIELD, PARAMETER, TYPE})
 public @interface BudgetsDs {
 }

 // In a another file
 @Qualifier
 @Retention(RUNTIME)
 @Target({METHOD, FIELD, PARAMETER, TYPE})
 public @interface OtherDs {
 }

3) Таким образом, вставка работает хорошо, и я могу внедрить другой источник данных, куда захочу, например:

@Dependent
public class BudgetService  {

@BudgetsDs
@Inject
DataSource budgetsDS;

@OtherDs
@Inject
DataSource otherDs;
... some getter, setter , etcetc...

}

Ниже приведено другое решение, которое тоже работает.

Спасибо aribeiro и John Ament. Мой первый вопрос о переполнении стека, на который очень хорошо ответило сообщество.


person Koraxos    schedule 22.04.2016    source источник
comment
Есть ли в вашей реализации DataSource аннотация @BudgetsDs?   -  person aribeiro    schedule 22.04.2016
comment
Нет, я просто использую его непосредственно в своем классе BudgetService,   -  person Koraxos    schedule 22.04.2016
comment
Чтобы контейнер внедрил правильную реализацию вашего DataSource, вам также необходимо поместить свой квалификатор в реализацию. Если вы заметили, в упомянутой вами ссылке квалификатор @Informal помещается в начало класса InformalGreeting. Затем, как вы можете видеть в docs.oracle.com/javaee/6 /tutorial/doc/gjban.html, в классе Printer вводится приветствие: @Inject @Informal Greeting greeting;.   -  person aribeiro    schedule 22.04.2016
comment
Таким образом, решением было бы реализовать класс, который расширяет   -  person Koraxos    schedule 22.04.2016
comment
Нет. Если у вас нет нескольких реализаций, просто удалите квалификатор и просто @Inject компонент.   -  person aribeiro    schedule 22.04.2016
comment
Дело в том, что у меня будет несколько DataSource, в связи с тем, что мне понадобится доступ к разным базам данных. Поэтому я должен использовать настраиваемые квалификаторы для реализации различных подключений, у меня также есть класс ResourceProducer, который получит @Resource   -  person Koraxos    schedule 22.04.2016
comment
Тогда да, вам нужно расширить свой класс DataSource. Взгляните на ответ, который я опубликовал.   -  person aribeiro    schedule 22.04.2016
comment
Если DataSource — это просто источник данных JDBC, то, что вы здесь делаете, должно работать. Можете ли вы включить полную трассировку стека NPE, который вы получаете?   -  person John Ament    schedule 23.04.2016


Ответы (1)


Ошибка, которую вы получаете, возникает из-за того, что контейнер не знает, как сопоставить созданный вами квалификатор с любой реализацией любого типа компонента.

Как указано в документации:

Квалификатор – это аннотация, которую вы применяете к bean-компоненту

Следовательно, чтобы преодолеть упомянутую ошибку, вам необходимо применить соответствующий квалификатор к каждой реализации DataSource:

@BudgetsDs
public class BudgetDataSource extends DataSource {
    (...)
}

@OtherDs
public class OtherDataSource extends DataSource {
    (...)
}

Затем контейнер сможет перейти к правильной реализации, когда вы вводите свои bean-компоненты:

@Dependent
public class BudgetService  {

    @BudgetsDs
    @Inject
    DataSource budgetsDS;

    (...)
}

@Dependent
public class OtherService {

    @Inject
    @OtherDs
    DataSource otherDS;

    (...)
}

Кстати, я заметил, что вы следуете документации по Java EE 6. Я бы посоветовал вам ознакомиться с последней документацией по Java EE.

person aribeiro    schedule 22.04.2016
comment
Хорошо, это то, о чем я думал, но я не был уверен, что попробую, просто нужно поесть. Я проголосовал за, но у меня недостаточно репутации, чтобы изменить отображаемый балл вашего сообщения - person Koraxos; 22.04.2016
comment
Этот ответ неверен. вы можете сделать то же самое с полями/методами производителя. - person John Ament; 23.04.2016
comment
@JohnAment, почему ответ неверен и какие преимущества вы получаете в этом случае от наличия продюсеров? - person aribeiro; 23.04.2016