liquibase-hibernate: Unable to resolve persistence unit root URL

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

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 10
  • Comments: 23

Most upvoted comments

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…

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.

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

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

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

@sic2 for Maven users, the problem should be fixed soon with this merged PR : https://github.com/liquibase/liquibase/pull/927

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.

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