トップ 一覧 ping 検索 ヘルプ RSS ログイン

Java EE JNDI ENC 注入の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!Java EE JNDI ENC 注入
[Java EE]

{{amazon 4873115086}}

*アプリケーションサーバーにデプロイされたすべてのEJBコンテナは、Enterprise Naming Context(ENC) と呼ばれる独自の内部レジストリを持っている
*これはJNDIで実装されている

!!!グローバルJNDI
*EJB3.1ではSLSB、SFSBのビューは以下の構文のグローバルJNDIで入手出来る必要がある
 java:global[/app-name]/module-name/bean-name [!FQN]
,項目,内容
,app-name,アプリケーション(またはEAR)名(オプション)
,module-name,モジュール(JARまたはWAR)名
,FQN,完全修飾インターフェース名

!!利点
*ベンダにかかわらず、同じ場所でEJBを見つけることができ移植性がある
!!改善できる点
*ルックアップコードはベンダー固有の JNDI Context の取得に依存
*キャストが必要で、タイプセーフではない
*自分でJNDI名を作成するため、間違えやすい
!!EJBコンテナは一連のタイプセーフな注入メカニズムを提供
*多くの場合、利用可能な参照を取得するのに必要なのは以下だけ
 @EJB
 MyEJBLocalBusiness bean;
!!!JNDI ENC
*EJB3.xでは、ENCが強化され、JNDI ENC参照をBeanクラスのフィールドに直接注入できるようになった
*このためにアノテーションが主に利用されるがm,XMLデプロイメント記述子も利用可能
""EJB、インターフェースへの参照、JMSキューまたはトピックの送信先、JMS接続ファクトリ、データソース、JCAリソース、プリミティブ型など、様々なものをENCに登録できる
!!JNDI ENCへの投入方法
*2つの異なる方法で設定できる
!XMLによる投入
*ejb-local-ref:MyEJBがMyEJB2のローカルビジネスインターフェースへの参照を必要としていることをEJBコンテナに通知
*ejbs/referenceToMyEJB2 という名前でJNDI ENC に登録
 <ejb-jar>
   <enterprise-bean>
     <session>
       <ejb-name>MyEJB</ejb-name>
       <ejb-local-ref>
         <ejb-ref-name>ejbs/referenceToMyEJB2</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <local>org.ejb3book.example.MyEJB2LocalBusiness</local>
         <ejb-link>MyEJB2</ejb-link>
       </ejb-local-ref>
     </session>
   </enterprise-bean>
 </ejb-jar>
!アノテーションによる設定
*アノテーションで定義された情報でJNDI ENCに投入
 @Stateful(name="MyEJB")
 @EJB(name="ejbs/referenceToMyEJB2",beanInterface=MyEJB2LocalBusiness.class,beanName="MyEBJ2")
 public class MyEJBBean implements MyEJBLocalBusiness {
   :
 }
!!ENCからの参照方法
*JNDI ENCに登録したものはすべて、java:comp/env コンテキストから名前で検索できます
*compはcomponent を表している
 try {
   javax.naming.InitialContext ctx = new InitialContext();
   bean = (MyEJB2LocalBusiness)ctx.lookup("java:comp/env/ejbs/referenceToMyEJB2");
  } catch(javax.naming.NamingException ne) {
    :
  }
!EJBContext
*EJBContextにはENCルックアップメソッドがあり、チェック例外を発生させず、相対名を使う
*SessionContext、MessageDrivenContext いずれも EJBContextを拡張
 @Resource
 private javax.ejb.SessionContext ctx;
  
 public void hoge() {
   MyEJBLocalBusiness bean = ctx.lookup("ejbs/referenceToMyEJB2");
 }
!アノテーションによる注入
*ENCルックアップの代わりに、EJB参照をメンバ変数に直接注入できる
 @EJB
 private MyEJB2LocalBusiness bean;
*セッターメソッドを使った注入もサポート
*フィールドに直接注入するより冗長だが、単体テストで簡単にモックできるというメリット
 @EJB
 public void setBean(final MyEJB2LocalBusiness bean) {
   this.bean = bean;
 }
!デフォルトENC名
*Beanクラスのフィールドやセッターメソッドにアノテーションをつけると、注入された要素のためにJNDI ENCにエントリーを作成することにもなる
*これらはすべての環境アノテーションで起こるが、@EBJでは、注入アノテーションのname()属性が指定されていると、参照はその名前でENCに格納される
*名前が指定されない場合、ENC名はアノテーションづけされたフィールドやメソッドの完全修飾クラス名とフィールド名やメソッドのベース名から付けられる
::例
 org.ejb3book.example.MyEJBBean/otherBean
::EJB参照(上記例は以下で検索できる)
 java:comp/env/org.ejb3book.example.MyEJBBean/otherBean
!XMLによる注入
*フィールドの初期化にアノテーションを利用したくない場合、ejb-jar.xmlデプロイメント記述子で<jnjection-target> を利用できる
 <ejb-jar>
   <enterprise-bean>
     <session>
       <ejb-name>MyEJB</ejb-name>
       <ejb-local-ref>
         <ejb-ref-name>ejbs/referenceToMyEJB2</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <local>org.ejb3book.example.MyEJB2LocalBusiness</local>
         <ejb-link>MyEJB2</ejb-link>
         <injection-target>
           <injection-target-class>
             org.ejb3book.example.MyEJBBean
           </injection-target-class>
           <injection-target-name>otherBean</injection-target-name>
         </injection-target>
       </ejb-local-ref>
     </session>
   </enterprise-bean>
 </ejb-jar>
!XMLによるオーバーライド
*注入アノテーションを使うと、Beanクラスのコードに構成をハードコーディングすることになるとみなされる場合もある
*EJB仕様ではXMLデプロイメント記述子を使って注入アノテーションをオーバーライドできる
""XMLは常にアノテーションメタデータよりも優先される。XMLはハードコーディングされたアノテーションを再構成する手段を提供する
!注入と継承
*Beanクラスをクラス階層に含めることができる
*注入アノテーションは特定の注入規則に従う

 public class Base {
   private SomeInf bean;
  
   @EJB(beanName="SomeEJB")
   public void someMethod(SomeInf bean) {
     this.bean = bean;
   }
 }

 @Stateless
 public class MySessionBean extends Base implements MySessionLocalBusiness {
 }
*上記例で、Baseを継承する ステートレスセッションBeanは、Baseクラスの someMethodに適切なリソースを注入する。

 @Stateless
 public class MySessionBean extends Base implements MySessionLocalBusiness {
   private SomeInf bean;
   @EJB(beanName="AnotherEJB")
   public void someMethod(SomeInf bean) {
     this.bean = bean;
   }
 }
*このようにすると、SomeEJBではなく、AnotherEJBが注入される
""someMethod が private の場合、Base には SomeEJBが注入される
!!参照の注入と型