WELD-001408 Неудовлетворенные зависимости при внедрении EJB, реализующих интерфейсы

Вот такая ситуация.

У меня есть следующие интерфейсы:

public interface Parent { }
public interface ChildOne extends Parent { }
public interface ChildTwo extends Parent { }

и 2 EJB:

@Stateless
public class FirstBean implements ChildOne { }

@Stateless
public class SecondBean implements ChildTwo { }

А также этот компонент CDI:

@Named
@SessionScoped
public class TestController implements Serializable {

    @Inject
    private FirstBean firstBean;

    @Inject
    private SecondBean secondBean;
}

При попытке развернуть это на Glassfish 3.1 я получаю следующее исключение:

Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [@Default] at injection point [[field] @Inject private com.test.controllers.TestController.firstBean]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [FirstBean] 
with qualifiers [@Default] at injection point [[field] @Inject private com.test.controllers.TestController.firstBean]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:305)

Когда оба EJB реализуют интерфейс Parent, исключение одно и то же.
Кроме того, я попытался добавить квалификаторы, но это ничего не изменило.


person jFrenetic    schedule 27.01.2012    source источник


Ответы (3)


Я просто поигрался с вашей конструкцией, прочитал немного сварного шва document и обнаружил следующее.

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

@Inject
private ChildOne firstBean;

Доступ к реализации, даже если интерфейс определен, возможен только для простых управляемых компонентов CDI (классов без аннотаций @ Stateless / @ Stateful). Так что избавьтесь от аннотации, и все получится.

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

person Roland Tiefenbrunner    schedule 28.01.2012
comment
Благодаря тонну! Действительно хорошее объяснение! И я уже столкнулся с этим исключением Unable to convert ejbRef for ejb..., я просто не знал, что это известная проблема. - person jFrenetic; 28.01.2012
comment
Я проверил еще раз. Я попытался внедрить эти EJB-компоненты по ссылке на интерфейс, как вы предложили. И я все еще получаю это Unsatisfied dependencies... исключение во время развертывания. Я даже аннотировал интерфейсы @Local. Тем не менее, это не работает. - person jFrenetic; 28.01.2012
comment
Я попробовал это вчера, и это сработало для меня, кроме того, это имеет некоторый смысл. В любом случае, я попробую еще раз, когда вернусь домой. - person Roland Tiefenbrunner; 28.01.2012
comment
Еще раз спасибо за помощь. Я даже загрузил свое тестовое приложение (с исходным кодом), чтобы упростить задачу. Вы можете получить его здесь - person jFrenetic; 28.01.2012
comment
Извините, ваш пример определенно работает. Я просто совершенно забыл добавить beans.xml в свой ejb-jar (однако у меня был один для CDI @Named beans). - person jFrenetic; 28.01.2012
comment
О, и я думаю, что нашел еще одно более элегантное решение. Пометка моих EJB аннотацией @LocalBean позволяет мне вводить их по классу реализации, и исключение, о котором вы упомянули при вызове метода абстрактного класса, не происходит. - person jFrenetic; 28.01.2012
comment
Думаю, более элегантный вариант зависит от варианта использования :) Просто имейте в виду недостаток. Следите за тем, чтобы не раскрывать реализации часто изменяющихся классов. Кроме того, вы потеряете возможность обмениваться реализацией во время выполнения, что возможно с использованием CDI (методы производителя, альтернативы). Однако, конечно, не всегда необходимо программировать с использованием интерфейса, особенно в Java EE, как объясняется здесь: oracle.com/technetwork/articles/java/intondemand-1444614.html - person Roland Tiefenbrunner; 30.01.2012

Лучше поздно, чем никогда:

Добавление аннотации к SLSB с помощью @LocalBean у меня работает с JBoss AS 7.1.1. Мне не нравится идея создания интерфейса без дополнительных затрат.

Используя ваш пример:

@Stateless
@LocalBean
public class FirstBean implements ChildOne { }

@Stateless
@LocalBean
public class SecondBean implements ChildTwo { }
person atamanroman    schedule 22.06.2012
comment
@atamanroman, вы знаете, переносится ли этот метод? Поскольку определение для @LocalBean означает, что компонент session предоставляет представление без интерфейса, и, поскольку здесь это не сеансовый компонент, будет ли он работать везде и правильно ли это? - person Anthony O.; 22.11.2012
comment
@AnthonyO. Сессионные компоненты без сохранения состояния и сеансовые компоненты с сохранением состояния являются сеансовыми компонентами. Так что да, это именно то, что требует стандарт. - person atamanroman; 22.11.2012

Вы пробовали использовать аннотацию @EJB, а не аннотацию CDI @inject?

E.g.

@Named
@SessionScoped
public class TestController implements Serializable {

    @EJB
    private FirstBean firstBean;

    @EJB
    private SecondBean secondBean;
}
person juan.villa    schedule 27.01.2012
comment
Нет, не видел. Спасибо за идею, но я очень хочу понять, что я здесь делаю не так. - person jFrenetic; 27.01.2012
comment
У вас есть beans.xml в вашем META-INF? - person juan.villa; 28.01.2012
comment
Я уверен. Если бы у меня его не было, WELD не обнаружил бы мои bean-компоненты CDI и не выполнял бы проверку во время развертывания. - person jFrenetic; 28.01.2012