| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

Java EE JNDI ENC 注入

提供: MyMemoWiki
ナビゲーションに移動 検索に移動

Java EE JNDI ENC 注入

Java EE |

  • アプリケーションサーバーにデプロイされたすべての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デプロイメント記述子も利用可能

<blockquote>EJB、インターフェースへの参照、JMSキューまたはトピックの送信先、JMS接続ファクトリ、データソース、JCAリソース、プリミティブ型など、様々なものをENCに登録できる</blockquote>

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デプロイメント記述子を使って注入アノテーションをオーバーライドできる

<blockquote>XMLは常にアノテーションメタデータよりも優先される。XMLはハードコーディングされたアノテーションを再構成する手段を提供する</blockquote>

注入と継承

  • 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が注入される

<blockquote>someMethod が private の場合、Base には SomeEJBが注入される</blockquote>

参照の注入と型