关于此任务
要求在调用对象方法时存在线程上下文的应用程序组件可以使用工作管理器(它实现了
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();
}