In the org.eclipse.microprofile.lra.tck.TckContextTests TCK the following two tests invoke a resource which submits threads on a non-managed executor service:
testAsync1Support()
testAsync2Support()
The methods are in the org.eclipse.microprofile.lra.tck.participant.api,ContextTckResource:
async1LRA()
asyncInvocationWithLRA()
In WildFly the tests use Narayana which has a io.narayana.lra.filter.ServerLRAFilter filter which is a CDI bean. Given the methods use a non-managed thread, the CDI context is not available and an exception is thrown:
07:17:47,687 WARN [io.narayana.lra] (pool-13-thread-1) LRA025036: CDI Context not available: LRAParticipantData is not usable in this (probably async) context.
07:17:47,721 ERROR [org.jboss.resteasy.core.providerfactory.DefaultExceptionMapper] (pool-13-thread-1) RESTEASY002375: Error processing request PUT /tckcontexttests/context-tck-resource/async-response-lra - org.eclipse.microprofile.lra.tck.participant.api.ContextTckResource.async1LRA: org.jboss.weld.contexts.ContextNotActiveException: WELD-001303: No active contexts for scope type jakarta.enterprise.context.RequestScoped
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:671)
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:95)
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:179)
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:64)
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:86)
at org.jboss.weld.core@6.0.4.Final//org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:108)
at org.jboss.resteasy.resteasy-cdi@7.0.3.Final//org.jboss.weld.generated.proxies.ws.rs.container.ResourceInfo$889195678$Proxy$_$$_WeldClientProxy.getResourceMethod(Unknown Source)
at org.jboss.narayana.lra.lra-participant@1.2.0.Final//io.narayana.lra.filter.ServerLRAFilter.filter(ServerLRAFilter.java:603)
at org.jboss.narayana.lra.lra-participant@1.2.0.Final//io.narayana.lra.filter.ServerLRAFilter$Proxy$_$$_WeldClientProxy.filter(Unknown Source)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.interception.jaxrs.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:342)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:243)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:100)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:73)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.SynchronousDispatcher.asynchronousDelivery(SynchronousDispatcher.java:479)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.core.AbstractAsynchronousResponse.internalResume(AbstractAsynchronousResponse.java:179)
at org.jboss.resteasy.resteasy-core@7.0.3.Final//org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext$Servlet3AsynchronousResponse.resume(Servlet3AsyncHttpRequest.java:90)
at deployment.tckcontexttests.war//org.eclipse.microprofile.lra.tck.participant.api.ContextTckResource.lambda$async1LRA$0(ContextTckResource.java:248)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
at java.base/java.lang.Thread.run(Thread.java:1474)
In an EE container, unmanaged threads should not be used to invoke tasks that require container managed resources.
A fix might be an attempt to lookup a ManagedExecutorService and if not found, given it's not required in the core profile, then use a known custom executor service. Potentially something like:
public static ExecutorService threadPool() {
ExecutorService executor = lookup("java:comp/DefaultManagedExecutorService");
if (executor == null) {
final ExecutorService delegate = new ThreadPoolExecutor(Math.max(5, Runtime.getRuntime().availableProcessors()), Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(), new ContextualThreadFactory("contextual-pool"));
}
return executor;
}
private static <T extends ExecutorService> T lookup(final String jndiName) {
final Boolean performLookup = JNDI_LOOKUPS.get(jndiName);
if (performLookup != null && performLookup) {
try {
// This could have some performance impact. However, we can't assume the context we're in, so we need
// to look it up each time.
return InitialContext.doLookup(jndiName);
} catch (NamingException ignore) {
} catch (Exception e) {
LogMessages.LOGGER.failedToLookupManagedExecutorService(e, jndiName);
}
} else if (performLookup == null) {
// Do one lookup and if not found assume it won't be in the future
try {
final T service = InitialContext.doLookup(jndiName);
JNDI_LOOKUPS.put(jndiName, Boolean.TRUE);
return service;
} catch (NamingException ignore) {
} catch (Exception e) {
LogMessages.LOGGER.failedToLookupManagedExecutorService(e, jndiName);
}
JNDI_LOOKUPS.put(jndiName, Boolean.FALSE);
}
return null;
}
In the
org.eclipse.microprofile.lra.tck.TckContextTestsTCK the following two tests invoke a resource which submits threads on a non-managed executor service:testAsync1Support()testAsync2Support()The methods are in the
org.eclipse.microprofile.lra.tck.participant.api,ContextTckResource:async1LRA()asyncInvocationWithLRA()In WildFly the tests use Narayana which has a
io.narayana.lra.filter.ServerLRAFilterfilter which is a CDI bean. Given the methods use a non-managed thread, the CDI context is not available and an exception is thrown:In an EE container, unmanaged threads should not be used to invoke tasks that require container managed resources.
A fix might be an attempt to lookup a
ManagedExecutorServiceand if not found, given it's not required in the core profile, then use a known custom executor service. Potentially something like: