您好,我有一個在 apache-tomee-plus-8.0.1 上運行的 Web 應用程式。我的問題是關于從自定義執行器中的可運行物件獲取環境變數。該變數在 /conf/context.xml 中定義:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- disable the scan in order to avoid errors at startup due to ora18n.jar-->
<JarScanner scanManifest="false" scanClassPath="false" scanBootstrapClassPath="false"></JarScanner>
<!-- base64 from user:pass -->
<Environment name="myCreds"
value="toto" type="java.lang.String" />
</Context>
我用來獲取變數“myCreds”的函式
private static String getCredentialsFromContext() throws NamingException {
Context initialContext = new InitialContext();
Context environmentContext = (Context) initialContext.lookup("java:comp/env");
return (String) environmentContext.lookup("myCreds");
}
此函式通過 JAX-RS 端點呼叫,該端點用于啟動服務器應用程式的長期后臺維護任務。然后后臺任務的進度在另一個端點上可用。如果我做
@GET
@Path("/testOK")
public static String testOK() {
return getCredentialsFromContext(); // works fine
}
但是當我使用執行器時,查找失敗并出現 javax.naming.NameNotFoundException: Name [comp/env] is not bound in this Context。無法找到 [comp]。
private static ExecutorService index_executor;
@GET
@Path("/testKO")
public static Response testKO() {
if (index_executor == null){
index_executor = Executors.newFixedThreadPool(5);
}
index_executor.submit(new Runnable() {
@Override
public void run() {
System.out.println(getCredentialsFromContext()); // FAIL
}
});
return Response.ok.build()
}
從可運行物件呼叫時,InitialContext 看起來不一樣。我想避免通過 args 傳遞“myCreds”的值。我試圖在 webapp 的 context.xml 中移動“myCreds”的宣告,但它沒有幫助。使用 JNDIContext 也會失敗。您是否了解問題所在以及為什么背景關系不同?
謝謝 :)
uj5u.com熱心網友回復:
JNDI 查找依賴于正在運行的執行緒上的一些背景關系資訊,通常是背景關系類加載器。
在 Java EE/Jakarta EE 服務器上,您不應自己生成新的(非托管)執行緒,而應使用ManagedExecutorService容器提供的執行緒。此服務自動從呼叫執行緒傳播某些型別的背景關系:
要從背景關系化應用程式組件傳播的背景關系型別包括JNDI 命名背景關系、類加載器和安全資訊。容器必須支持這些背景關系型別的傳播。
(雅加達并發規范,強調我的)
ManagedExecutorService您可以使用@Resource注解注入:
@Resource
private ManagedExecutorService executorService;
使用 Wildfly 上的ManagedExecutorService作品,但在 TomEE 上,恕我直言,有一個錯誤會阻止命名背景關系的傳播:JAX-RS 資源CxfContainerClassLoader用作背景關系類加載器,它包裝了真正的類加載器,防止它傳播到托管執行緒。
一種解決方法是暫時切換到包裝的類加載器:
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
if (tccl instanceof org.apache.openejb.util.classloader.Unwrappable) {
final ClassLoader cl = ((org.apache.openejb.util.classloader.Unwrappable) tccl).unwrap();
Thread.currentThread().setContextClassLoader(cl);
}
executorService.submit(...);
Thread.currentThread().setContextClassLoader(tccl);
編輯@Stateless:實際上,將 JAX-RS 資源標記為 JNDI 命名背景關系的正確傳播就足夠了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/426567.html
上一篇:升級到v9.0.58后的Tomcat和Tomcatdbcp問題
下一篇:遷移到Grails5.1.1后速度變慢-在GrailsControllerUrlMappingInfo上花費的時間
