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

Extension for Flyway #1575 #1649

Merged
merged 1 commit into from
Apr 2, 2019
Merged
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
11 changes: 11 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
<jprocesses.version>1.6.5</jprocesses.version>
<jboss-logmanager.version>1.0.2</jboss-logmanager.version>
<jetty.version>9.4.15.v20190215</jetty.version>
<flyway.version>5.2.4</flyway.version>
<yasson.version>1.0.3</yasson.version>
</properties>

Expand Down Expand Up @@ -250,6 +251,11 @@
<artifactId>quarkus-elytron-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
Expand Down Expand Up @@ -1695,6 +1701,11 @@
<version>${swagger-ui.version}</version>
</dependency>

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>${flyway.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
19 changes: 16 additions & 3 deletions build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,16 @@
<artifactId>quarkus-kubernetes-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway-deployment</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Miscellaneous -->
<dependency>
Expand Down Expand Up @@ -699,7 +709,8 @@
</goals>
<phase>compile</phase>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
</deployment>
</configuration>
</execution>
</executions>
Expand All @@ -719,8 +730,10 @@
<bannedDependencies>
<excludes>
<!-- Use javax.annotation-api -->
<exclude>org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec</exclude>
<exclude>org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec</exclude>
<exclude>org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec
</exclude>
<exclude>org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec
</exclude>
<!-- use our jboss-logmanager -->
<exclude>org.jboss.logging:jboss-logmanager</exclude>
<!-- We don't want all the API's in one jar-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public final class FeatureBuildItem extends MultiBuildItem {
public static final String UNDERTOW_WEBSOCKETS = "undertow-websockets";
public static final String VERTX = "vertx";
public static final String VERTX_WEB = "vertx-web";
public static final String FLYWAY = "flyway";

private final String info;

Expand Down
10 changes: 10 additions & 0 deletions devtools/common/src/main/filtered/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -393,5 +393,15 @@
],
"groupId": "io.quarkus",
"artifactId": "quarkus-vertx"
},
{
"name": "Flyway",
"labels": [
"flyway",
"database",
"data"
],
"groupId": "io.quarkus",
"artifactId": "quarkus-flyway"
}
]
103 changes: 103 additions & 0 deletions docs/src/main/asciidoc/flyway-guide.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////

include::./attributes.adoc[]
= {project-name} - Using Flyway
:migrations-path: src/main/resources/db/migration
:config-file: application.properties

https://flywaydb.org/[Flyway] is a popular database migration tool that is commonly used in JVM environments.

{project-name} provides first class support for using Flyway in native mode as will be explained in this guide.

[NOTE]
--
You only need to add this extension if your are doing native compilation with {project-name}.
Otherwise, you can use Flyway by just adding it as a dependency in the `pom.xml` and run the {project-name} app in JVM mode.
--

== Setting up native compilation support for Flyway

To get native compilation working in {project-name} with Flyway, you just need to:

* add your migrations to the `{migrations-path}` folder as you usually do with Flyway

NOTE: The migrations location is not configurable in native mode. The Flyway extension will always look for migrations in the default path.

* create your `Flyway` object and run your migration as you normally do

In your `pom.xml`, add the following dependencies:

* the Flyway extension
* your JDBC driver extension (`quarkus-jdbc-postgresql`, `quarkus-jdbc-h2`, `quarkus-jdbc-mariadb`, ...)

[source,xml]
--
<dependencies>
<!-- Flyway specific dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>

<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
</dependencies>
--

You can use MP-config to get any relevant configuration properties you may need by adding them to the `{config-file}` file.

[source,properties]
--
# configure your datasource
datasource.url: jdbc:postgresql://localhost:5432/mydatabase
datasource.username: sarah
datasource.password: connor
--

Note that you can use any name for these configuration properties.

Add a SQL migration to the default folder following the Flyway naming conventions: `{migrations-path}/V1.0.0__Quarkus.sql`

[source,sql]
--
CREATE TABLE quarkus
(
id INT,
name VARCHAR(20)
);
INSERT INTO quarkus(id, name)
VALUES (1, 'QUARKED');
--

Now you can create your `Flyway` object as you usually do:

[source,java]
--
@ApplicationScoped
public class MigrationService {

@ConfigProperty(name = "datasource.url") <1>
String dbURL;
@ConfigProperty(name = "datasource.username")
String dbUser;
@ConfigProperty(name = "datasource.password")
String dbPassword;

public void migrate() {
Flyway flyway = Flyway.configure()
.dataSource(dbURL, dbUser, dbPassword)
.load(); <2>
flyway.migrate();
}
}
--

<1> Inject your config properties as needed
<2> Create the `Flyway` object and enjoy
58 changes: 58 additions & 0 deletions extensions/flyway/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019 Red Hat, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-flyway-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-flyway-deployment</artifactId>
<name>Quarkus - Flyway - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.quarkus.flyway;

import static java.nio.file.Files.walk;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;

import org.jboss.logging.Logger;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.substrate.SubstrateResourceBuildItem;

class FlywayBuildStep {

private static final String FLYWAY_DATABASES_PATH_ROOT = "org/flywaydb/core/internal/database";
private static final String FLYWAY_METADATA_TABLE_FILENAME = "createMetaDataTable.sql";
private static final String[] FLYWAY_DATABASES_WITH_SQL_FILE = {
"cockroachdb",
"derby",
"h2",
"hsqldb",
"mysql",
"oracle",
"postgresql",
"redshift",
"saphana",
"sqlite",
"sybasease"
};

private static final Logger LOGGER = Logger.getLogger(FlywayBuildStep.class);

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FeatureBuildItem.FLYWAY);
}

@Record(ExecutionTime.STATIC_INIT)
@BuildStep(providesCapabilities = "io.quarkus.flyway")
void registerSubstrateResources(
BuildProducer<SubstrateResourceBuildItem> resource,
ApplicationArchivesBuildItem appArchives) throws IOException, URISyntaxException {
Path root = appArchives.getRootArchive().getArchiveRoot();
List<String> resources = generateDatabasesSQLFiles();
resources.addAll(discoverApplicationMigrations(root));
resource.produce(new SubstrateResourceBuildItem(resources.toArray(new String[0])));
}

private List<String> discoverApplicationMigrations(Path root) throws IOException, URISyntaxException {
List<String> resources = new ArrayList<>();
try {
// TODO: this should be configurable, using flyway default
String location = "db/migration";
Enumeration<URL> migrations = Thread.currentThread().getContextClassLoader().getResources(location);
while (migrations.hasMoreElements()) {
URL path = migrations.nextElement();
LOGGER.info("Adding application migrations in path: " + path);
List<String> applicationMigrations = walk(Paths.get(path.toURI()))
.filter(Files::isRegularFile)
.map(it -> Paths.get(location, it.getFileName().toString()).toString())
.peek(it -> LOGGER.debug("Discovered: " + it))
.collect(Collectors.toList());
resources.addAll(applicationMigrations);
}
return resources;
} catch (IOException | URISyntaxException e) {
throw e;
}
}

private List<String> generateDatabasesSQLFiles() {
List<String> result = new ArrayList<>();
for (String database : FLYWAY_DATABASES_WITH_SQL_FILE) {
String filePath = FLYWAY_DATABASES_PATH_ROOT + "/" + database + "/" + FLYWAY_METADATA_TABLE_FILENAME;
result.add(filePath);
LOGGER.debug("Adding flyway internal migration: " + filePath);
}
return result;
}
}
Loading