diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayDevConsoleProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayDevConsoleProcessor.java index 35154bf7f78205..f2400e8671d120 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayDevConsoleProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayDevConsoleProcessor.java @@ -1,34 +1,22 @@ package io.quarkus.flyway; import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT; -import static java.util.List.of; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; -import org.eclipse.microprofile.config.ConfigProvider; - -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpResponseStatus; import io.quarkus.agroal.spi.JdbcInitialSQLGeneratorBuildItem; import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; -import io.quarkus.dev.config.CurrentConfig; -import io.quarkus.dev.console.DevConsoleManager; -import io.quarkus.devconsole.runtime.spi.DevConsolePostHandler; import io.quarkus.devconsole.spi.DevConsoleRouteBuildItem; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayContainersSupplier; -import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; import io.quarkus.flyway.runtime.devconsole.FlywayDevConsoleRecorder; -import io.vertx.core.MultiMap; -import io.vertx.ext.web.RoutingContext; public class FlywayDevConsoleProcessor { @@ -42,71 +30,21 @@ public DevConsoleRuntimeTemplateInfoBuildItem collectBeanInfo( @BuildStep @Record(value = RUNTIME_INIT, optional = true) DevConsoleRouteBuildItem invokeEndpoint(FlywayDevConsoleRecorder recorder) { - return new DevConsoleRouteBuildItem("datasources", "POST", recorder.handler()); + return new DevConsoleRouteBuildItem("datasources", "POST", recorder.datasourcesHandler()); } @BuildStep - DevConsoleRouteBuildItem invokeEndpoint(List generatorBuildItem, + @Record(value = RUNTIME_INIT, optional = true) + DevConsoleRouteBuildItem invokeEndpoint(FlywayDevConsoleRecorder recorder, + List generatorBuildItem, FlywayBuildTimeConfig buildTimeConfig, CurateOutcomeBuildItem curateOutcomeBuildItem) { - return new DevConsoleRouteBuildItem("create-initial-migration", "POST", new DevConsolePostHandler() { - @Override - protected void handlePostAsync(RoutingContext event, MultiMap form) throws Exception { - String name = form.get("datasource"); - JdbcInitialSQLGeneratorBuildItem found = null; - for (var i : generatorBuildItem) { - if (i.getDatabaseName().equals(name)) { - found = i; - break; - } - } - if (found == null) { - flashMessage(event, "Unable to find SQL generator"); - return; - } - FlywayDataSourceBuildTimeConfig config = buildTimeConfig.getConfigForDataSourceName(name); - if (config.locations.isEmpty()) { - flashMessage(event, "Datasource has no locations configured"); - return; - } - System.out.println(found.getSqlSupplier().get()); - - List resourcesDir = DevConsoleManager.getHotReplacementContext().getResourcesDir(); - if (resourcesDir.isEmpty()) { - flashMessage(event, "No resource directory found"); - return; - } - - // In the current project only - Path path = resourcesDir.get(0); - - Path migrationDir = path.resolve(config.locations.get(0)); - Files.createDirectories(migrationDir); - Path file = migrationDir.resolve( - "V1.0.0__" + curateOutcomeBuildItem.getApplicationModel().getAppArtifact().getArtifactId() + ".sql"); - Files.writeString(file, found.getSqlSupplier().get()); - flashMessage(event, file + " was created"); - Map newConfig = new HashMap<>(); - if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.baseline-on-migrate", String.class).isEmpty()) { - newConfig.put("quarkus.flyway.baseline-on-migrate", "true"); - } - if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.migrate-at-start", String.class).isEmpty()) { - newConfig.put("quarkus.flyway.migrate-at-start", "true"); - } - for (var profile : of("test", "dev")) { - if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.clean-at-start", String.class).isEmpty()) { - newConfig.put("%" + profile + ".quarkus.flyway.clean-at-start", "true"); - } - } - CurrentConfig.EDITOR.accept(newConfig); - //force a scan, to make sure everything is up-to-date - DevConsoleManager.getHotReplacementContext().doScan(true); - flashMessage(event, "Initial migration created, Flyway will now manage this datasource"); - event.response().setStatusCode(HttpResponseStatus.SEE_OTHER.code()).headers() - .set(HttpHeaderNames.LOCATION, - event.request().absoluteURI().replace("create-initial-migration", "datasources")); - event.response().end(); - } - }); + Map> initialSqlSuppliers = new HashMap<>(); + for (JdbcInitialSQLGeneratorBuildItem buildItem : generatorBuildItem) { + initialSqlSuppliers.put(buildItem.getDatabaseName(), buildItem.getSqlSupplier()); + } + return new DevConsoleRouteBuildItem("create-initial-migration", "POST", + recorder.createInitialMigrationHandler(buildTimeConfig, + curateOutcomeBuildItem.getApplicationModel().getAppArtifact().getArtifactId(), initialSqlSuppliers)); } } diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/devconsole/FlywayDevConsoleRecorder.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/devconsole/FlywayDevConsoleRecorder.java index 1871cd18eeb150..8b99b521a63a58 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/devconsole/FlywayDevConsoleRecorder.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/devconsole/FlywayDevConsoleRecorder.java @@ -1,13 +1,28 @@ package io.quarkus.flyway.runtime.devconsole; +import static java.util.List.of; + +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import org.eclipse.microprofile.config.ConfigProvider; import org.flywaydb.core.Flyway; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.quarkus.dev.config.CurrentConfig; +import io.quarkus.dev.console.DevConsoleManager; import io.quarkus.devconsole.runtime.spi.DevConsolePostHandler; import io.quarkus.devconsole.runtime.spi.FlashScopeUtil.FlashMessageStatus; +import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayContainer; import io.quarkus.flyway.runtime.FlywayContainersSupplier; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; import io.quarkus.runtime.annotations.Recorder; import io.vertx.core.Handler; import io.vertx.core.MultiMap; @@ -16,7 +31,7 @@ @Recorder public class FlywayDevConsoleRecorder { - public Handler handler() { + public Handler datasourcesHandler() { return new DevConsolePostHandler() { @Override protected void handlePost(RoutingContext event, MultiMap form) throws Exception { @@ -44,4 +59,62 @@ protected void handlePost(RoutingContext event, MultiMap form) throws Exception } }; } + + public Handler createInitialMigrationHandler(FlywayBuildTimeConfig buildTimeConfig, + String artifactId, + Map> initialSqlSuppliers) { + return new DevConsolePostHandler() { + @Override + protected void handlePostAsync(RoutingContext event, MultiMap form) throws Exception { + String name = form.get("datasource"); + Supplier found = initialSqlSuppliers.get(name); + if (found == null) { + flashMessage(event, "Unable to find SQL generator"); + return; + } + FlywayDataSourceBuildTimeConfig config = buildTimeConfig.getConfigForDataSourceName(name); + if (config.locations.isEmpty()) { + flashMessage(event, "Datasource has no locations configured"); + return; + } + System.out.println(found.get()); + + List resourcesDir = DevConsoleManager.getHotReplacementContext().getResourcesDir(); + if (resourcesDir.isEmpty()) { + flashMessage(event, "No resource directory found"); + return; + } + + // In the current project only + Path path = resourcesDir.get(0); + + Path migrationDir = path.resolve(config.locations.get(0)); + Files.createDirectories(migrationDir); + Path file = migrationDir.resolve( + "V1.0.0__" + artifactId + ".sql"); + Files.writeString(file, found.get()); + flashMessage(event, file + " was created"); + Map newConfig = new HashMap<>(); + if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.baseline-on-migrate", String.class).isEmpty()) { + newConfig.put("quarkus.flyway.baseline-on-migrate", "true"); + } + if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.migrate-at-start", String.class).isEmpty()) { + newConfig.put("quarkus.flyway.migrate-at-start", "true"); + } + for (var profile : of("test", "dev")) { + if (ConfigProvider.getConfig().getOptionalValue("quarkus.flyway.clean-at-start", String.class).isEmpty()) { + newConfig.put("%" + profile + ".quarkus.flyway.clean-at-start", "true"); + } + } + CurrentConfig.EDITOR.accept(newConfig); + //force a scan, to make sure everything is up-to-date + DevConsoleManager.getHotReplacementContext().doScan(true); + flashMessage(event, "Initial migration created, Flyway will now manage this datasource"); + event.response().setStatusCode(HttpResponseStatus.SEE_OTHER.code()).headers() + .set(HttpHeaderNames.LOCATION, + event.request().absoluteURI().replace("create-initial-migration", "datasources")); + event.response().end(); + } + }; + } } diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevConsoleProcessor.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevConsoleProcessor.java index 9530aa4463c01e..722117fdd8f038 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevConsoleProcessor.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevConsoleProcessor.java @@ -1,20 +1,11 @@ package io.quarkus.hibernate.orm.deployment.dev; -import java.util.List; -import java.util.function.Supplier; - -import io.quarkus.agroal.spi.JdbcInitialSQLGeneratorBuildItem; import io.quarkus.deployment.IsDevelopment; -import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.BuildSteps; import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; -import io.quarkus.dev.console.DevConsoleManager; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; import io.quarkus.hibernate.orm.deployment.HibernateOrmEnabled; -import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem; -import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil; -import io.quarkus.hibernate.orm.runtime.dev.HibernateOrmDevInfoCreateDDLSupplier; import io.quarkus.hibernate.orm.runtime.dev.HibernateOrmDevInfoSupplier; @BuildSteps(onlyIf = { HibernateOrmEnabled.class, IsDevelopment.class }) @@ -28,30 +19,4 @@ public DevConsoleRuntimeTemplateInfoBuildItem exposeInfo(CurateOutcomeBuildItem curateOutcomeBuildItem); } - // FIXME migrate to a JsonRpcService - @BuildStep - void handleInitialSql(List persistenceUnitDescriptorBuildItems, - BuildProducer runtimeInfoProducer, - BuildProducer initialSQLGeneratorBuildItemBuildProducer, - CurateOutcomeBuildItem curateOutcomeBuildItem) { - for (PersistenceUnitDescriptorBuildItem puDescriptor : persistenceUnitDescriptorBuildItems) { - String puName = puDescriptor.getPersistenceUnitName(); - String dsName = puDescriptor.getConfig().getDataSource().orElse(PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME); - DevConsoleRuntimeTemplateInfoBuildItem devConsoleRuntimeTemplateInfoBuildItem = new DevConsoleRuntimeTemplateInfoBuildItem( - "create-ddl." + puName, new HibernateOrmDevInfoCreateDDLSupplier(puName), this.getClass(), - curateOutcomeBuildItem); - runtimeInfoProducer.produce(devConsoleRuntimeTemplateInfoBuildItem); - initialSQLGeneratorBuildItemBuildProducer - .produce(new JdbcInitialSQLGeneratorBuildItem(dsName, new Supplier() { - @Override - public String get() { - return DevConsoleManager.getTemplateInfo() - .get(devConsoleRuntimeTemplateInfoBuildItem.getGroupId() + "." - + devConsoleRuntimeTemplateInfoBuildItem.getArtifactId()) - .get(devConsoleRuntimeTemplateInfoBuildItem.getName()).toString(); - } - })); - } - } - } diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevUIProcessor.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevUIProcessor.java index 2e23a239bf4284..715e22ec02ce4e 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevUIProcessor.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/dev/HibernateOrmDevUIProcessor.java @@ -1,12 +1,19 @@ package io.quarkus.hibernate.orm.deployment.dev; +import java.util.List; + +import io.quarkus.agroal.spi.JdbcInitialSQLGeneratorBuildItem; import io.quarkus.deployment.IsDevelopment; +import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.BuildSteps; import io.quarkus.devui.spi.JsonRPCProvidersBuildItem; import io.quarkus.devui.spi.page.CardPageBuildItem; import io.quarkus.devui.spi.page.Page; import io.quarkus.hibernate.orm.deployment.HibernateOrmEnabled; +import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem; +import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil; +import io.quarkus.hibernate.orm.runtime.dev.HibernateOrmDevInfoCreateDDLSupplier; import io.quarkus.hibernate.orm.runtime.dev.HibernateOrmDevJsonRpcService; @BuildSteps(onlyIf = { HibernateOrmEnabled.class, IsDevelopment.class }) @@ -40,4 +47,15 @@ JsonRPCProvidersBuildItem createJsonRPCService() { return new JsonRPCProvidersBuildItem(NAME, HibernateOrmDevJsonRpcService.class); } + @BuildStep + void handleInitialSql(List persistenceUnitDescriptorBuildItems, + BuildProducer initialSQLGeneratorBuildItemBuildProducer) { + for (PersistenceUnitDescriptorBuildItem puDescriptor : persistenceUnitDescriptorBuildItems) { + String puName = puDescriptor.getPersistenceUnitName(); + String dsName = puDescriptor.getConfig().getDataSource().orElse(PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME); + initialSQLGeneratorBuildItemBuildProducer + .produce(new JdbcInitialSQLGeneratorBuildItem(dsName, new HibernateOrmDevInfoCreateDDLSupplier(puName))); + } + } + } diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/dev/HibernateOrmDevJsonRpcService.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/dev/HibernateOrmDevJsonRpcService.java index 9110458fa080c7..b9b353a0c14b73 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/dev/HibernateOrmDevJsonRpcService.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/dev/HibernateOrmDevJsonRpcService.java @@ -1,8 +1,9 @@ package io.quarkus.hibernate.orm.runtime.dev; -import io.quarkus.arc.profile.IfBuildProfile; import jakarta.enterprise.context.ApplicationScoped; +import io.quarkus.arc.profile.IfBuildProfile; + @ApplicationScoped @IfBuildProfile("dev") public class HibernateOrmDevJsonRpcService {