-
Notifications
You must be signed in to change notification settings - Fork 232
getTracer() fails because SenderFactory and ThriftSenderFactory are loaded from different ClassLoaders #520
Comments
Can you share your
+1, would you like to send a PR? |
By the way: I got a PR merged last week adding transparent Jaeger and OT support for WildFly. It'll be available from WF 14 Beta2 and on and I'm really interested in getting feedback about it. |
We already declared the import of the services and through debugging I managed to see that META-INF/io.jaegertracing.spi.SenderFactory from jaeger-thrift is found and the class name io.jaegertracing.thrift.internal.senders.ThriftSenderFactory is read, but the problem is the class loader this class is then loaded with. What stands PR for? |
Looks like you nailed it.
PR stands for pull request :) If you want to contribute with a fix, let me know and I can guide you. |
PR created. |
In our project we have an ear which contains multiple jars and a seperated web service war. Both are deployed in a WildFly 13.
In the ear there is a api.jar which contains interfaces and other classes which should be visible for other deployments and a core.jar with implementations of the api.jar.
Through pom dependencies and jboss-deployment-structure.xml the war can use the classes from api.jar. In the ear there is also a lib directory with libraries used the jars in the ear, for example the libraries of opentracing and jaeger.
The war also has dependencies to the jaeger libraries.
All worked fine until we tried to update the jaeger libraries from version 0.27.0 to 0.30.4.
When we call the web service the following happens. The call gets to a web filter which among other things sets up a jaeger tracer for logging. This happens in the core.jar. We use the "Configuration via Environment" way to obtain a tracer. But since the new version we get this exception:
From version 0.29.0 to 0.30.0 a change was made to io.jaegertracing.Configuration.SenderConfiguration.getSender() method which now calls the SenderResolver.resolve(SenderConfiguration) method. In this method a java.util.ServiceLoader is used to load available implementations of io.jaegertracing.spi.SenderFactory, the ServiceLoader is created like this: ServiceLoader.load(SenderFactory.class). Because this happens in the core.jar and uses libraries of the ear the SenderFactory class is loaded with the class loader of the ear. The ServiceLoader then does find the class io.jaegertracing.thrift.internal.senders.ThriftSenderFactory as an implementation of SenderFactory BUT this class is loaded by the class loader of the war. That is because the method ServiceLoader.load(SenderFactory.class) uses Thread.currentThread().getContextClassLoader() as loader. The current thread originally was started in the web service deployment.
A possible suggestion could be to call ServiceLoader.load(SenderFactory.class, SenderFactory.class.getClassLoader()) in SenderResolver.resolve(SenderConfiguration). But we don't know which impact this would have.
We found a workaround by calling Thread.currentThread().setContextClassLoader(SenderFactory.class.getClassLoader()) before we call getTracer() on the Configuration.
Thanks for your help
The text was updated successfully, but these errors were encountered: