Как правильно использовать @Alternative для клиентских реализаций

РЕДАКТИРОВАТЬ: я изменил точки инъекции CDI с использования @EJB на использование @Inject, как указано в моих комментариях ниже. Просто к сведению.


У меня есть два проекта EAR, оба в основном одинаковые. Единственная разница, которую они имеют, - это несколько специфичных для клиента реализаций, где это необходимо. У меня проблема, однако.

Вот что у меня есть:

EAR #1 содержит следующие модули:

web.war 
ejb-default.jar
ejb-client-1.jar

EAR #2 содержит следующие модули:

web.war
ejb-default.jar
ejb-client-2.jar

В ejb-default содержится следующее:

@Singleton
@Startup
public class ApplicationSettingsBean implements ApplicationSettingsBeanLocal

Теперь для EAR #1 файл ejb-client-1.jar может быть пустым, поэтому любые EJB-инъекции должны использовать то, что есть в ejb-default.

Однако для EAR #2 я хочу заменить реализацию по умолчанию на конкретную для клиента. Например:

@Singleton
@Startup    
@Alternative
public class ApplicationSettingsBean implements ApplicationSettingsBeanLocal {

Я также создал следующую запись beans.xml в ejb-client-2:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <alternatives>
        <class>com.client2.ejb.ApplicationSettingsBean</class>
    </alternatives>
</beans>

Я ожидаю, что реализация @Alternative будет внедрена, когда такая реализация существует. Если в точке внедрения указан @Default, то должна быть внедрена реализация по умолчанию (ejb-default). Хотя так не бывает:

    // Inject the alternative implementation
    @Inject
    private ApplicationSettingsBeanLocal appSettingsBean;

С этим CDI вводится значение по умолчанию, а не альтернатива. Это не ожидаемое поведение.


person John Manko    schedule 04.10.2012    source источник
comment
Итак, я изменил все свои точки инъекции с @EJB на @Inject, как рекомендовал Гэвин Кинг на другом форуме, и это устранило ошибку. Однако это не решило проблему. Теперь реализация @Alternative игнорируется в пользу реализации @Default (подразумеваемая аннотация). Я дважды проверил файл beans.xml во второй банке EJB, и он выглядит хорошо.   -  person John Manko    schedule 05.10.2012
comment
seamframework.org/107780.lace   -  person John Manko    schedule 05.10.2012
comment
Вышеприведенный код был изменен, чтобы отразить проблему.   -  person John Manko    schedule 05.10.2012


Ответы (2)


beans.xml, где вы должны указать альтернативы, должен находиться внутри ejb-default.jar, а не в ejb-client-2.jar< /эм>.

Спецификация CDI (1.1, но применимая и к предыдущей реализации) гласит в главе 5.1, что:

Альтернатива недоступна для внедрения, поиска или разрешения EL для классов или страниц JSP/JSF в модуле, если модуль не является архивом компонентов и альтернатива явно не выбрана в этом архиве компонентов.

Другими словами, вы должны выбрать альтернативу в том же модуле класса, который использует компонент.

person Gaetano Piazzolla    schedule 12.11.2014
comment
Была та же проблема, модуль WAR ссылался на простой JAR, который содержит некоторые bean-компоненты без сохранения состояния. Интерфейс одного из них внедряется в ресурс REST в WAR через CDI. Не сработало, хотя ИТ-тесты в JAR были в порядке и стоили мне 3 часов исследований, пока я не нашел ваш пост. Спасибо, чувак, теперь я могу пойти на Рождество;) - person hecko84; 22.12.2015

Для тех, кому интересно, что происходит, это смешивает внедрение CDI и EJB (EE5). Вот почему возникает первая ошибка. Альтернативы - это идея CDI, и @EJB их не распознает.

Причина по умолчанию вместо альтернативы заключается в том, что это квалификатор, используемый при инъекции (альтернативы не имеют подразумеваемого @Default). По сути, это говорит CDI, что я точно знаю, какой экземпляр мне нужен, это экземпляр с теми же квалификаторами, которые я использую при внедрении. Лучший способ справиться с такими вещами — просто использовать @Inject без каких-либо квалификаторов, если только вы ТОЧНО не знаете, какой экземпляр вам нужен, и вы добавляете эти квалификаторы в инъекцию (те же, что и в реализующем классе).

person LightGuard    schedule 04.10.2012
comment
Да, прямо. Мне потребовалась минута, чтобы понять, что @Alternative предназначен только для @Inject точек инъекции и недоступен для @EJB. Однако после внесения необходимых изменений класс @Alternative по-прежнему не распознается по сравнению с реализацией по умолчанию. Любая идея, почему это может быть? - person John Manko; 05.10.2012
comment
Какой сервер приложений вы используете? Кроме того, где ваши файлы beans.xml, особенно с альтернативой? Где это вызывается, война? - person LightGuard; 06.10.2012
comment
Я использую Glassfish 3.1.2. У меня есть пустой beans.xml в ejb-default.jar, который содержит реализацию по умолчанию. У меня есть beans.xml (с соответствующей альтернативной разметкой) в ejb-client-2.jar, который содержит реализацию @Alternative. Я внедряю EJB (используя @Inject) из управляемого компонента в WAR. - person John Manko; 06.10.2012
comment
Я думаю, что это проблема, призвание с войны. Война ничего не знает об альтернативе. Просто ради смеха добавьте альтернативу войне и посмотрите, что получится. Если вы не на 3.1.2.2, вы также можете попробовать это и посмотреть, поможет ли это. - person LightGuard; 08.10.2012
comment
Я попробую это и отчитаюсь. - person John Manko; 12.10.2012