quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.53k stars 2.61k forks source link

Unable to use Postgres Socket Factory on dev mode #15782

Open loicmathieu opened 3 years ago

loicmathieu commented 3 years ago

Describe the bug

On dev mode, the Postgres driver is unable to load the Socket Factory class, but on prod mode, using a standard JAR file, it works.

Expected behavior

Both dev mode and prod mode works the same.

Actual behavior

Using a Postgres socket factory on dev mode lead to a ClassNotFoundException

2021-03-16 16:56:45,700 WARN  [io.agr.pool] (agroal-11) Datasource '<default>': The SocketFactory class provided com.google.cloud.sql.postgres.SocketFactory could not be instantiated.
2021-03-16 16:56:45,701 WARN  [org.hib.eng.jdb.env.int.JdbcEnvironmentInitiator] (Quarkus Main Thread) HHH000342: Could not obtain connection to query metadata: org.postgresql.util.PSQLException: The SocketFactory class provided com.google.cloud.sql.postgres.SocketFactory could not be instantiated.
    at org.postgresql.core.SocketFactoryFactory.getSocketFactory(SocketFactoryFactory.java:43)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:182)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:225)
    at org.postgresql.Driver.makeConnection(Driver.java:465)
    at org.postgresql.Driver.connect(Driver.java:264)
    at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:200)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:452)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:434)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:65)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1126)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassNotFoundException: com.google.cloud.sql.postgres.SocketFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:315)
    at org.postgresql.util.ObjectFactory.instantiate(ObjectFactory.java:46)
    at org.postgresql.core.SocketFactoryFactory.getSocketFactory(SocketFactoryFactory.java:39)
    ... 13 more

To Reproduce

This is hard to provide an easy to use reproducer as I had this issue while trying to connect to Google Cloud SQL.

Configuration

# Add your application.properties here, if applicable.
quarkus.datasource.db-kind=other
quarkus.datasource.jdbc.url=jdbc:postgresql:///mydabatabe
quarkus.datasource.jdbc.driver=org.postgresql.Driver
quarkus.datasource.username=quarkus
quarkus.datasource.password=quarkus
quarkus.datasource.jdbc.additional-jdbc-properties.cloudSqlInstance=project-id:gcp-region:instance
quarkus.datasource.jdbc.additional-jdbc-properties.socketFactory=com.google.cloud.sql.postgres.SocketFactory

Environment (please complete the following information):

Output of uname -a or ver

Linux 5.8.0-44-generic #50-Ubuntu SMP Tue Feb 9 06:29:41 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "11.0.7" 2020-04-14

Quarkus version or git rev

1.12.2.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

loicmathieu commented 3 years ago

/cc @stuartwdouglas there seems to be a classloader issue on dev mode with how Postgres load socket factories

geoand commented 3 years ago

From the looks of the source code of org.postgresql.util.ObjectFactory it doesn't look like we can do much as Class.forName() is being used with the ClassLoader being passed in as an argument. If we where able to use the TCCL there, it would likely work as expected

loicmathieu commented 3 years ago

@geoand this is really annoying, we cannot mandate all libraries to use the TCCL to be compatible with out dev mode :(

I saw you add the upstream label, do you openned an issue upstream ?

geoand commented 3 years ago

I did not, no

geoand commented 3 years ago

@geoand this is really annoying, we cannot mandate all libraries to use the TCCL to be compatible with out dev mode :(

Using Class.forName without a ClassLoader as parameter is bad practice. I'm not saying it should be the TCCL, I'm saying that is should be configurable

stuartwdouglas commented 3 years ago

Can you try adding a META-INF/quarkus-extension.properties file to your project, and adding the following to it:

parent-first-artifacts=com.google.whatever\:artifact-with-the-socketfactory

Just as a temp workaround to see if it works? In theory we should be able to do this with the new parent-first CL config, however in practice it won't work at the moment without some changes.

loicmathieu commented 3 years ago

@stuartwdouglas tried, same result :(

stuartwdouglas commented 3 years ago

Actually it would probably need to go into its own sperate project and be added as a dep: https://github.com/stuartwdouglas/quarkus/blob/23ae9fd2a058b71bd65ff323d72fe84bfdb82a98/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java#L759

The current code only deals with zip files for dependencies.

loicmathieu commented 3 years ago

@stuartwdouglas I don't understand, this is a JAR file and the code path you mentionned is for JAR file so it should ne taken into account.

Actually it would probably need to go into its own sperate project and be added as a dep

I don't understand, this is already a separate dep, what should be done with it ? An extension ?

loicmathieu commented 3 years ago

@stuartwdouglas @geoand if nothing can be done at our side (according to me, updating a dependency code via bytecode injection is not a solution), can one of you open an issue upstream on the PostgreSQL client ? I'm not sure why loading a class without a CL is not a good idead so I don't know how to describe the bug and the possible side effect of them moving to the TCCL.

krashnakant commented 2 years ago

any further development happen here.

jhonnyman commented 1 year ago

Hello all, any updates on this issue? Recently tried to deploy my app to GCP Cloud Run and was blocked by the same issue. I'm on quarkus 2.16.1.Final version.

danieloh30 commented 9 months ago

Any progress here? I have the same issue when I even deploy the app to gcloud function.

cpoyatos1 commented 4 months ago

+1