Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Liquibase not reading JAR from classpath #177

Closed
luisospina-sealed opened this issue Oct 3, 2022 · 11 comments · Fixed by #206
Closed

Liquibase not reading JAR from classpath #177

luisospina-sealed opened this issue Oct 3, 2022 · 11 comments · Fixed by #206

Comments

@luisospina-sealed
Copy link

I'm trying to connect to a Postgres Google Cloud SQL instance which requires an additional dependency (https://mvnrepository.com/artifact/com.google.cloud.sql/postgres-socket-factory/1.7.0)

I'm using the following command to execute Liquibase update:

docker run -it -v $(pwd)/src/main/resources:/liquibase/changelog -v $(pwd)/build/libs:/liquibase/classpath liquibase/liquibase \
  --classpath="/liquibase/changelog:/liquibase/classpath/postgres-socket-factory-1.7.0.jar" \
  --changelog-file=/liquibase/changelog/db/liquibase-changelog.xml \
  --url='jdbc:postgresql:///db-name?cloudSqlInstance=project:us-east1:instance-db&socketFactory=com.google.cloud.sql.postgres.SocketFactory' \
  --log-level=DEBUG \
  update

But Liquibase is not using the JAR that I specified above .--classpath="/liquibase/changelog:/liquibase/classpath/postgres-socket-factory-1.7.0.jar"

I'm seeing that the JAR is being copied to the container to the right path, but when running command update Liquibase throws a Class not found error:

image

@luisospina-sealed
Copy link
Author

by running the command as DEBUG log-leve, i'm seeing the JAR file is there (in the overall search path)

[2022-10-03 23:34:03] FINE [liquibase.resource] Overall search path: 
  - /liquibase/.
  - /liquibase/changelog
  - /liquibase/classpath/postgres-socket-factory-1.7.0.jar
  - /liquibase/internal/lib
  - /liquibase/internal/lib/commons-collections4.jar
  - /liquibase/internal/lib/commons-lang3.jar
  - /liquibase/internal/lib/commons-text.jar
  - /liquibase/internal/lib/connector-api.jar
  - /liquibase/internal/lib/h2.jar
  - /liquibase/internal/lib/hsqldb.jar
  - /liquibase/internal/lib/jaxb-api.jar
  - /liquibase/internal/lib/jaxb-core.jar
  - /liquibase/internal/lib/jaxb-runtime.jar
  - /liquibase/internal/lib/jaybird.jar
  - /liquibase/internal/lib/jcc.jar
  - /liquibase/internal/lib/liquibase-commercial.jar
  - /liquibase/internal/lib/liquibase-core.jar
  - /liquibase/internal/lib/mariadb-java-client.jar
  - /liquibase/internal/lib/mssql-jdbc.jar
  - /liquibase/internal/lib/ojdbc8.jar
  - /liquibase/internal/lib/opencsv.jar
  - /liquibase/internal/lib/picocli.jar
  - /liquibase/internal/lib/postgresql.jar
  - /liquibase/internal/lib/snakeyaml.jar
  - /liquibase/internal/lib/snowflake-jdbc.jar
  - /liquibase/internal/lib/sqlite-jdbc.jar
  - /liquibase/lib

But still getting theClassNotFoundException

@sfat
Copy link
Contributor

sfat commented Nov 7, 2022

hey @luisospina-sealed,
I think I manage to figure your issue out, not sure if it's a bug in liquibase or it's not the recommended way, but here's what I did:

  1. I downloaded the postgres-socket-factory with dependencies from GCP Github releases: https://storage.googleapis.com/cloud-sql-java-connector/v1.7.2/postgres-socket-factory-1.7.2-jar-with-dependencies.jar
  2. Then it was a bit of massaging the parameters. TL;DR instead of adding on /changelog, I've added them on /lib, resulting in something like this:
docker run -it -v $(pwd)/src/main/resources:/liquibase/changelog -v $(pwd)/build/libs:/liquibase/lib liquibase/liquibase \
  --classpath="/liquibase/lib:/liquibase/lib/postgres-socket-factory-1.7.2-jar-with-dependencies.jar" \
  --changelog-file=/liquibase/changelog/db/liquibase-changelog.xml \
  --url="jdbc:postgresql:///<DATABASE_NAME>?cloudSqlInstance=dbInstance&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=user&password=pwd" \
  --log-level=DEBUG \
  update

Now the error that I'm getting is:

Caused by: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql:///<DATABASE_NAME>?cloudSqlInstance=dbInstance&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=*****&password=***** with driver org.postgresql.Driver.  Something unusual has occurred to cause the driver to fail. Please report this exception.
	at liquibase.database.ConnectionServiceFactory.create(ConnectionServiceFactory.java:35)
	at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:217)
	... 36 more
Caused by: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql:///<DATABASE_NAME>?cloudSqlInstance=dbInstance&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=*****&password=***** with driver org.postgresql.Driver.  Something unusual has occurred to cause the driver to fail. Please report this exception.
	at liquibase.database.jvm.JdbcConnection.open(JdbcConnection.java:91)
	at com.datical.liquibase.ext.database.jvm.ProJdbcConnection.open(Unknown Source)
	at liquibase.database.ConnectionServiceFactory.create(ConnectionServiceFactory.java:32)
	... 37 more
Caused by: org.postgresql.util.PSQLException: Something unusual has occurred to cause the driver to fail. Please report this exception.
	at org.postgresql.Driver.connect(Driver.java:314)
	at liquibase.database.jvm.JdbcConnection.open(JdbcConnection.java:83)
	... 39 more
Caused by: java.lang.RuntimeException: Unable to obtain credentials to communicate with the Cloud SQL API
	at com.google.cloud.sql.core.CoreSocketFactory$ApplicationDefaultCredentialFactory.create(CoreSocketFactory.java:390)
	at com.google.cloud.sql.core.CoreSocketFactory.getInstance(CoreSocketFactory.java:140)
	at com.google.cloud.sql.core.CoreSocketFactory.connect(CoreSocketFactory.java:265)
	at com.google.cloud.sql.postgres.SocketFactory.createSocket(SocketFactory.java:76)
	at org.postgresql.core.PGStream.createSocket(PGStream.java:229)
	at org.postgresql.core.PGStream.<init>(PGStream.java:98)
	at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:109)
	at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:235)
	at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
	at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:247)
	at org.postgresql.Driver.makeConnection(Driver.java:434)
	at org.postgresql.Driver.connect(Driver.java:291)
	... 40 more
Caused by: java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
	at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:134)
	at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:125)
	at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:97)
	at com.google.cloud.sql.core.CoreSocketFactory$ApplicationDefaultCredentialFactory.create(CoreSocketFactory.java:388)
	... 51 more

But this is normal, since I don't have access to GCP.

Hope it helps :)

@rokjoana
Copy link

I have a similar issue, but when creating an extended docker image with the neo4j plugin jar:
I'm using the dockerfile

FROM liquibase/liquibase:4.19

USER root
WORKDIR /liquibase/internal/lib/
RUN curl -o liquibase-neo4j.jar https://repo1.maven.org/maven2/org/liquibase/ext/liquibase-neo4j/4.20.0/liquibase-neo4j-4.20.0-full.jar
RUN chown liquibase: liquibase-neo4j.jar
WORKDIR /liquibase
USER liquibase

and when the image starts the following error occurs:

Unexpected error running Liquibase: Driver class was not specified and could not be determined from the url (jdbc:neo4j:bolt://localhost:54225)

I've confirmed that the url is correctly set and also I've tried placing the jar on /liquibase/internal/lib/ and /liquibase/lib/ with similar results.
Could we have another directory, besides the one to mount /liquibase/classpath to mount the plugin jars?

@Kuba15
Copy link

Kuba15 commented Apr 26, 2023

Hello,
I may have a related issue.
I am using "includeAll" with a specific "resourceComparator".
The resourceComparator is in a JAR listed at the container startup (located in /liquibase/lib), but the class is not found, giving the message "no resourceComparator defined - taking default implementation".
If I put a class like java.lang.String or a class from liquibase-core, the class is found.
But classes from an external JAR are not.

@nvoxland
Copy link
Contributor

Short answer:
You can add -v /path/to/your/lib/dir:/liquibase/lib and it should work.

Longer answer:
Yes, the "classpath" setting in the docs and what gets exposed in the docker container doesn't work with extensions. The base problem is that "classpath" isn't really setting the classpath, it's a backwards-compatible name for the search-path which is only for changelog files.

For what to include in the classpath, liquibase ONLY looks in:

  • /liquibase/internal/lib (for jars shipped with liquibase, so not where extensions/drivers get added)
  • /liquibase/lib (for "global" jars to be used by all users of liquibase)
  • ${PWD}/liquibase_libs (for "project" jars which may be different depending on your project)

I'm going to open a PR with a better volume mapping for /liquibase/lib and improve the docs

@mukta-kindred
Copy link

Hi @nvoxland,
The above suggestion fixed the issue.Steps I followed are:

  1. Changed my docker command to mount jar files folder to /liquibase/lib (and not /liquibase/classpath)
    docker run --rm -v /path/to/my-project:/liquibase/changelog -v /path/to/my-project/lib:/liquibase/lib liquibase/liquibase:4.21.1 --defaultsFile=/liquibase/changelog/liquibase.properties update
  2. Changed my classpath property in liquibase.properties file accordingly:
    classpath=/liquibase/changelog:/liquibase/lib/redshift-jdbc42-2.1.0.9.jar:/liquibase/lib/liquibase-redshift-4.21.1.jar
    The ’ Drivers and Extensions’ section of Liquibase docker page (https://hub.docker.com/r/liquibase/liquibase) needs to be changed.
    Thanks.

@nvoxland
Copy link
Contributor

I'm going to re-open this, since #206 improves it and also updates the docs.

@nvoxland nvoxland reopened this May 16, 2023
@nvoxland nvoxland linked a pull request May 16, 2023 that will close this issue
@nvoxland
Copy link
Contributor

@stmty9
Copy link

stmty9 commented May 20, 2023

I would suggest that anyone who has an issue putting their desired jar into /liquibase/lib try instead to put it into /liquibase/liquibase_libs instead using the following working dir:

WORKDIR "/liquibase"

we have a gradle task that pulls down our desired dependency and was putting it into lib relative to the build (effectively putting it at /liquibase/lib. This was working for months, then all of a sudden stopped working recently (turns out we were using the latest tag - UH OH).

I tried quite a few different things (for some reason pinning the liquibase/liquibase image to an older version was causing mismatch checksums on migrations that have previously run??

I ended up pulling the dependencies into liquibase_libs relative to the build (which puts them into /liquibase/liquibase_libs and this worked.

Thanks @nvoxland for adding all the paths so that I could try them all to see what ended up working.

@jnewton03
Copy link
Contributor

reopening issues as the fix applied in #206 broke something with lpm. Had to revert in #210.

@jnewton03 jnewton03 reopened this May 22, 2023
@jnewton03
Copy link
Contributor

Users can also use LPM and we have this documented. Additionally users have expressed workarounds in this issue, so closing for now. Please feel free to re-open if the issue persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants