S2Containerは、Dependency Injection(以降DIと略します)をおこなう軽量コンテナです。 EJB3も実装しています。
早速試してみましょう。登場人物は次のようになります。
- あいさつクラス
- あいさつクライアントクラス
- あいさつクラスから取得したあいさつ(文字列)をコンソールに出力する。
- あいさつメインクラス
- 起動用のクラス。あいさつクラスとあいさつクライアントクラスの組み立ても行う。
Greeting.java
あいさつのためのインターフェースです。
package examples.ejb3;
public interface Greeting {
String greet();
}
GreetingImpl.java
あいさつの実装です。Statelessアノテーションを使って、簡単にStateless SessionBeanを作ることができます。
package examples.ejb3.impl;
import javax.ejb.Stateless;
import examples.ejb3.Greeting;
@Stateless
public class GreetingImpl implements Greeting {
public String greet() {
return "Hello World!";
}
}
GreetingClient.java
あいさつを利用するクライアントのインターフェースです。
package examples.ejb3;
public interface GreetingClient {
void execute();
}
GreetingClientImpl.java
あいさつを利用するクライアントの実装です。 EJBアノテーションを使って、Greetingインターフェースを実装したSessionBeanを参照することができます。
package examples.ejb3.impl;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import examples.ejb3.Greeting;
import examples.ejb3.GreetingClient;
@Stateless
public class GreetingClientImpl implements GreetingClient {
@EJB
private Greeting greeting;
public void execute() {
System.out.println(greeting.greet());
}
}
GreetingMain.dicon
EJB3用の設定ファイルです。 この内容を最初に記述しておけば、後からEJBが増えても、ファイルに情報を追加する必要はありません。 詳しくは、コンポーネントの自動登録を参照してください。
<components> <include path="ejb3tx.dicon"/> <component class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister"> <initMethod name="addClassPattern"> <arg>"examples.ejb3.impl"</arg> <arg>".*Impl"</arg> </initMethod> </component> </components>
GreetingMain.java
Seasar2のEJB3を実行するためのコードは次のようになります。 SingletonS2ContainerFactoryについての詳細はS2Containerの生成を参照してください。 @EJBのname属性を指定しなかった場合の、デフォルトの名前の命名規則は、DefaultAutoNamingを参照してください。
package examples.ejb3.main;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import examples.ejb3.GreetingClient;
public class GreetingMain {
private static final String PATH = "examples/ejb3/dicon/GreetingMain.dicon";
public static void main(String[] args) throws Exception {
SingletonS2ContainerFactory.setConfigPath(PATH);
SingletonS2ContainerFactory.init();
try {
doMain(args);
} finally {
SingletonS2ContainerFactory.destroy();
}
}
public static void doMain(String[] args) throws Exception {
Context ctx = new InitialContext();
GreetingClient greetingClient = (GreetingClient)
ctx.lookup("greetingClient");
greetingClient.execute();
}
}
実行結果は下記のようになります。
DEBUG 2006-03-25 18:38:47,892 [main] トランザクションを開始しました
Hello World!
DEBUG 2006-03-25 18:38:47,922 [main] トランザクションをコミットしました
S2Containerでは、EJB 3.0 Simplified APIのアノテーションもサポートしています。EJB3アノテーションを利用するにはJava5(Tiger)が必要です。
Statelessアノテーションを使って、Stateless SessionBeanを定義します。
Tigerアノテーションは以下のようになります。name属性を省略した場合、 コンポーネントの自動登録で使われるAutoNamingの実装クラスによって、 名前が自動的に決められます。
@Stateless(name="xxx")
public class Xxx {
...
}
Statefulアノテーションを使って、Stateful SessionBeanを定義します。
Tigerアノテーションは以下のようになります。name属性を省略した場合、 コンポーネントの自動登録で使われるAutoNamingの実装クラスによって、 名前が自動的に決められます。
@Stateful(name="xxx")
public class Xxx {
...
}
EJBアノテーションによって、EJB3コンポーネントを参照することができます。 Statless、Statefulアノテーションのname属性で付けた名前をbeanName属性に指定することができます。 beanName属性は、インターフェースを実装したオブジェクトが複数存在する場合にのみ使うようにしてください。
EJBアノテーションはフィールドまたはsetterメソッドに指定することができます.フィールドに指定された場合でbeanName属性が指定されなかった場合は,フィールド名がEJB3コンポーネント名として使用されます.
@EJB
private Aaa aaa;
@EJB(beanName="bbb2")
public void setBbb(Bbb bbb) {
...
}
Resourceアノテーションによって、DataSourceやDAO等のコンポーネントを参照することができます。 コンポーネントの名前をname属性に指定することができます。 name属性は、インターフェースを実装したオブジェクトが複数存在する場合にのみ使うようにしてください。
Resourceアノテーションはフィールドまたはsetterメソッドに指定することができます.フィールドに指定された場合でname属性が指定されなかった場合は,フィールド名がコンポーネント名として使用されます.
@Resource
private EmployeeDao employeeDao;
@Resource(name="fooDataSource")
private void setDataSource(DataSource ds) {
...
}
TransactionManagementアノテーションにより、コンテナ管理トランザクション(CMT)とBean管理トランザクション(BMT)を使い分けることができます。
デフォルトはCMTであるため、CMTを使用する場合はTransactionManagementアノテーションを明示する必要はありません。
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class Xxx {
...
}
TransactionAttributeアノテーションにより、ビジネスメソッドのトランザクション属性を設定することができます。この指定が有効なのは、CMTの場合のみです。
クラスにTransactionAttributeアノテーションを付けることにより、そのクラスのビジネスメソッド全体のトランザクション属性を設定することができます。指定しなかった場合のデフォルトはREQUIREDです。
メソッドにTransactionAttributeアノテーションを付けることにより、そのビジネスメソッドのトランザクション属性を設定することができます。指定しなかった場合のデフォルトはクラスに付けられたトランザクション属性です。
TransactionAttributeアノテーションを使用するには、そのセッションビーンを登録するコンテナにejb3tx.diconをインクルードする必要があります。 ejb3tx.diconはS2Tigerのresourcesディレクトリの下にあります。
@Stateless
@TransactionAttribute(TransactionAttributeType.MANDATRY)
public class Xxx {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void someMethod() {
...
}
}
Interceptorsアノテーションにより、ビジネスメソッドの呼び出しやライフサイクルイベントをインターセプトするクラスを複数指定することができます。
Interceptorsアノテーションはクラスまたはメソッドに付けることができます。
@Stateless
@Interceptors({foo.bar.HogeInterceptor.class, foo.bar.SomeInterceptor})
public class Xxx {
...
@Interceptors(foo.bar.MethodInterceptor)
private void hogehoge() {
...
}
}
ExcludeClassInterceptorsアノテーションにより、クラスに@Interceptorsアノテーションで指定したインターセプタをメソッドに適用しないことを指定することができます。
@Stateless
@Interceptors(foo.bar.HogeInterceptor.class)
public class Xxx {
...
@ExcludeClassInterceptos
@Interceptors(foo.bar.MethodInterceptor)
private void hogehoge() {
...
}
}
PostConstructアノテーションにより、インスタンス生成~DIの後に呼び出されるメソッドを指定することができます。
PostConstructアノテーションはセッションビーンまたはインターセプタクラスのメソッドに指定することができます。
セッションビーンにPostConstructアノテーションを付ける場合、そのメソッドは非static 、非final で引数がなく、戻り値型がvoid でなければなりません。メソッド名および可視性は任意です。
インターセプタにPostConstructアノテーションを付ける場合、そのメソッドは非static 、非final で引数はjavax.interceptor.InvocationContext 型一つだけ、戻り値型がvoid でなければなりません。メソッド名および可視性は任意です。
@Stateless
@Interceptors(Yyy.class)
public class Xxx {
...
@PostConstruct
private void initialize() {
...
}
}
public class Yyy {
...
@PostConstruct
private void initialize(InvocationContext context) {
...
}
}
AroundInvokeアノテーションにより、ビジネスメソッドの呼び出しをインターセプトすることができます。
AroundInvokeアノテーションはセッションビーンまたはインターセプタクラスのメソッドに指定することができます。
セッションビーンにAroundInvokeアノテーションを付けることができるメソッドは非static 、非final で引数はjavax.interceptor.InvocationContext 型一つだけ、戻り値型はjava.lang.Object 型でなければなりません。メソッドの名前や可視性は任意です。
クラスで一つのメソッドにだけAroundInvokeアノテーションを付けることができます。
@Stateless
@Interceptors(Yyy.class)
public class Xxx {
...
@AroundInvoke
private Object invoke(InvocationContext context) throws Exception {
...
}
}
public class Yyy {
...
@AroundInvoke
Object invoke(InvocationContext context) throws Exception {
...
}
}
|