Можно ли внедрить реализацию EJB, а не его интерфейс, используя CDI?

Моя конфигурация: Wildfly 8.2.0, Weld

Можно ли вводить в bean-компоненте, а не в его интерфейсе в CDI?

@Stateless
class Bean implements IBean {
...
}    

interface IBean {
...
}

@SessionScoped
class Scoped {
   @Inject
   Bean bean; //Fail

   @Inject
   IBean iBean; //OK
}

РЕДАКТИРОВАТЬ:

Больше информации в моем предыдущем вопросе: EJB без сохранения состояния внедряет интерфейсный сбой

2 ответа

Решение

Да, вы можете, но когда EJB внедряет бизнес-представление, единственное представляемое вами бизнес-представление - это @Local посмотреть, который является по умолчанию при реализации интерфейса (IBean в вашем случае это локальный бизнес интерфейс). Итак, если вы хотите внедрить сам компонент, вам нужно сообщить контейнеру, что вы используете представление без интерфейса.

В вашем примере, если вы все еще хотите реализовать свой интерфейс и внедрить Bean Вы должны использовать @LocalBean аннотация, которая означает, что бин предоставляет представление без интерфейса:

@Stateless
@LocalBean // <-- no-interface view
class Bean implements IBean {
...
}  

interface IBean {
....
}

@SessionScoped
class Scoped {
   @Inject
   Bean bean; //Should be OK
}

Или, если вы не хотите реализовывать какой-либо интерфейс, компонент по умолчанию определяет представление без интерфейса:

@Stateless
class Bean {
...
}  

@SessionScoped
class Scoped {
   @Inject
   Bean bean; //OK
}

Смотрите также:

Похоже, вы получили неясный ответ на свой предыдущий вопрос, и на самом деле весь этот вопрос является продолжением этого вопроса.

Вообще говоря, CDI позволяет вводить как интерфейс, так и impl для управляемых компонентов CDI. Это не относится к EJB. Когда EJB реализует интерфейс, это становится его бизнес-интерфейсом. Действительными являются только объявленные там методы. Эффективно, ваш Bean Класс определяет только то, как эти методы работают, и фактически не существует как компонент в вашей среде выполнения.

Так что нет, при использовании EJB вы не можете внедрить реализацию, только интерфейс. Если вы действительно хотите это сделать, я бы отошел от EJB.

Одна из возможных причин, по которой вы можете не захотеть использовать интерфейс для внедрения EJB, может заключаться в том, что у вас может быть много EJB, реализующих этот интерфейс, и ваш контейнер EJB может жаловаться на то, что он не может разрешить двусмысленность того, какой конкретный EJB должен быть введенным в данном контексте. Если это так, вы можете легко указать имя конкретного класса EJB, реализующего общий интерфейс, используяjavax.inject.Named аннотация, как показано ниже:

@SessionScoped
class Scoped {
   @Named("Bean")
   IBean iBean;
}
Другие вопросы по тегам