Java EE 7 検証環境構築(5) JBoss Toolsが生成したサンプルソースのCDIを確認する

  1. Java EE 7 検証環境構築(1) WildFly + JBoss Tools で EARプロジェクトを作成し Arquillian で ユニットテストをグリーンにするところまで
  2. Java EE 7 検証環境構築(2) WildFly に DataSourceを作成
  3. Java EE 7 検証環境構築(3) JPAからMySQLに接続するユニットテストをArquillianで実行
  4. Java EE 7 検証環境構築(4) Java EE での DI(Dependency Injection) および CDI(Contexts and Dependency Injection)をながめる
  5. Java EE 7 検証環境構築(5) JBoss Toolsが生成したサンプルソースのCDIを確認する
  6. Java EE 7 検証環境構築(6) JPA エンティティの作成と挿入
  7. Java EE 7 検証環境構築(7) JPA 問い合わせ(1) 名前付きクエリを使ってみる。テストでトランザクションも意識する
  8. Java EE 7 検証環境構築(8) JPA 問い合わせ(2) 動的クエリとCriteria API を試す
  9. Java EE 7 検証環境構築(9) jBatch 概要をおさえる
  10. Java EE 7 検証環境構築(10) JBoss Tools で作成した EARプロジェクトをJava EE 6 から 7 に変更する
  11. Java EE 7 検証環境構築(11) jBatch用 プロジェクトの作成を行う
  12. Java EE 7 検証環境構築(12) jBatch 簡易サンプル作成と Arquillian でユニットテスト
  13. Java EE 7 検証環境構築(13) jBatch REST サービス経由で実行する
  14. Java EE 7 検証環境構築(14) WildFly の管理をGUIで行う
  15. Java EE 7 検証環境構築(15) WildFly を サービスとして設定する(Windows/Linux)
  16. Java EE 7 検証環境構築(16) WildFly と Apache を mod_jk で連携させる(Widows)

CDI の参照実装 JBoss Weld

CDI の概要は何となく理解した。後は、どう使うのか。

まず、JBoss Tools で自動作成された EAR Project のサービスクラスを確認してみる。

@Stateless
public class MemberRegistration {

    @Inject
    private Logger log;

    @Inject
    private EntityManager em;

    @Inject
    private Event memberEventSrc;

    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の一覧を確認してみる。

BeanManager

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に管理されてたわ。

納得。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です