java ee6: override CDI alternative

牧云@^-^@ 提交于 2019-12-09 13:53:17

问题


I'm using Glassfish 3.1.2.2, java ee6.

I have a library in which a class uses CDI to get a helper class. I would like in one specific project where I use that library, to override that CDI dependency and force the library to use my own helper class, specific to that project instead. I can modify the library at will, but by default it should use its default helper class, so that behaviour doesn't change for other users of the library.

This should be the perfect application of the @Alternative CDI pattern. I made a java interface for the helper class API; There is a default implementation in the library, then I can use the <alternatives> tag in the beans.xml; in the project where I want to override the behaviour, I would specify my own implementation of the helper in the beans.xml of that specific project.

Except it doesn't work. It's apparently impossible to override the alternatives behaviour from the library outside of the library in CDI 1.0 (java ee6).

And so no matter what I specify in the beans.xml of my outer project, CDI keeps selecting the bean defined in the library.

I considered going through a producer but I didn't find how to get CDI to give to the producer the EntityManager as a parameter, so that I can pass it forward to the helper class. In this project, we normally inject the EntityManager using the @PersistenceContext annotation.

Any ideas on how to override that CDI injection from the outer project?


回答1:


You could write a Portable Extension to do this. Listen to the ProcessAnnotatedType event and replace the AnnotatedType with your own. You could use the Apache DeltaSpike BeanBuilder class to help with this.




回答2:


Apache DeltaSpike provides a feature called global-alternatives which bypasses those stupid BDA rules. It's tested with a lot of containers and you don't have do care about the details manually. With OpenWebBeans you don't have this issue at all and some versions of Weld support it via a beans.xml in WEB-INF instead of META-INF.




回答3:


The solution I used in the end is related to the suggestion from LightGuard: I have CDI extension, and I override processAnnotatedType(), as suggested.

However instead of replacing the AnnotatedType (which I'm not sure how I could do), I use the technique described there: http://docs.jboss.org/weld/reference/latest/en-US/html/extend.html#d0e4800

And veto the the bean that was defined in the library.

Now that the default implementation is veto'ed, if I put my own bean in my application, that's the one that CDI chooses.

To make this work also in Arquillian integration tests, you must add this call to your archive:

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

The javax.enterprise.inject.spi.Extension resource does not need to have effect in Arquillian (see SHRINKWRAP-266).



来源:https://stackoverflow.com/questions/18575174/java-ee6-override-cdi-alternative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!