Mettre à jour automatiquement le journal des modifications de Liquibase lors de la construction

Je travaille actuellement sur un projet Spring qui utilise Hibernate et Liquibase. Ce que je cherche à faire est de mettre à jour automatiquement le journal des modifications de Liquibase chaque fois que je construis le projet. Il est censé générer un diff basé sur ma firebase database productive actuelle et sur mes entités Hibernate mises à jour.

Mais le problème que j’ai est que chaque fois que je nettoie et reconstruis mon projet, l’erreur suivante apparaît:

liquibase-plugin: Running the 'main' activity... INFO 6/22/15 11:12 AM: liquibase-hibernate: Reading hibernate configuration hibernate:spring:com.example.name.domain?dialect=org.hibernate.dialect.MySQL5Dialect INFO 6/22/15 11:12 AM: liquibase-hibernate: Found package com.example.app.domain INFO 6/22/15 11:12 AM: liquibase-hibernate: Found dialect org.hibernate.dialect.MySQL5Dialect Unexpected error running Liquibase: Unable to resolve persistence unit root URL SEVERE 6/22/15 11:12 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:69) at liquibase.integration.commandline.Main.createReferenceDatabaseFromCommandParams(Main.java:1169) at liquibase.integration.commandline.Main.doMigration(Main.java:936) at liquibase.integration.commandline.Main.run(Main.java:175) 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:497) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:43) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:88) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.liquibase.gradle.LiquibaseTask.runLiquibase(LiquibaseTask.groovy:97) 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:497) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:382) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141) at org.liquibase.gradle.LiquibaseTask$_liquibaseAction_closure1.doCall(LiquibaseTask.groovy:52) 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:497) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015) at groovy.lang.Closure.call(Closure.java:423) at groovy.lang.Closure.call(Closure.java:439) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1379) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1310) at org.codehaus.groovy.runtime.dgm$150.invoke(Unknown Source) at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271) at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.liquibase.gradle.LiquibaseTask.liquibaseAction(LiquibaseTask.groovy:46) 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:497) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:226) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:219) at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:208) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:589) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:572) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310) at org.gradle.api.internal.AbstractTask.execute(AbstractTask.java:305) at org.gradle.api.internal.TaskInternal$execute$0.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112) at build_au43cnsvyw2rwctsxb5mg4cmw$_run_closure4.doCall(/Users/mihajlovic/Documents/repos/Backend/dbmigration/build.gradle:52) 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:497) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015) at groovy.lang.Closure.call(Closure.java:423) at groovy.lang.Closure.call(Closure.java:439) at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:558) at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:539) at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77) at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63) at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62) at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23) at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68) at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62) at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55) at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149) at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106) at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86) at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90) at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28) at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:50) at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:27) at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40) at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169) at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237) at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210) at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35) at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24) at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206) at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169) at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33) at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22) at org.gradle.launcher.Main.doAction(Main.java:33) at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45) 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:497) at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54) at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35) at org.gradle.launcher.GradleMain.main(GradleMain.java:23) Caused by: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:580) at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:436) at liquibase.ext.hibernate.database.HibernateSpringDatabase.buildConfigurationFromScanning(HibernateSpringDatabase.java:227) at liquibase.ext.hibernate.database.HibernateSpringDatabase.buildConfiguration(HibernateSpringDatabase.java:55) at liquibase.ext.hibernate.database.HibernateDatabase.setConnection(HibernateDatabase.java:45) at liquibase.database.DatabaseFactory.findCorrectDatabaseImplementation(DatabaseFactory.java:123) at liquibase.database.DatabaseFactory.openDatabase(DatabaseFactory.java:143) at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:50) ... 140 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:577) ... 147 more 

Si je comprends bien, le problème est que Liquibase exige que toutes les classes d’entité soient chargées dans le classpath de gradle, mais comme les classes Java sont simplement compilées ou n’ont pas été compilées, ce n’est pas le cas, d’où le message d’erreur.

Je peux corriger cette erreur en construisant le projet en deux étapes:

  1. comstackJava d’abord la tâche comstackJava pour construire les classes d’entité.
  2. Une fois cela fait, je peux effectuer une build normale – maintenant sans aucun problème.

Cependant, la construction du projet en deux étapes est assez fastidieuse. Est-il possible de contourner ce problème pour le construire en une seule étape?

Mon build.gradle ressemble actuellement à ceci:

 buildscript { ext { springBootVersion = '1.2.3.RELEASE' } repositories { mavenCentral() files 'build/classes/main' } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") classpath("io.spring.gradle:dependency-management-plugin:0.5.0.RELEASE") classpath("org.liquibase:liquibase-gradle-plugin:1.1.0") classpath("mysql:mysql-connector-java:5.1.35") classpath('org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final') classpath('org.liquibase.ext:liquibase-hibernate4:3.5') classpath('org.springframework.data:spring-data-jpa:1.8.0.RELEASE') classpath files('build/classes/main/') } } apply plugin: 'org.liquibase.gradle' apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'idea' apply plugin: 'spring-boot' apply plugin: 'io.spring.dependency-management' apply plugin: 'war' war { baseName = 'example' version = '0.0.1-SNAPSHOT' } sourceCompatibility = 1.8 targetCompatibility = 1.8 repositories { mavenCentral() flatDir { dirs 'libs' } } configurations { providedRuntime } dependencies { comstack("org.springframework.boot:spring-boot-starter-data-jpa") comstack("org.springframework.boot:spring-boot-starter-web") comstack("org.apache.commons:commons-lang3:3.0") comstack("mysql:mysql-connector-java:5.1.35") comstack('org.liquibase:liquibase-core:3.3.5') providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") testComstack("org.springframework.boot:spring-boot-starter-test") } liquibase { activities { main { changeLogFile 'src/main/resources/db/changelog/db.changelog-master.xml' url 'jdbc:mysql://localhost:3306/Example' username 'root' password '' referenceDriver 'liquibase.ext.hibernate.database.connection.HibernateDriver' referenceUrl 'hibernate:spring:com.example.app.domain?dialect=org.hibernate.dialect.MySQL5Dialect' } } runList = 'main' } eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7' } } task wrapper(type: Wrapper) { gradleVersion = '2.4' } 

Je l’ai finalement compris! Vous pouvez utiliser le type Exec pour exécuter des commandes dans la ligne de commande qui démarre ensuite un nouveau processus. Vous pouvez trouver plus d’informations dans la documentation .

Voici la solution avec laquelle je me suis retrouvé:

 task updateChangeLog(type: Exec) { commandLine 'gradle', 'diffChangeLog' } updateChangeLog.dependsOn comstackJava 

Cela démarre un nouveau processus de graduation séparé avec ma tâche diffChangeLog .

Vous pouvez définir la tâche Liquibase comme ceci:

 task liquibase(type: JavaExec, depends: build) { classpath = sourceSets.main.runtimeClasspath ... }