「Java EE JNDI ENC 注入」の版間の差分
ナビゲーションに移動
検索に移動
| 1行目: | 1行目: | ||
| − | ==Java EE JNDI ENC 注入== | + | ==[[Java EE JNDI ENC 注入]]== |
[[Java EE]] | | [[Java EE]] | | ||
{{amazon|4873115086}} | {{amazon|4873115086}} | ||
| − | * | + | *アプリケーションサーバーにデプロイされたすべての[[EJB]]コンテナは、Enterprise Naming Context(ENC) と呼ばれる独自の内部レジストリを持っている |
*これはJNDIで実装されている | *これはJNDIで実装されている | ||
==グローバルJNDI== | ==グローバルJNDI== | ||
| − | * | + | *[[EJB]]3.1ではSLSB、SFSBのビューは以下の構文のグローバルJNDIで入手出来る必要がある |
java:global[/app-name]/module-name/bean-name [!FQN] | java:global[/app-name]/module-name/bean-name [!FQN] | ||
{|class="wikitable" | {|class="wikitable" | ||
| 15行目: | 15行目: | ||
|- | |- | ||
|app-name | |app-name | ||
| − | |アプリケーション( | + | |アプリケーション(またはEA[[R]])名(オプション) |
|- | |- | ||
|module-name | |module-name | ||
| − | |モジュール( | + | |モジュール(JA[[R]]またはWA[[R]])名 |
|- | |- | ||
|FQN | |FQN | ||
| 26行目: | 26行目: | ||
===利点=== | ===利点=== | ||
| − | * | + | *ベンダにかかわらず、同じ場所で[[EJB]]を見つけることができ移植性がある |
===改善できる点=== | ===改善できる点=== | ||
*ルックアップコードはベンダー固有の JNDI Context の取得に依存 | *ルックアップコードはベンダー固有の JNDI Context の取得に依存 | ||
*キャストが必要で、タイプセーフではない | *キャストが必要で、タイプセーフではない | ||
*自分でJNDI名を作成するため、間違えやすい | *自分でJNDI名を作成するため、間違えやすい | ||
| − | === | + | ===[[EJB]]コンテナは一連のタイプセーフな注入メカニズムを提供=== |
*多くの場合、利用可能な参照を取得するのに必要なのは以下だけ | *多くの場合、利用可能な参照を取得するのに必要なのは以下だけ | ||
| − | @EJB | + | @[[EJB]] |
| − | + | My[[EJB]]LocalBusiness bean; | |
==JNDI ENC== | ==JNDI ENC== | ||
| − | * | + | *[[EJB]]3.xでは、ENCが強化され、JNDI ENC参照をBeanクラスのフィールドに直接注入できるようになった |
| − | * | + | *このためにアノテーションが主に利用されるがm,[[XML]]デプロイメント記述子も利用可能 |
| − | <blockquote> | + | <blockquote>[[EJB]]、インターフェースへの参照、JMSキューまたはトピックの送信先、JMS接続ファクトリ、データソース、JCAリソース、プリミティブ型など、様々なものをENCに登録できる</blockquote> |
===JNDI ENCへの投入方法=== | ===JNDI ENCへの投入方法=== | ||
*2つの異なる方法で設定できる | *2つの異なる方法で設定できる | ||
| − | ==== | + | ====[[XML]]による投入==== |
| − | *ejb-local-ref: | + | *ejb-local-ref:My[[EJB]]がMy[[EJB]]2のローカルビジネスインターフェースへの参照を必要としていることを[[EJB]]コンテナに通知 |
| − | *ejbs/ | + | *ejbs/referenceToMy[[EJB]]2 という名前でJNDI ENC に登録 |
<ejb-jar> | <ejb-jar> | ||
<enterprise-bean> | <enterprise-bean> | ||
<session> | <session> | ||
| − | <ejb-name> | + | <ejb-name>My[[EJB]]</ejb-name> |
<ejb-local-ref> | <ejb-local-ref> | ||
| − | <ejb-ref-name>ejbs/ | + | <ejb-ref-name>ejbs/referenceToMy[[EJB]]2</ejb-ref-name> |
<ejb-ref-type>Session</ejb-ref-type> | <ejb-ref-type>Session</ejb-ref-type> | ||
| − | <local>org.ejb3book.example. | + | <local>org.ejb3book.example.My[[EJB]]2LocalBusiness</local> |
| − | <ejb-link> | + | <ejb-link>My[[EJB]]2</ejb-link> |
</ejb-local-ref> | </ejb-local-ref> | ||
</session> | </session> | ||
| 59行目: | 59行目: | ||
====アノテーションによる設定==== | ====アノテーションによる設定==== | ||
*アノテーションで定義された情報でJNDI ENCに投入 | *アノテーションで定義された情報でJNDI ENCに投入 | ||
| − | @Stateful(name=" | + | @Stateful(name="My[[EJB]]") |
| − | @EJB(name="ejbs/ | + | @[[EJB]](name="ejbs/referenceToMy[[EJB]]2",beanInterface=My[[EJB]]2LocalBusiness.class,beanName="MyEBJ2") |
| − | public class | + | public class My[[EJB]]Bean implements My[[EJB]]LocalBusiness { |
: | : | ||
} | } | ||
| 69行目: | 69行目: | ||
try { | try { | ||
javax.naming.InitialContext ctx = new InitialContext(); | javax.naming.InitialContext ctx = new InitialContext(); | ||
| − | bean = ( | + | bean = (My[[EJB]]2LocalBusiness)ctx.lookup("java:comp/env/ejbs/referenceToMy[[EJB]]2"); |
} catch(javax.naming.NamingException ne) { | } catch(javax.naming.NamingException ne) { | ||
: | : | ||
} | } | ||
| − | ==== | + | ====[[EJB]]Context==== |
| − | * | + | *[[EJB]]ContextにはENCルックアップメソッドがあり、チェック例外を発生させず、相対名を使う |
| − | *SessionContext、MessageDrivenContext いずれも | + | *SessionContext、MessageDrivenContext いずれも [[EJB]]Contextを拡張 |
| − | @ | + | @[[R]]esource |
private javax.ejb.SessionContext ctx; | private javax.ejb.SessionContext ctx; | ||
public void hoge() { | public void hoge() { | ||
| − | + | My[[EJB]]LocalBusiness bean = ctx.lookup("ejbs/referenceToMy[[EJB]]2"); | |
} | } | ||
====アノテーションによる注入==== | ====アノテーションによる注入==== | ||
| − | * | + | *ENCルックアップの代わりに、[[EJB]]参照をメンバ変数に直接注入できる |
| − | @EJB | + | @[[EJB]] |
| − | private | + | private My[[EJB]]2LocalBusiness bean; |
*セッターメソッドを使った注入もサポート | *セッターメソッドを使った注入もサポート | ||
*フィールドに直接注入するより冗長だが、単体テストで簡単にモックできるというメリット | *フィールドに直接注入するより冗長だが、単体テストで簡単にモックできるというメリット | ||
| − | @EJB | + | @[[EJB]] |
| − | public void setBean(final | + | public void setBean(final My[[EJB]]2LocalBusiness bean) { |
this.bean = bean; | this.bean = bean; | ||
} | } | ||
| 97行目: | 97行目: | ||
*名前が指定されない場合、ENC名はアノテーションづけされたフィールドやメソッドの完全修飾クラス名とフィールド名やメソッドのベース名から付けられる | *名前が指定されない場合、ENC名はアノテーションづけされたフィールドやメソッドの完全修飾クラス名とフィールド名やメソッドのベース名から付けられる | ||
=====例===== | =====例===== | ||
| − | org.ejb3book.example. | + | org.ejb3book.example.My[[EJB]]Bean/otherBean |
| − | ===== | + | =====[[EJB]]参照(上記例は以下で検索できる)===== |
| − | java:comp/env/org.ejb3book.example. | + | java:comp/env/org.ejb3book.example.My[[EJB]]Bean/otherBean |
| − | ==== | + | ====[[XML]]による注入==== |
*フィールドの初期化にアノテーションを利用したくない場合、ejb-jar.xmlデプロイメント記述子で<jnjection-target> を利用できる | *フィールドの初期化にアノテーションを利用したくない場合、ejb-jar.xmlデプロイメント記述子で<jnjection-target> を利用できる | ||
<ejb-jar> | <ejb-jar> | ||
<enterprise-bean> | <enterprise-bean> | ||
<session> | <session> | ||
| − | <ejb-name> | + | <ejb-name>My[[EJB]]</ejb-name> |
<ejb-local-ref> | <ejb-local-ref> | ||
| − | <ejb-ref-name>ejbs/ | + | <ejb-ref-name>ejbs/referenceToMy[[EJB]]2</ejb-ref-name> |
<ejb-ref-type>Session</ejb-ref-type> | <ejb-ref-type>Session</ejb-ref-type> | ||
| − | <local>org.ejb3book.example. | + | <local>org.ejb3book.example.My[[EJB]]2LocalBusiness</local> |
| − | <ejb-link> | + | <ejb-link>My[[EJB]]2</ejb-link> |
<injection-target> | <injection-target> | ||
<injection-target-class> | <injection-target-class> | ||
| − | org.ejb3book.example. | + | org.ejb3book.example.My[[EJB]]Bean |
</injection-target-class> | </injection-target-class> | ||
<injection-target-name>otherBean</injection-target-name> | <injection-target-name>otherBean</injection-target-name> | ||
| 121行目: | 121行目: | ||
</enterprise-bean> | </enterprise-bean> | ||
</ejb-jar> | </ejb-jar> | ||
| − | ==== | + | ====[[XML]]によるオーバーライド==== |
*注入アノテーションを使うと、Beanクラスのコードに構成をハードコーディングすることになるとみなされる場合もある | *注入アノテーションを使うと、Beanクラスのコードに構成をハードコーディングすることになるとみなされる場合もある | ||
| − | * | + | *EJB仕様では[[XML]]デプロイメント記述子を使って注入アノテーションをオーバーライドできる |
| − | <blockquote> | + | <blockquote>[[XML]]は常にアノテーションメタデータよりも優先される。[[XML]]はハードコーディングされたアノテーションを再構成する手段を提供する</blockquote> |
====注入と継承==== | ====注入と継承==== | ||
*Beanクラスをクラス階層に含めることができる | *Beanクラスをクラス階層に含めることができる | ||
| 132行目: | 132行目: | ||
private SomeInf bean; | private SomeInf bean; | ||
| − | @EJB(beanName=" | + | @[[EJB]](beanName="Some[[EJB]]") |
public void someMethod(SomeInf bean) { | public void someMethod(SomeInf bean) { | ||
this.bean = bean; | this.bean = bean; | ||
| 146行目: | 146行目: | ||
public class MySessionBean extends Base implements MySessionLocalBusiness { | public class MySessionBean extends Base implements MySessionLocalBusiness { | ||
private SomeInf bean; | private SomeInf bean; | ||
| − | @EJB(beanName=" | + | @[[EJB]](beanName="Another[[EJB]]") |
public void someMethod(SomeInf bean) { | public void someMethod(SomeInf bean) { | ||
this.bean = bean; | this.bean = bean; | ||
} | } | ||
} | } | ||
| − | * | + | *このようにすると、Some[[EJB]]ではなく、Another[[EJB]]が注入される |
| − | <blockquote>someMethod が private の場合、Base には | + | <blockquote>someMethod が private の場合、Base には Some[[EJB]]が注入される</blockquote> |
===参照の注入と型 === | ===参照の注入と型 === | ||
2020年2月16日 (日) 04:27時点における最新版
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
<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;
}
}
<blockquote>someMethod が private の場合、Base には SomeEJBが注入される</blockquote>
参照の注入と型
© 2006 矢木浩人