Commits
Tarun Sukhani authored 8c242f7b795
fix: resolve db.factory with the application classloader (PF-174) DBPlugin.factory() used the one-argument Class.forName, which is caller- sensitive and so resolved against the loader that defined play.db.DBPlugin -- the framework's. A DataSourceFactory in the application's own app/ tree was therefore unusable: under the bundle launcher, whose classpath is conf, the framework jar and the lib jars only, the lookup failed outright and the app refused to start with "Expected implementation of play.db.DataSourceFactory"; under a Gradle launch it was found via build/classes/java/main but as a second copy with its own statics, distinct from the one Play.classloader hands the rest of the application. The db.driver lookup fifteen lines below already passed Play.classloader, so db.driver accepted an application class and db.factory did not. Pass it here too. Play.classloader delegates framework and lib classes to its parent, so the default HikariDataSourceFactory and any jar-shipped factory resolve exactly as before; only application classes gain visibility. Covered by an integration test rather than a unit test because proving the difference needs a real booted ApplicationClassloader over an app tree. The fixture factory lives in testapp/app/services/ and, because compile-tests globs test-src/**/*.java, is also compiled into test-classes/ -- reproducing the Gradle two-copies case exactly, so the test distinguishes the loaders instead of merely observing a ClassNotFoundException. Reverting the fix fails it with AppClassLoader where ApplicationClassloader is expected. The companion test asserts the built-in default still resolves to the parent loader's class, which is what keeps DBPlugin's cast to DataSourceFactory safe. Found by JCLAW-1164, which wants a factory under app/services/telemetry that wraps the Hikari pool's inner datasource for OpenTelemetry JDBC spans. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JTvjeSmGVe7RFyx8ZJXRAx