package bo.gotthardt.ebean; import com.avaje.ebean.EbeanServer; import com.avaje.ebean.EbeanServerFactory; import com.avaje.ebean.config.ServerConfig; import com.codahale.metrics.MetricRegistry; import io.dropwizard.Configuration; import io.dropwizard.cli.ConfiguredCommand; import io.dropwizard.db.DataSourceFactory; import io.dropwizard.db.ManagedDataSource; import io.dropwizard.migrations.CloseableLiquibase; import io.dropwizard.setup.Bootstrap; import liquibase.diff.DiffResult; import liquibase.diff.compare.CompareControl; import liquibase.diff.output.DiffOutputControl; import liquibase.diff.output.changelog.DiffToChangeLog; import liquibase.exception.LiquibaseException; import net.sourceforge.argparse4j.inf.Namespace; import java.sql.SQLException; /** * Dropwizard command for creating Liquibase database changelogs. * @param <T> */ public class DbDiffCommand<T extends Configuration & HasDatabaseConfiguration> extends ConfiguredCommand<T> { public DbDiffCommand() { super("dbdiff", "Creates a Liquibase changelog that migrates from the current database to one created freshly by Ebean.\nAn empty database named 'migrationdiff' must exist."); } @Override protected void run(Bootstrap<T> bootstrap, Namespace namespace, T configuration) throws Exception { // The existing database with migrations managed by Liquibase. DataSourceFactory outdatedDb = configuration.getDatabaseConfig(); try (CloseableLiquibase outdatedLiquibase = createLiquibase(outdatedDb)) { // A temporary database that starts out empty and then gets the autogenerated Ebean table definitions applied. DataSourceFactory freshDb = EbeanConfigUtils.clone(outdatedDb); String url = outdatedDb.getUrl(); freshDb.setUrl(url.substring(0, url.lastIndexOf("/")) + "/migrationdiff"); // Creating the Ebean server makes it apply its table definitions to the database immediately. ServerConfig serverConfig = EbeanConfigUtils.createServerConfig(freshDb); serverConfig.setDdlGenerate(true); serverConfig.setDdlRun(true); EbeanServer ebeanServer = EbeanServerFactory.create(serverConfig); try (CloseableLiquibase freshLiquibase = createLiquibase(freshDb)) { // Create and print the differences between the two databases, i.e. a migration that should be applied to update to the newest Ebean definitions. DiffResult diff = outdatedLiquibase.diff(freshLiquibase.getDatabase(), outdatedLiquibase.getDatabase(), CompareControl.STANDARD); DiffToChangeLog diffToChangeLog = new DiffToChangeLog(diff, new DiffOutputControl(false, false, true)); diffToChangeLog.print(System.out); } } } private static CloseableLiquibase createLiquibase(DataSourceFactory dbConfig) throws SQLException, LiquibaseException { ManagedDataSource dataSource = dbConfig.build(new MetricRegistry(), "liquibase"); return new CloseableLiquibase(dataSource); } }