Java EE 7 検証環境構築(5) JBoss Toolsが生成したサンプルソースのCDIを確認する
- Java EE 7 検証環境構築(1) WildFly + JBoss Tools で EARプロジェクトを作成し Arquillian で ユニットテストをグリーンにするところまで
- Java EE 7 検証環境構築(2) WildFly に DataSourceを作成
- Java EE 7 検証環境構築(3) JPAからMySQLに接続するユニットテストをArquillianで実行
- Java EE 7 検証環境構築(4) Java EE での DI(Dependency Injection) および CDI(Contexts and Dependency Injection)をながめる
- Java EE 7 検証環境構築(5) JBoss Toolsが生成したサンプルソースのCDIを確認する
- Java EE 7 検証環境構築(6) JPA エンティティの作成と挿入
- Java EE 7 検証環境構築(7) JPA 問い合わせ(1) 名前付きクエリを使ってみる。テストでトランザクションも意識する
- Java EE 7 検証環境構築(8) JPA 問い合わせ(2) 動的クエリとCriteria API を試す
- Java EE 7 検証環境構築(9) jBatch 概要をおさえる
- Java EE 7 検証環境構築(10) JBoss Tools で作成した EARプロジェクトをJava EE 6 から 7 に変更する
- Java EE 7 検証環境構築(11) jBatch用 プロジェクトの作成を行う
- Java EE 7 検証環境構築(12) jBatch 簡易サンプル作成と Arquillian でユニットテスト
- Java EE 7 検証環境構築(13) jBatch REST サービス経由で実行する
- Java EE 7 検証環境構築(14) WildFly の管理をGUIで行う
- Java EE 7 検証環境構築(15) WildFly を サービスとして設定する(Windows/Linux)
- Java EE 7 検証環境構築(16) WildFly と Apache を mod_jk で連携させる(Widows)
CDI の概要は何となく理解した。後は、どう使うのか。
まず、JBoss Tools で自動作成された EAR Project のサービスクラスを確認してみる。
@Stateless public class MemberRegistration { @Inject private Logger log; @Inject private EntityManager em; @Inject private EventmemberEventSrc; public void register(Member member) throws Exception { log.info("Registering " + member.getName()); em.persist(member); memberEventSrc.fire(member); } }
さて、ここでインジェクトされている、Logger や EntityManager はどこで登録されているのかしら?
事前定義 Bean
事前定義された、Bean。もしかして事前定義されている?
http://docs.oracle.com/javaee/7/tutorial/doc/cdi-adv004.htm#CJGHGDBA
事前定義 | Resource or CDI Bean | インジェクション例 |
UserTransaction | Resource | @Resource UserTransaction transaction; |
Principal | Resource | @Resource Principal principal; |
Validator | Resource | @Resource Validator validator; |
ValidatorFactory | Resource | @Resource ValidatorFactory factory; |
HttpServletRequest | CDI Bean | @Inject HttpServletRequest req; |
HttpSession | CDI Bean | @Inject HttpSession session; |
ServletContext | CDI Bean | @Inject ServletContext context; |
の中には、ないようだ。
CDIが管理しているBeanをのぞいてみる
で、CDIが管理しているBeanの一覧を確認してみる。
Any bean may obtain an instance of BeanManager by injecting it:
@Inject BeanManager manager;
Arquillian テストケースで、BeanManager が管理しているBean一覧を出力
@RunWith(Arquillian.class) public class BeanManagerTest { @Deployment public static Archive<?> createTestArchive() { return ShrinkWrap.create(WebArchive.class, "test.war") .addClasses(Resources.class) .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") ; } @Inject Logger log; @Inject BeanManager manager; @Test public void testListAllBeans() throws Exception { @SuppressWarnings("serial") Set<?>> beans = manager.getBeans(Object.class, new AnnotationLiteral (){}); for (Bean<?> bean: beans) { log.info(String.format( "BeanName=%s,Scope=%s", bean.getBeanClass().getName(), bean.getScope().getName())); } } }
結果(Sort & Unique 済み)。
BeanName=com.sun.faces.application.view.ViewScopeExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=com.sun.faces.application.view.ViewScopedCDIEventFireHelperImpl,Scope=javax.enterprise.context.Dependent BeanName=com.sun.faces.flow.FlowCDIEventFireHelperImpl,Scope=javax.enterprise.context.Dependent BeanName=com.sun.faces.flow.FlowCDIExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=com.sun.faces.flow.FlowDiscoveryCDIExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=com.sun.faces.flow.FlowDiscoveryCDIHelper,Scope=javax.enterprise.context.Dependent BeanName=info.typea.tallarico.test.BeanManagerTest,Scope=javax.enterprise.context.Dependent BeanName=info.typea.tallarico.util.Resources,Scope=javax.enterprise.context.Dependent BeanName=javax.enterprise.inject.spi.Bean,Scope=javax.enterprise.context.Dependent BeanName=javax.enterprise.inject.spi.Decorator,Scope=javax.enterprise.context.Dependent BeanName=javax.enterprise.inject.spi.Interceptor,Scope=javax.enterprise.context.Dependent BeanName=org.hibernate.validator.internal.cdi.ValidationExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.hibernate.validator.internal.engine.ValidatorFactoryImpl,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.hibernate.validator.internal.engine.ValidatorImpl,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.jberet.creation.BatchBeanProducer,Scope=javax.enterprise.context.Dependent BeanName=org.jberet.creation.BatchCDIExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.jboss.arquillian.protocol.servlet.runner.ServletTestRunner,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.arquillian.testenricher.cdi.container.CDIExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.jboss.resteasy.cdi.ResteasyCdiExtension,Scope=javax.enterprise.context.ApplicationScoped BeanName=org.jboss.weld.bean.builtin.BeanManagerProxy,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.bean.builtin.EventMetadataBean,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.bean.builtin.InjectionPointBean,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.bean.builtin.InstanceImpl,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.bean.builtin.ee.HttpServletRequestBean,Scope=javax.enterprise.context.RequestScoped BeanName=org.jboss.weld.bean.builtin.ee.HttpSessionBean,Scope=javax.enterprise.context.SessionScoped BeanName=org.jboss.weld.bean.builtin.ee.PrincipalBean,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.bean.builtin.ee.ServletContextBean,Scope=javax.enterprise.context.RequestScoped BeanName=org.jboss.weld.bean.builtin.ee.UserTransactionBean,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.context.conversation.ConversationImpl,Scope=javax.enterprise.context.RequestScoped BeanName=org.jboss.weld.context.http.HttpSessionDestructionContext,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.event.EventImpl,Scope=javax.enterprise.context.Dependent BeanName=org.jboss.weld.manager.BeanManagerImpl,Scope=javax.enterprise.context.Dependent
Logger も、EntityManger も管理Beanにない。。。
んーどういう理屈?
@Deployment public static Archive<?> createTestArchive() { return ShrinkWrap.create(WebArchive.class, "test.war") .addClasses(Resources.class) .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") ; }
Arquillian テストクラスをもう一度よく見てみる。
beans.xml は、CDI を有効化するための、デプロイメント記述子。
ん、Resource.class は?ソースを確認。
/** * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans * * <p> * Example injection on a managed bean field: * </p> * * <pre> * @Inject * private EntityManager em; * </pre> */ public class Resources { // use @SuppressWarnings to tell IDE to ignore warnings about field not being referenced directly @SuppressWarnings("unused") @Produces @PersistenceContext private EntityManager em; @Produces public Logger produceLog(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); } }
おーあった、あった。Logger と EntityManager のファクトリメソッドをもった Resourceクラス(JBoss Tools のプロジェクトで自動生成されたクラス)は、BeanManagerに管理されてたわ。
納得。