Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,32 @@ Then create a run a MigrationRunner. When running the database connection can ei
runner.run();
```


### Run from ebean with JDBC migrations

Migration supports two modes how to run automatically on ebean server start:

- Run as AutoRunner (controlled by `ebean.migration.run = true`)
- Run as Ebean plugin (controlled by `ebean.migration.plugin.run = true`)

To run as plugin, you need the additional dependency to `ebean-migration-db`.

In the AutoRunner mode, you only have a `MigrationContext` that provides access to the current connection.
When the plugin is used, you have a `MigrationContextDb` in your JDBC migrations and you can access the current transaction
and the ebean server. This is useful to make queries with the ebean server:
```java
public void migrate(MigrationContext context) throws SQLException {
Database db = ((MigrationContextDb) context).database();
db.findDto(...)
}
```


**Important**:
- do not use `DB.getDefault()` at this stage
- do not create new transactions (or committing existing one)
- be aware that the DB layout may not match to your entities (use `db.findDto` instead of `db.find`)

## Notes:
MigrationConfig migrationPath is the root path (classpath or filesystem) where the migration scripts are searched for.

Expand Down
169 changes: 169 additions & 0 deletions ebean-migration-db/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.avaje</groupId>
<artifactId>java11-oss</artifactId>
<version>3.12</version>
<relativePath />
</parent>

<groupId>io.ebean</groupId>
<artifactId>ebean-migration-db</artifactId>
<version>14.0.1-SNAPSHOT</version>

<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean-migration.git</developerConnection>
<tag>HEAD</tag>
</scm>

<properties>
<nexus.staging.autoReleaseAfterClose>true</nexus.staging.autoReleaseAfterClose>
<surefire.useModulePath>false</surefire.useModulePath>
</properties>

<dependencies>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>14.0.1-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.0</version>
<scope>provided</scope>
</dependency>


<dependency>
<groupId>io.avaje</groupId>
<artifactId>classpath-scanner</artifactId>
<version>7.1</version>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.25.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.220</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>9.4.1.jre8</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.4.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.nuodb.jdbc</groupId>
<artifactId>nuodb-jdbc</artifactId>
<version>22.0.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>11.5.6.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.0.6</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<!-- Note: Using ojdbc10 here will affect loading other drivers on jdk8,
because the driverManager will stop on first load error and stops loading
other drivers -->
<artifactId>ojdbc8</artifactId>
<version>19.12.0.0</version>
<scope>test</scope>
</dependency>

<!--
mvn install:install-file -Dfile=/some/path/to/ojdbc7.jar -DgroupId=oracle \
-DartifactId=oracle-jdbc -Dversion=7.0 -Dpackaging=jar
-->
<!-- <dependency>-->
<!-- <groupId>oracle</groupId>-->
<!-- <artifactId>oracle-jdbc</artifactId>-->
<!-- <version>8.0</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->

<dependency>
<groupId>org.avaje.composite</groupId>
<artifactId>logback</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test-containers</artifactId>
<version>7.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.avaje</groupId>
<artifactId>junit</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>8.0</version>
<scope>test</scope>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.33</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:13.25.0</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.ebean.migration.db;

import io.ebean.Database;
import io.ebean.Transaction;
import io.ebean.migration.MigrationContext;

/**
* @author Roland Praml, FOCONIS AG
*/
public interface MigrationContextDb extends MigrationContext {
public Transaction transaction();

public Database database();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHECKME: Should I add "Transaction" and "Database" in MigrationContext (means that ebean-migration will get a dependency to ebean-api)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.ebean.migration.db;

import io.ebean.migration.MigrationConfig;
import io.ebean.plugin.Plugin;
import io.ebean.plugin.SpiServer;

/**
* @author Roland Praml, FOCONIS AG
*/
public class MigrationPlugin implements Plugin {
private MigrationConfig config = new MigrationConfig();
private SpiServer server;

@Override
public void configure(SpiServer server) {
config.setName(server.name());
config.load(server.config().getProperties());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHECKME:

Ebean transfers some values form the DatabaseConfig

      final String dbSchema = config.getDbSchema();
      migrationRunner.setDefaultDbSchema(dbSchema); // mig: schema, setCurrentSchema
      Platform platform = config.getDatabasePlatform().platform();
      migrationRunner.setBasePlatform(platform.base().name().toLowerCase());  // mig: basePlatform
      migrationRunner.setPlatform(platform.name().toLowerCase()); // mig: platform or platformName

Would mean that some properties have to be migrated

this.server = server;
if (server.config().isRunMigration() && config.isPluginRun()) {
throw new UnsupportedOperationException("You cannot enable both 'migration.run' and 'migration.plugin.run'");
}
}

@Override
public void online(boolean online) {
if (online && config.isPluginRun()) {
new MigrationRunnerDb(config, server).run();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHECKME: online might be too early. If we decide to implement this as plugin we might need some lifecycles in the Plugin api (e.g. a postOnline method)

}
}

@Override
public void shutdown() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.ebean.migration.db;

import io.ebean.Database;
import io.ebean.Transaction;
import io.ebean.migration.MigrationConfig;
import io.ebean.migration.MigrationResource;
import io.ebean.migration.MigrationRunner;

import java.util.List;

/**
* Runs the default checkState and run method on a current ebean server.
*
* @author Roland Praml, FOCONIS AG
*/
public class MigrationRunnerDb extends MigrationRunner {
private final Database db;

public MigrationRunnerDb(MigrationConfig migrationConfig, Database db) {
super(migrationConfig);
this.db = db;
}

/**
* Return the migrations that would be applied if the migration is run.
*/
@Override
public List<MigrationResource> checkState() {
try (Transaction txn = db.beginTransaction()) {
return checkState(new TransactionBasedMigrationContext(migrationConfig, txn, db));
}
}

/**
* Run the migrations if there are any that need running.
*/
@Override
public void run() {
try (Transaction txn = db.beginTransaction()) {
run(new TransactionBasedMigrationContext(migrationConfig, txn, db));
// No commit here!
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.ebean.migration.db;

import io.ebean.Database;
import io.ebean.Transaction;
import io.ebean.migration.MigrationConfig;
import io.ebean.migration.MigrationContext;

import java.sql.Connection;
import java.sql.SQLException;

/**
* A default implementation of the MigrationContext.
*
* @author Roland Praml, FOCONIS AG
*/
class TransactionBasedMigrationContext implements MigrationContextDb {
private final Transaction transaction;
private final String migrationPath;
private final String platform;
private final String basePlatform;
private final Database database;

TransactionBasedMigrationContext(MigrationConfig config, Transaction transaction, Database database) {
this.transaction = transaction;
this.migrationPath = config.getMigrationPath();
this.platform = config.getPlatform();
this.basePlatform = config.getBasePlatform();
this.database = database;
}

@Override
public Connection connection() {
return transaction.connection();
}

@Override
public String migrationPath() {
return migrationPath;
}

@Override
public String platform() {
return platform;
}

@Override
public String basePlatform() {
return basePlatform;
}

@Override
public void commit() throws SQLException {
// we must not use txn.commit here, as this closes the underlying connection, which is needed for logicalLock etc.
transaction.commitAndContinue();
}

@Override
public Transaction transaction() {
return transaction;
}

@Override
public Database database() {
return database;
}
}
13 changes: 13 additions & 0 deletions ebean-migration-db/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module io.ebean.migration.db {

exports io.ebean.migration.db;

requires transitive java.sql;
requires transitive io.avaje.applog;
requires transitive io.avaje.classpath.scanner;
requires transitive io.ebean.ddl.runner;
requires static io.ebean.api;
requires io.ebean.migration;
uses io.ebean.plugin.Plugin;
provides io.ebean.plugin.Plugin with io.ebean.migration.db.MigrationPlugin;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.ebean.migration.db.MigrationPlugin
Loading