作業マネージャーを ContextService として使用することで、インターフェースの起動をコンテキストに対応して行い、
実行プロパティーを指定することで、スレッド・コンテキストがどのように取り込まれ、実行のスレッドに適用されるのかを制御します。
このタスクについて
オブジェクトのメソッドを呼び出す時点でスレッド・コンテキストが存在していなければならないアプリケーション・コンポーネントでは、javax.enterprise.concurrent.ContextService を実装する作業マネージャーを使用して、オブジェクトのコンテキスト・プロキシーを構成できます。コンテキスト・プロキシーの作成時に、作業マネージャーの設定に従ってスレッド・コンテキストが取り込まれます。コンテキスト・プロキシー上でインターフェース・メソッドが呼び出される際は、事前に取り込まれたスレッド・コンテキストが呼び出しの前に適用され、後で復元されます。
スレッド・コンテキストがどのように取り込まれて適用されるのかをコンテキスト・プロキシーで制御するために、実行プロパティーを指定することができます。例えば、
コンテキスト・プロキシー・メソッドは、実行プロパティーを使用して動作をオーバーライドしない限り、中断状態の実行スレッドに既にあるトランザクションで起動されます。
- スレッド・コンテキストを要求するメソッドを使用して、インターフェースを定義します (または、適切な既存のインターフェースを選択します)。
public interface AddressFinder {
Address getAddress(Person p) throws Exception;
}
- 次のようにして、インターフェースの実装を提供します。
public class DatabaseAddressFinder implements AddressFinder {
private final String resRefLookupName;
public DatabaseAddressFinder(String resRefLookupName) {
this.resRefLookupName = resRefLookupName;
}
public Address getAddress(Person p) throws Exception {
// Resource reference lookup requires the thread context of the
// application component that defines the resource reference.
DataSource ds = (DataSource) new InitialContext().lookup(
resRefLookupName);
Connection con = ds.getConnection();
try {
ResultSet r = con.createStatement().executeQuery(
"SELECT STREETADDR, CITY, STATE, ZIP " +
"FROM ADDRESSES WHERE PERSONID=" + p.id);
if (r.next())
return new Address(r.getString(1), r.getString(2),
r.getString(3), r.getInt(4));
else
return null;
} finally {
con.close();
}
}
}
- コンテキスト・サービスを使用して現行スレッドからコンテキストを取り込み、そのコンテキストでインスタンスをラップします。その際、実行プロパティーのセットを適用します。
ContextService contextService = (ContextService) new InitialContext().lookup(
"java:comp/DefaultContextService");
Map<String, String> executionProperties =Collections.singletonMap(
ManagedTask.TRANSACTION,
ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD)
AddressFinder addressFinder = contextService.createContextualProxy(
new DatabaseAddressFinder("java:comp/env/jdbc/MyDataSourceRef"),
executionProperties,
AddressFinder.class);
- 別のスレッドから、コンテキスト・プロキシーを使用して、元のスレッドのコンテキストの下でメソッドを呼び出します。
transaction.begin();
try {
Address myAddress = addressFinder.getAddress(me); updateShippingInfo(myAddress);
} finally {
transaction.commit();
}