You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to be able to create a ConnectionCustomizer to instrument our connection pools to monitor for activity for our health endpoint without necessarily hitting the database in the endpoint itself if we can avoid it.
But I'm having issues getting the class I'm creating visible to c3p0's classloader because we are using Clojure. Clojure uses a dynamic classloader to load classfiles compiled by each form.
with suitable bodies of these methods for our purposes. And then pass "connectionCustomizerClassName" (.getName CheckinTracker) as connection properties.
the problem for us though is that c3p0 looks for these ConnectionCustomizer with Class.forName (source). This happens from threads created by a threadpool somewhere that has the application class loader rather than Clojure's dynamic classloader. I'm able to work around this issue with a bit of reflection and setting the instantiated customizer in the cache with
I am sorry for the long delay. I am not from this timeline.
c3p0 does have the config parameter contextClassLoaderSource, and by default (ordinarily by default), that's the parent Thread's (in c3p0-speak the "caller") context ClassLoader, in practice the context ClassLoader of the first Thread to call getConnection() on a PooledDataSource. So, ensuring the ClassLoader you want at that initializing call would be one way to go, although it seems a bit fragile.
As of c3p0-0.10.0, c3p0 allows you to take full control over threading by defining a TaskRunnerFactory. So you can set whatever context ClassLoader you want.
However, though its fun to use Executors and loom Threads and stuff, most users should have little reason to switch from c3p0's old-school, battle-hardened hand-rolled Thread pool. (c3p0 predates java.util.concurrent.*) That's DefaultTaskRunnerFactory. c3p0 plug-ins are all no-arg public constructor reflectons, because being old-school JavaBeans means we are happiest with simple sorts of properties. But if there were an abstract version of DefaultTaskRunnerFactory with an abstract method like ClassLoader customContextClassLoader() that returns either null or an overriding context ClassLoader, might that help? Could you set-up the ClassLoader you need somewhere it could be looked up prior to c3p0 init?
Let me know! If you are working at my pace, I'll expect to hear from you, er, sometime in the next year or two. 😊
I want to be able to create a
ConnectionCustomizer
to instrument our connection pools to monitor for activity for our health endpoint without necessarily hitting the database in the endpoint itself if we can avoid it.But I'm having issues getting the class I'm creating visible to c3p0's classloader because we are using Clojure. Clojure uses a dynamic classloader to load classfiles compiled by each form.
In Clojure, I can do
with suitable bodies of these methods for our purposes. And then pass
"connectionCustomizerClassName" (.getName CheckinTracker)
as connection properties.the problem for us though is that c3p0 looks for these
ConnectionCustomizer
withClass.forName
(source). This happens from threads created by a threadpool somewhere that has the application class loader rather than Clojure's dynamic classloader. I'm able to work around this issue with a bit of reflection and setting the instantiated customizer in the cache withand this works, but I was wondering if this could be made a bit easier. Some possible solutions:
Datasources/pooledDataSource
methodsThank you for the lovely library otherwise and wondering if you have any thoughts about a way to make this easier.
The text was updated successfully, but these errors were encountered: