java ee6: переопределить альтернативу CDI

Я использую Glassfish 3.1.2.2, java ee6.

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

Это должно быть идеальным применением шаблона @Alternative CDI. Я сделал java-интерфейс для API вспомогательного класса; В библиотеке есть реализация по умолчанию, тогда я могу использовать тег <alternatives> в beans.xml; в проекте, где я хочу переопределить поведение, я бы указал свою собственную реализацию помощника в beans.xml этого конкретного проекта.

За исключением того, что это не работает. Это очевидно невозможно переопределить поведение альтернатив из библиотеки вне библиотеки в CDI 1.0 (java ee6).

И поэтому независимо от того, что я указываю в beans.xml моего внешнего проекта, CDI продолжает выбирать bean-компонент, определенный в библиотеке.

Я рассматривал использование производителя, но не нашел, как заставить CDI передать производителю EntityManager в качестве параметра , чтобы я мог передать его вспомогательному классу. В этом проекте мы обычно внедряем EntityManager, используя аннотацию @PersistenceContext.

Любые идеи о том, как переопределить эту инъекцию CDI из внешнего проекта?


person Emmanuel Touzery    schedule 02.09.2013    source источник


Ответы (3)


Вы можете написать переносимое расширение, чтобы сделать это. Прослушайте событие ProcessAnnotatedType и замените AnnotatedType своим собственным. Вы можете использовать класс Apache DeltaSpike BeanBuilder, чтобы помочь с этим.

person LightGuard    schedule 03.09.2013
comment
Как насчет аннотации @Priority? Разве это не сработает в этом случае или это только JEE 7? - person albogdano; 20.09.2013
comment
Хм? В CDI 1.0 или 1.1 нет аннотации @Priority - person LightGuard; 20.09.2013
comment
В JEE 7 есть, я прочитал документы . Затем вы можете написать @Alternative @Priority(Interceptor.Priority.APPLICATION+10) public class X и переопределить bean-компонент по умолчанию, используя только аннотации. - person albogdano; 20.09.2013
comment
Ах, это, вероятно, исходит из спецификации Interceptor, это не часть спецификации CDI. - person LightGuard; 20.09.2013

Apache DeltaSpike предоставляет функцию, называемую глобальными альтернативами, которая обходит эти глупые правила BDA. Он протестирован с большим количеством контейнеров, и вам не нужно заботиться о деталях вручную. С OpenWebBeans у вас вообще нет этой проблемы, и некоторые версии Weld поддерживают ее через beans.xml в WEB-INF вместо META-INF.

person Dar Whi    schedule 08.09.2013

Решение, которое я использовал в конце, связано с предложением LightGuard: у меня есть расширение CDI, и я переопределяю processAnnotatedType(), как было предложено.

Однако вместо замены AnnotatedType (что я не уверен, как я мог бы сделать) я использую метод, описанный здесь: http://docs.jboss.org/weld/reference/latest/en-US/html/extend.html#d0e4800

И наложить вето на bean-компонент, который был определен в библиотеке.

Теперь, когда на реализацию по умолчанию наложено вето, если я поставлю свой собственный bean-компонент в свое приложение, это будет тот, который выберет CDI.

Чтобы это работало и в интеграционных тестах Arquillian, вы должны добавить этот вызов в свой архив:

addAsServiceProvider(Extension.class, <CDI extension class name>.class)

Ресурс javax.enterprise.inject.spi.Extension не должен действовать в Arquillian (см. SHRINKWRAP-266).

person Emmanuel Touzery    schedule 03.09.2013