Closed tomaszc closed 2 years ago
I am currently running into the exact same issue - did you make any progress in solving it?
My solution was to create custom liquibase task. I'll try to provide you with the most important parts of the code, based on this post. Thanks to it I was able to create changelog (by gradle task diffFixedDBvsEntities
) from differences between my current database schema and java-domain-entities from 'my.package.with.domain.entities' package:
buildscript {
ext {
springBootVersion = '1.5.8.RELEASE'
mariadbJdbcVersion = '2.1.2'
liquibaseVersion = '3.5.3'
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
...
//GRADLE LIQUIBASE PLUGIN DEPENDENCIES
classpath "org.mariadb.jdbc:mariadb-java-client:$mariadbJdbcVersion"
classpath 'gradle.plugin.org.liquibase:liquibase-gradle-plugin:1.2.4'
classpath 'org.hibernate:hibernate-core:5.0.12.Final'
classpath 'org.yaml:snakeyaml:1.17'
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
...
apply from: 'gradle/liquibase.gradle'
...
dependencies {
compile "org.springframework.boot:spring-boot-starter"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
...
compile "org.mariadb.jdbc:mariadb-java-client:$mariadbJdbcVersion"
...
runtime "org.liquibase:liquibase-core:$liquibaseVersion"
}
spring.datasource.url=jdbc:mariadb://127.0.0.1:3306/myDB
spring.datasource.username=MARIADB_USER
spring.datasource.password=MARIADB_PASS
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
liquibaseDiff.referenceUrl=hibernate:spring:my.package.with.domain.entities?hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&dialect=org.hibernate.dialect.MySQL5Dialect
//retrieve spring datasource properties from application.properties
def applicationProps = new Properties()
applicationProps.load(new FileInputStream("src/main/resources/application-dev.properties"))
def dbUsername = applicationProps.getProperty('spring.datasource.username') def dbPassword = applicationProps.getProperty('spring.datasource.password') def dbUrl = applicationProps.getProperty('spring.datasource.url') def dbJdbcDriver = applicationProps.getProperty('spring.datasource.driver-class-name') def liquibaseReferenceURL = applicationProps.getProperty('liquibaseDiff.referenceUrl')
//output files def defaultChangeLogFile = "$projectDir/src/main/resources/db/changelog/db.changelog-master.yaml" def customDiffChangeLogFile = "$projectDir/src/main/resources/db/changelog/db.changeloginitial${new Date().format('yyyyMMdd_HHmmss')}.yaml"
/**
dependencies { liquibase "org.liquibase.ext:liquibase-hibernate5:3.6"
//TODO delete if checked that unused
//liquibase "org.springframework:spring-beans:4.3.12.RELEASE"
//liquibase "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
}
/**
Diff fix - compare existing db vs java entities. Fixes not working official gradle diff */ task diffFixedDBvsEntities(type: JavaExec) { group = "liquibase"
classpath sourceSets.main.runtimeClasspath classpath configurations.liquibase main = "liquibase.integration.commandline.Main"
args "--changeLogFile=" + customDiffChangeLogFile args "--referenceUrl=" + liquibaseReferenceURL args "--username=" + dbUsername args "--password=" + dbPassword args "--url=" + dbUrl args "--referenceDriver=liquibase.ext.hibernate.database.connection.HibernateDriver" args "diffChangeLog" }
/**
liquibase { activities { main { driver dbJdbcDriver url dbUrl username dbUsername password dbPassword
changeLogFile defaultChangeLogFile
}
}
}
This is caused by liquibase-gradle-plugin, not liquibase-hibernate. liquibase-gradle-plugin has a problem related with classpath. https://github.com/liquibase/liquibase-gradle-plugin/issues/10
So for now, you can solve this problem by using classpath
variable in activity
closure for liquibase
block of liquibase-gradle-plugin.
For example, you can modify your liquibase
gradle block like below.
liquibase {
activities {
main {
...
classpath 'src/main'
...
}
}
}
Version 2.0 of the Liquibase Gradle plugin changed the way the classpath is set for Liquibase. You can now easily add any artifacts you need with liquibaseRuntime
dependencies inside the normal dependencies
block of the build.gradle file. That might help with this issue.
It turns out the underlying issue is that the liquibase-gradle-plugin does not assume that you want or need your project's files in the classpath when Liquibase runs. And I'm not sure I want to always assume that for all builds by automatically including project files in the classpath of all Liquibase builds - it seems to only be an issue with Spring Boot projects.
There is a pretty simple workaround: Adding liquibaseRuntime files('src/main')
or liquibaseRuntime sourceSets.main.output
to your dependencies appears to solve this problem.
I also got this exception and it was solved by compiling project and after generating target folder i started command liquibase diff (i use maven) 1) mvn compile 2) mvn liquibase:diff
I am also suffering from this issue. I am using maven plugin. Version 3.6 was working correctly (but it had other bugs like index regeneration during diffs). Bumping to 3.7 introduces this error. Can anyone take a look? This bug makes 3.7 pretty much unusable.
We are facing the same issue on the new 3.7 version... Any idea how to solve this?
Up. Same issue with 3.7
Hello I have the same error with maven, here the config I use
<profile>
<id>Liquibase DB Actions</id>
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<changeLogFile>
liquibase/master.xml
</changeLogFile>
<diffChangeLogFile>
src/main/resources/liquibase/changelog/${maven.build.timestamp}_changelog.xml
</diffChangeLogFile>
<url>jdbc:postgresql://${db.host}:5432/${db.name}</url>
<username>${db.username}</username>
<password>${db.password}</password>
<defaultSchemaName>public</defaultSchemaName>
<referenceUrl>
hibernate:spring:gara.model.db?hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
</referenceUrl>
<verbose>true</verbose>
<logging>debug</logging>
</configuration>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
Error:
Error setting up or running Liquibase: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
@SulaymonHursanov your solution seems to work for me using maven. also I encountred this when a deleted changeLog file is referenced in the master.xml
Still not working on version 3.8, mvn compile && mvn liquibase:diff
makes no difference, we are still getting aforementioned error... So we have to remain on version 3.6 which works, but lacks some bugfixes which would be nice to have...
My 2 cents here...
After a lot of debugging, I found that the bug comes from this method : HibernateSpringPackageDatabase.createEntityManagerFactoryBuilder()
when initializing the DefaultPersistenceUnitManager
.
Before version 3.6.0, no ResourceLoader was given to the DefaultPersistenceUnitManager
.
After v3.6.0, with this commit, this line was added :
internalPersistenceUnitManager.setResourceLoader(new DefaultResourceLoader(getHibernateConnection().getResourceAccessor().toClassLoader()));
If I change this line with this, the plugin works again :
internalPersistenceUnitManager.setResourceLoader(new DefaultResourceLoader());
Also, while debugging, I found that the ClassLoader given to the PersistenceUnitManager with v3.6+ was a CompositeClassLoader
. Before (so, the default one), is a URLClassLoader
.
Some more digging...
The bug occurs inside the DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl()
method.
The ResourceLoader tries to get the root URL from the ClassLoader. But, the new given ClassLoader is an instance of CompositeClassLoader
which does not implement the getResource()
and getResources()
methods (they always return null / empty collection).
If I implement those, everything run fine 👌
private static class CompositeClassLoader extends ClassLoader {
// ...
@Override
public URL getResource(String name) {
for (ClassLoader cl : classLoaders) {
URL url = cl.getResource(name);
if (url != null)
return url;
}
// Try with the context class loader associated with the current thread.
return Thread.currentThread().getContextClassLoader().getResource(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
List<URL> urls = new ArrayList<>();
for (ClassLoader cl : classLoaders) {
Enumeration<URL> resources = cl.getResources(name);
while (resources.hasMoreElements()) {
urls.add(resources.nextElement());
}
}
if (!urls.isEmpty()) {
return Collections.enumeration(urls);
}
// Try with the context class loader associated with the current thread.
return Thread.currentThread().getContextClassLoader().getResources(name);
}
}
It turns out the underlying issue is that the liquibase-gradle-plugin does not assume that you want or need your project's files in the classpath when Liquibase runs. And I'm not sure I want to always assume that for all builds by automatically including project files in the classpath of all Liquibase builds - it seems to only be an issue with Spring Boot projects.
There is a pretty simple workaround: Adding
liquibaseRuntime files('src/main')
orliquibaseRuntime sourceSets.main.output
to your dependencies appears to solve this problem.
what is the equivalent fix for maven
Three years and this is still not solved...how is this possible?
@sic2 I am waiting for this too, but I understand that pace of development correlates with funding of the project.
There is another workaround for Gradle users that may be simpler, depending on your use case. You could add liquibaseRuntime.extendsFrom runtime
to your configurations
block, or if you don't have a configurations block, add configurations.liquibaseRuntime.extendsFrom configurations.runtime
elswwhere in your build.gradle file. This tells Gradle that the liquibaseRuntime configuration should inherit all dependencies from the runtime
configuration. This would include all Spring and Hibernate dependencies, the database driver, and project files.
I'm not going to make this the default in the Gradle plugin because In most use cases, Liquibase only needs a database driver and parsing libraries, and I want to keep the classpath clean.
@sic2 for Maven users, the problem should be fixed soon with this merged PR : https://github.com/liquibase/liquibase/pull/927
Liquibase 3.8.7 is out. I have tested it in 2 of my projects and the problem seems fixed :-)
Oh damn, I just merged my task with 3.6 :( I need to do another PR asap and rewrite documentation :P
Thank you !
With Liquibase 3.8.7 the issue is solved, too! 🎉
I am going to close this one out as it appears to be resolved with newer versions of things... if this is not the case, please holler and we can reopen. Many thanks.
Hello,
I' struggling with liquibase diff generation on a very simple project which uses newest Spring Boot 1.5.8.RELEASE. I have empty, running database (MariaDB 10.3.2) and a simple domain object. I wan't to generate initial changelog based on this domain
build.gradle:
Domain object (only one in this package):
Error during liquibase diff execution:
I know that this issue was mentioned under ticket 68. But I wasn't able to resolve it be altering different hibernate/liquibase/liquibase-ext dependency versions.
┆Issue is synchronized with this Jira Bug by Unito