配置线程上下文服务实例
可配置 ContextService 实例以捕获受管线程上下文并应用它以对任何线程调用指定接口方法。
关于此任务
缺省线程上下文服务实例 (DefaultContextService) 由服务器创建,配置为至少捕获并传播 classloaderContext、jeeMetadataContext 和 securityContext 元素。可配置线程上下文传播以包含以下类型的线程上下文:
- classloaderContext
- 使任务的提交者的类装入器可用于该任务。如果上下文类装入器已序列化,那么类装入器必须是来自应用程序的线程上下文类装入器。当前不支持针对 OSGi Web 应用程序捆绑软件的类装入器序列化。
- jeeMetadataContext
- 使提交任务的应用程序组件的名称空间对该任务可用。
- securityContext
- 必须在 server.xml 文件中启用 appSecurity-2.0 功能部件以使用此类型的线程上下文。使任务的提交者的调用者主体集和调用主体集可用于该任务。可以通过使用 JAAS 登录模块来使用提交者的 WSPrincipal 凭证进行登录以完成此操作。有关提交者主体集中的哪些信息不在安全上下文中的详细信息,请参阅 concurrent-1.0 功能部件限制。
过程
在 server.xml 文件中启用线程上下文服务。此线程上下文服务在 <concurrent-1.0> 功能部件下提供。
<featureManager>
<feature>concurrent-1.0</feature>
</featureManager>
示例
在 server.xml 文件中配置线程上下文服务实例:
- 在 JNDI 中以名称 concurrent/threadContextSvc1 注册且仅捕获并传播 jeeMetadataContext 的线程上下文服务:
<contextService id="threadContextSvc1" jndiName="concurrent/${id}"> <jeeMetadataContext/> </contextService>
- 带有 classloaderContext 和 securityContext 的线程上下文服务:
<contextService jndiName="concurrent/threadContextSvc2"> <classloaderContext/> <securityContext/> </securityContext/>
- 从 threadContextSvc1 继承 jeeMetadataContext 并添加 securityContext 的线程上下文服务:
<contextService jndiName="concurrent/threadContextSvc3" baseContextRef="threadContextSvc1"> <securityContext> </contextService>
查找缺省上下文服务的示例:
ContextService threadContextSvc =
(ContextService) new InitialContext().lookup(
"java:comp/DefaultContextService");
myContextualAsyncCallback = threadContextSvc.createContextualProxy(
myAsyncCallback, MyAsyncCallback.class);
doSomethingAsync(arg1, arg2, myContextualAsyncCallback);
将线程上下文服务实例注入到应用程序组件中(通过使用 @Resource)或使用资源环境引用 (resource-env-ref) 进行查找的示例。
- 使用 @Resource 的示例:
@Resource(lookup="concurrent/threadContextSvc1") ContextService threadContextSvc1; ... Callable<Integer> processSalesOrderCompletion = new Callable<Integer>() { public Integer call() throws Exception { DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ...update various database tables return isSuccessful; } }; // capture thread context of current application component execProps = Collections.singletonMap(ManagedTask.TRANSACTION, ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD); processSalesOrderCompletion = (Callable<Boolean>) threadContextSvc1.createContextualProxy(processSaleCompletion, execProps, Callable.class); //later from a different application component tran.begin(); ... successful = processSalesOrderCompletion.call(); if (successful) tran.commit(); else tran.rollback();
- 在 web.xml 文件中指定 resource-env-ref 的示例:
<resource-env-ref> <resource-env-ref-name>concurrent/threadContextSvc3</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.concurrent.ContextService</resource- env-ref-type> </resource-env-ref>
- 使用资源环境引用的示例查找:
ContextService threadContextSvc3 = (ContextService) new InitialContext().lookup("java:comp/env/concurrent/threadContextSvc3"); Runnable updateAndGetNextFromDatabase = threadContextSvc3.createContextualProxy (new Runnable() { public void run() { DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ... update the database and get next item to process } }, Runnable.class); barrier = new CyclicBarrier(3, updateAndGetNextFromDatabase); ...