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

Unable to resolve persistence unit root URL #170

Closed
tomaszc opened this issue Nov 6, 2017 · 23 comments
Closed

Unable to resolve persistence unit root URL #170

tomaszc opened this issue Nov 6, 2017 · 23 comments

Comments

@tomaszc
Copy link

tomaszc commented Nov 6, 2017

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:

	ext {
		springBootVersion = '1.5.8.RELEASE'
	        lombokVersion = '1.16.18'
	        mariadbJdbcVersion = '2.1.2'
	}
	dependencies {
		classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"

		//GRADLE LIQUIBASE PLUGIN DEPENDENCIES
		classpath "org.springframework:spring-beans:4.3.12.RELEASE"
		classpath "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
	        classpath "org.mariadb.jdbc:mariadb-java-client:$mariadbJdbcVersion"
		classpath "org.hibernate:hibernate-core:5.0.12.Final"
		classpath "gradle.plugin.org.liquibase:liquibase-gradle-plugin:1.2.4"
	        classpath "org.liquibase:liquibase-core:3.5.3"
		classpath "org.liquibase.ext:liquibase-hibernate5:3.6
	}
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'groovy'
apply plugin: 'org.liquibase.gradle'

jar.baseName = 'myApplication'
group = 'my.group.id'
version = '1.0-SNAPSHOT'
sourceCompatibility = 1.8

dependencies {
	compile "org.springframework.boot:spring-boot-starter:$springBootVersion"
	compile "org.springframework.boot:spring-boot-starter-data-jpa"
	compile "org.projectlombok:lombok:$lombokVersion"

	compile "org.mariadb.jdbc:mariadb-java-client:$mariadbJdbcVersion"
	compile "org.liquibase:liquibase-core:3.5.3"
}

liquibase {
    activities {
        main {
            driver 'org.mariadb.jdbc.Driver'
            url 'jdbc:mariadb://localhost:3306/greeterDB'
            username 'root'
            password 'mariadb_pass'

            changeLogFile 'src/main/resources/db/changelog/changelog-master.xml'

            referenceUrl 'hibernate:spring:my.group.id.persistence.domain?dialect=org.hibernate.dialect.MySQLDialect'
        }
    }
}

Domain object (only one in this package):

package my.group.id.persistence.domain;

import lombok.*;
import javax.persistence.*;

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@ToString
public class Greeting {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String message;
    private String type;
}

Error during liquibase diff execution:

10:53:20: Executing external task 'diff'...
:diff
liquibase-plugin: Running the 'main' activity...
INFO 11/6/17 10:53 AM: liquibase-hibernate: Reading hibernate configuration hibernate:spring:my.group.id.persistence.domain?dialect=org.hibernate.dialect.MySQLDialect
INFO 11/6/17 10:53 AM: liquibase-hibernate: Found package my.group.id.persistence.domain
Unexpected error running Liquibase: Unable to resolve persistence unit root URL

SEVERE 11/6/17 10:53 AM: liquibase: Unable to resolve persistence unit root URL
liquibase.exception.DatabaseException: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
	at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:127)
	at liquibase.integration.commandline.Main.createReferenceDatabaseFromCommandParams(Main.java:1283)
	at liquibase.integration.commandline.Main.doMigration(Main.java:993)
	at liquibase.integration.commandline.Main.run(Main.java:188)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:46)
	at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:91)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.liquibase.gradle.LiquibaseTask.runLiquibase(LiquibaseTask.groovy:113)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:384)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
	at org.liquibase.gradle.LiquibaseTask$_liquibaseAction_closure2.doCall(LiquibaseTask.groovy:56)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
	at groovy.lang.Closure.call(Closure.java:414)
	at groovy.lang.Closure.call(Closure.java:430)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2040)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2025)
	at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2078)
	at org.codehaus.groovy.runtime.dgm$165.invoke(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:251)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:71)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.liquibase.gradle.LiquibaseTask.liquibaseAction(LiquibaseTask.groovy:55)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:142)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:135)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:122)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:762)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:729)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:748)
Caused by: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
	at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:605)
	at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:445)
	at liquibase.ext.hibernate.database.HibernateSpringPackageDatabase.createEntityManagerFactory(HibernateSpringPackageDatabase.java:79)
	at liquibase.ext.hibernate.database.HibernateEjb3Database.buildMetadataFromPath(HibernateEjb3Database.java:51)
	at liquibase.ext.hibernate.database.HibernateDatabase.buildMetadata(HibernateDatabase.java:136)
	at liquibase.ext.hibernate.database.HibernateDatabase.setConnection(HibernateDatabase.java:75)
	at liquibase.database.DatabaseFactory.findCorrectDatabaseImplementation(DatabaseFactory.java:131)
	at liquibase.database.DatabaseFactory.openDatabase(DatabaseFactory.java:151)
	at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:85)
	... 96 more
Caused by: java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist
	at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187)
	at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:601)
	... 104 more


For more information, use the --logLevel flag
:diff FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':diff'.
> liquibase.exception.LiquibaseException: Unexpected error running Liquibase: Unable to resolve persistence unit root URL

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s
1 actionable task: 1 executed
class path resource [] cannot be resolved to URL because it does not exist
10:53:20: External task execution finished 'diff'.

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

@angrybobcat
Copy link

I am currently running into the exact same issue - did you make any progress in solving it?

@tomaszc
Copy link
Author

tomaszc commented Jan 31, 2018

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:

  1. build.gradle:
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"
}
  1. src/main/resources/application-dev.properties:
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
  1. gradle/liquibase.gradle:
//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.changelog_initial_${new Date().format('yyyyMMdd_HHmmss')}.yaml"


/**
 * CUSTOM GRADLE SCRIPT FOR LIQUIBASE
 *
 * ENABLES GENERATING LIQUIBASE CHANGELOG FILES FROM JAVA ENTITIES.
 * THIS CAN HELP YOU TO CREATE INITIAL DATABASE SCHEMA
 *
 * WHY NOT OFFICIAL GRADLE PLUGIN USAGE?
 * https://github.com/liquibase/liquibase-hibernate/issues/170
 * SCRIPT BASED ON:
 * https://stackoverflow.com/questions/35716378/unable-to-generate-difference-from-liquibase-gradle-plugin
 */
configurations {
    liquibase
}

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"
}

/**
 * STANDARD GRADLE SCRIPT -
 *
 * HAS PROBLEMS WITH DIFF (between DB and Java Entities)
 */
apply plugin: 'org.liquibase.gradle'

liquibase {
    activities {
        main {
            driver dbJdbcDriver
            url dbUrl
            username dbUsername
            password dbPassword

            changeLogFile defaultChangeLogFile
        }
    }
}

@iBluemind
Copy link

iBluemind commented Jun 13, 2018

This is caused by liquibase-gradle-plugin, not liquibase-hibernate. liquibase-gradle-plugin has a problem related with classpath. liquibase/liquibase-gradle-plugin#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'
            ...
        }
    }
}

@stevesaliman
Copy link

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.

@stevesaliman
Copy link

stevesaliman commented Sep 3, 2018

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.

@SulaymonHursanov
Copy link

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

@eXsio
Copy link

eXsio commented Jun 28, 2019

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.

@Neloop
Copy link

Neloop commented Jul 1, 2019

We are facing the same issue on the new 3.7 version... Any idea how to solve this?

@szczebel
Copy link

szczebel commented Jul 5, 2019

Up. Same issue with 3.7

@rfanjul
Copy link

rfanjul commented Jul 31, 2019

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&amp;hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&amp;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

@mboullouz
Copy link

mboullouz commented Sep 4, 2019

@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

@Neloop
Copy link

Neloop commented Sep 4, 2019

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...

@mselerin
Copy link

mselerin commented Oct 16, 2019

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.

@mselerin
Copy link

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);
    }
}

@mohamedzaki90
Copy link

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.

what is the equivalent fix for maven

@sic2
Copy link

sic2 commented Feb 24, 2020

Three years and this is still not solved...how is this possible?

@aljazerzen
Copy link

@sic2 I am waiting for this too, but I understand that pace of development correlates with funding of the project.

@stevesaliman
Copy link

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.

@mselerin
Copy link

@sic2 for Maven users, the problem should be fixed soon with this merged PR : liquibase/liquibase#927

@mselerin
Copy link

Liquibase 3.8.7 is out. I have tested it in 2 of my projects and the problem seems fixed :-)

@vschoener
Copy link

Oh damn, I just merged my task with 3.6 :( I need to do another PR asap and rewrite documentation :P

Thank you !

@timbru31
Copy link

With Liquibase 3.8.7 the issue is solved, too! 🎉

@kataggart
Copy link

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.

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

No branches or pull requests