![[8.5.5.4 或更高版本]](../ng_v8554.gif)
配置线程上下文服务实例
可配置 ContextService 实例以捕获受管线程上下文并在对任何线程调用所指定接口方法时应用此上下文。
关于此任务
过程
在 server.xml 文件中启用线程上下文服务。此线程上下文服务在 <concurrent-1.0> 功能部件下提供。
<featureManager>
<feature>concurrent-1.0</feature>
</featureManager>
结果
缺省线程上下文服务实例 (DefaultContextService) 由服务器创建并配置为至少捕获并传播 classloaderContext、jeeMetadataContext 和 securityContext。可配置线程上下文传播以包含以下类型的线程上下文:
- classloaderContext
- 使任务的提交者的线程上下文类装入器可用于该任务。
如果上下文类装入器已序列化,那么类装入器必须是来自应用程序的线程上下文类装入器。当前不支持针对 Web 应用程序捆绑软件的类装入器序列化。
- jeeMetadataContext
- 使提交该任务的应用程序组件的名称空间可用于该任务。
- securityContext
必须在 server.xml 文件中启用 appSecurity-2.0 功能部件以使用此类型的线程上下文。使任务的提交者的调用者主体集和调用主体集对任务可用,此操作是通过使用提交者的 WSPrincipal(使用 JAAS 登录)进行登录来完成的。有关提交者主体集中的哪些信息未包含在安全上下文中的详细信息,请参阅 concurrent-1.0 功能部件限制。
要点: 在堆栈产品中,其他线程上下文提供者可能按功能部件提供。可选 baseContextRef
属性允许上下文服务实例从另一上下文服务实例的上下文配置继承。
示例
将线程上下文服务实例插入到应用程序组件中(通过使用 @Resource)或使用资源环境引用 (resource-env-ref) 进行查找。
- 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>
- 在 JNDI 中使用名称 concurrent/threadContextSvc1 进行注册的线程上下文服务,此服务仅捕获并传播 jeeMetadataContext:
- 使用 @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); ...