diff --git a/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices.adoc b/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices.adoc index 95883d1d..31cd5553 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices.adoc @@ -247,6 +247,23 @@ endif::add-copy-button-to-env-var[] a|`import-only`, `export-only`, `import-export` | +a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments[`quarkus.google.cloud.devservices.firebase.emulator.cli.experiments`]## + +[.description] +-- +Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable command line option). + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++` +endif::add-copy-button-to-env-var[] +-- +|list of string +| + a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug[`quarkus.google.cloud.devservices.firebase.emulator.cli.debug`]## [.description] diff --git a/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices_quarkus.google.adoc b/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices_quarkus.google.adoc index 95883d1d..31cd5553 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices_quarkus.google.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-google-cloud-firebase-devservices_quarkus.google.adoc @@ -247,6 +247,23 @@ endif::add-copy-button-to-env-var[] a|`import-only`, `export-only`, `import-export` | +a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments[`quarkus.google.cloud.devservices.firebase.emulator.cli.experiments`]## + +[.description] +-- +Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable command line option). + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++` +endif::add-copy-button-to-env-var[] +-- +|list of string +| + a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug[`quarkus.google.cloud.devservices.firebase.emulator.cli.debug`]## [.description] diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceConfig.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceConfig.java index 08b58ab6..6c2d614e 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceConfig.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceConfig.java @@ -1,6 +1,7 @@ package io.quarkiverse.googlecloudservices.firebase.deployment; import java.util.Optional; +import java.util.Set; import io.quarkiverse.googlecloudservices.firebase.deployment.testcontainers.FirebaseEmulatorContainer; import io.quarkus.runtime.annotations.ConfigRoot; @@ -199,6 +200,12 @@ interface Cli { */ Optional importExport(); + /** + * Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable + * command line option). + */ + Optional> experiments(); + /** * Enable firebase emulators debugging. */ diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceProcessor.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceProcessor.java index 3f39cf72..eaae2547 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceProcessor.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseDevServiceProcessor.java @@ -67,7 +67,11 @@ public DevServicesResultBuildItem start(DockerStatusBuildItem dockerStatusBuildI // Try starting the container if conditions are met try { - devService = startContainerIfAvailable(dockerStatusBuildItem, projectConfig, firebaseBuildTimeConfig, + devService = startContainerIfAvailable( + dockerStatusBuildItem, + closeBuildItem, + projectConfig, + firebaseBuildTimeConfig, globalDevServicesConfig.timeout); } catch (Throwable t) { LOGGER.warn("Unable to start Firebase dev service", t); @@ -87,9 +91,11 @@ public DevServicesResultBuildItem start(DockerStatusBuildItem dockerStatusBuildI * @param dockerStatusBuildItem, Docker status * @param config, Configuration for the Firebase service * @param timeout, Optional timeout for starting the service + * @param closeBuildItem * @return Running service item, or null if the service couldn't be started */ private DevServicesResultBuildItem.RunningDevService startContainerIfAvailable(DockerStatusBuildItem dockerStatusBuildItem, + CuratedApplicationShutdownBuildItem closeBuildItem, FirebaseDevServiceProjectConfig projectConfig, FirebaseDevServiceConfig config, Optional timeout) { @@ -111,7 +117,7 @@ private DevServicesResultBuildItem.RunningDevService startContainerIfAvailable(D return null; } - return startContainer(dockerStatusBuildItem, projectConfig, config, timeout); + return startContainer(closeBuildItem, projectConfig, config, timeout); } private boolean isEnabled(FirebaseDevServiceConfig config) { @@ -125,12 +131,12 @@ private boolean isEnabled(FirebaseDevServiceConfig config) { /** * Starts the Pub/Sub emulator container with provided configuration. * - * @param dockerStatusBuildItem, Docker status + * @param closeBuildItem The close build item to handle shutdown of the container * @param config, Configuration for the Firebase service * @param timeout, Optional timeout for starting the service * @return Running service item, or null if the service couldn't be started */ - private DevServicesResultBuildItem.RunningDevService startContainer(DockerStatusBuildItem dockerStatusBuildItem, + private DevServicesResultBuildItem.RunningDevService startContainer(CuratedApplicationShutdownBuildItem closeBuildItem, FirebaseDevServiceProjectConfig projectConfig, FirebaseDevServiceConfig config, Optional timeout) { @@ -155,6 +161,8 @@ private DevServicesResultBuildItem.RunningDevService startContainer(DockerStatus .forEach((e, h) -> LOGGER.info("Google Cloud emulator config property " + e + " set to " + h)); } + closeBuildItem.addCloseTask(emulatorContainer::close, true); + // Return running service item with container details return new DevServicesResultBuildItem.RunningDevService(FirebaseBuildSteps.FEATURE, emulatorContainer.getContainerId(), diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilder.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilder.java index e3ed09aa..e356965a 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilder.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilder.java @@ -79,6 +79,7 @@ private void handleCliConfig(FirebaseDevServiceConfig.Firebase.Emulator.Cli cli, cli.javaToolOptions().ifPresent(cliConfig::withJavaToolOptions); cli.emulatorData().map(FirebaseEmulatorConfigBuilder::asPath).ifPresent(cliConfig::withEmulatorData); cli.importExport().ifPresent(cliConfig::withImportExport); + cli.experiments().ifPresent(cliConfig::withExperiments); cli.debug().ifPresent(cliConfig::withDebug); cliConfig.done(); diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java index 740cd2fe..ca3cbfc8 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java @@ -161,6 +161,7 @@ private FirebaseEmulatorContainer.HostingConfig readHosting(Object hosting, Path var publicDir = Optional .ofNullable(hostingMap.get("public")) + .or(() -> Optional.ofNullable(hostingMap.get("source"))) .map(f -> this.resolvePath(f, customFirebaseJson)); LOGGER.debug("Hosting configured with public directory {}", publicDir); diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java index b7506104..bde36472 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java @@ -185,6 +185,7 @@ public record DockerConfig( * @param javaToolOptions The options to pass to the java based emulators * @param emulatorData The path to the directory where to store the emulator data * @param importExport Specify whether to import, export or do both with the emulator data + * @param experiments Firebase experiments to enable on the docker image * @param debug Whether to run with the --debug flag */ public record CliArgumentsConfig( @@ -193,6 +194,7 @@ public record CliArgumentsConfig( Optional javaToolOptions, Optional emulatorData, ImportExport importExport, + Optional> experiments, boolean debug) { public static final CliArgumentsConfig DEFAULT = new CliArgumentsConfig( Optional.empty(), @@ -200,6 +202,7 @@ public record CliArgumentsConfig( Optional.empty(), Optional.empty(), ImportExport.IMPORT_EXPORT, + Optional.of(new HashSet<>()), false); } @@ -609,6 +612,7 @@ public class CliBuilder { private String javaToolOptions; private Path emulatorData; private ImportExport importExport; + private Set experiments; private boolean debug; /** @@ -620,6 +624,7 @@ private CliBuilder() { this.javaToolOptions = Builder.this.cliArguments.javaToolOptions.orElse(null); this.emulatorData = Builder.this.cliArguments.emulatorData.orElse(null); this.importExport = Builder.this.cliArguments.importExport; + this.experiments = Builder.this.cliArguments.experiments.orElse(new HashSet<>()); this.debug = Builder.this.cliArguments.debug; } @@ -690,6 +695,28 @@ public CliBuilder withDebug(boolean debug) { return this; } + /** + * Add the firebase experiments setting + * + * @param experiments The experiments to enable + * @return The builder + */ + public CliBuilder withExperiments(Set experiments) { + this.experiments = new HashSet<>(experiments); + return this; + } + + /** + * Add a single firebase experiment to the set + * + * @param experiment The experiment to add + * @return The builder + */ + public CliBuilder addExperiment(String experiment) { + this.experiments.add(experiment); + return this; + } + /** * Finish the builder * @@ -702,6 +729,7 @@ public Builder done() { Optional.ofNullable(this.javaToolOptions), Optional.ofNullable(this.emulatorData), this.importExport, + Optional.of(this.experiments), this.debug); return Builder.this; } @@ -924,7 +952,7 @@ public FirebaseEmulatorContainer(EmulatorConfig emulatorConfig) { LOGGER.debug("Mounting {} to the container hosting path", hostingPath); // Mount volume for static hosting content - this.withFileSystemBind(hostingPath, containerHostingPath(emulatorConfig), BindMode.READ_ONLY); + this.withFileSystemBind(hostingPath, containerHostingPath(emulatorConfig), BindMode.READ_WRITE); } if (this.services.containsKey(Emulator.CLOUD_FUNCTIONS)) { @@ -938,7 +966,7 @@ public FirebaseEmulatorContainer(EmulatorConfig emulatorConfig) { LOGGER.debug("Mounting {} to the container functions sources path", functionsPath); // Mount volume for functions - this.withFileSystemBind(functionsPath, containerFunctionsPath(emulatorConfig), BindMode.READ_ONLY); + this.withFileSystemBind(functionsPath, containerFunctionsPath(emulatorConfig), BindMode.READ_WRITE); } } @@ -1023,14 +1051,15 @@ public ImageFromDockerfile build() { this.initialSetup(); this.authenticateToFirebase(); this.setupJavaToolOptions(); - this.setupUserAndGroup(); this.downloadEmulators(); - this.addFirebaseJson(); - this.includeFirestoreFiles(); - this.includeStorageFiles(); + this.setupExperiments(); this.setupDataImportExport(); this.setupHosting(); this.setupFunctions(); + this.addFirebaseJson(); + this.includeFirestoreFiles(); + this.includeStorageFiles(); + this.setupUserAndGroup(); this.runExecutable(); return result; @@ -1153,8 +1182,36 @@ private void setupJavaToolOptions() { toolOptions -> dockerBuilder.env("JAVA_TOOL_OPTIONS", toolOptions)); } + private void setupExperiments() { + emulatorConfig.cliArguments.experiments().ifPresent( + experimentsSet -> { + var experiments = String.join(",", experimentsSet); + LOGGER.debug("Firebase experiments found, enabling experiments: {}", experiments); + dockerBuilder.env("FIREBASE_CLI_EXPERIMENTS", String.join(",", experiments)); + }); + } + private void addFirebaseJson() { - dockerBuilder.workDir(FIREBASE_ROOT); + /* + * Workaround for https://github.com/firebase/firebase-tools/issues/5903#issuecomment-1568239576 + * + * Remove the conditional and just set FIREBASE_ROOT as workdir once the upstream bug is fixed. + */ + if (isEmulatorEnabled(Emulator.FIREBASE_HOSTING)) { + var hostingPath = containerHostingPath(emulatorConfig); + + LOGGER.debug( + "Hosting emulator detected. Setting workdir to {} as a workaround for an upstream bug in firebase-tools", + hostingPath); + + dockerBuilder.workDir(hostingPath); + } else { + LOGGER.debug("No hosting emulator detected. Using default workdir"); + dockerBuilder.workDir(FIREBASE_ROOT); + } + /* + * Workaround ends <-- https://github.com/firebase/firebase-tools/issues/5903#issuecomment-1568239576 + */ emulatorConfig.customFirebaseJson().ifPresentOrElse( this::includeCustomFirebaseJson, @@ -1256,6 +1313,8 @@ private void runExecutable() { List arguments = new ArrayList<>(); arguments.add("emulators:start"); + arguments.add("--config"); + arguments.add(FIREBASE_ROOT + "/firebase.json"); emulatorConfig.cliArguments().projectId() .map(id -> "--project") @@ -1268,7 +1327,9 @@ private void runExecutable() { arguments.add("--debug"); } - if (emulatorConfig.cliArguments().importExport.isDoExport()) { + if (emulatorConfig.cliArguments().importExport.isDoImport()) { + LOGGER.debug("Import requested. Importing data on startup"); + emulatorConfig .cliArguments() .emulatorData() @@ -1287,6 +1348,8 @@ private void runExecutable() { } if (emulatorConfig.cliArguments().importExport.isDoExport()) { + LOGGER.debug("Export requested. Saving data on exit"); + emulatorConfig .cliArguments() .emulatorData() @@ -1340,11 +1403,22 @@ public void stop() { * kill (SIGKILL) command instead of a stop (SIGTERM) command. This will kill the container instantly * and prevent firebase from writing the "--export-on-exit" data to the mounted directory. */ + LOGGER.debug("Requesting to stopping the container to give export a chance to finish"); + this.getDockerClient().stopContainerCmd(this.getContainerId()).exec(); + LOGGER.debug("Stopping abd removing the container"); + super.stop(); } + @Override + public void close() { + LOGGER.debug("Emulator is being closed"); + + this.stop(); + } + /** * Configures the Pub/Sub emulator container. */ @@ -1420,6 +1494,10 @@ private void writeOutputFrame(OutputFrame frame, Level level) { } private String getEmulatorEndpoint(Emulator emulator) { + if (emulator.equals(Emulator.CLOUD_STORAGE)) { + return "http://" + this.getHost() + ":" + emulatorPort(emulator); + } + return this.getHost() + ":" + emulatorPort(emulator); } } diff --git a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilderTest.java b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilderTest.java index 49397aca..60febcea 100644 --- a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilderTest.java +++ b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/FirebaseEmulatorConfigBuilderTest.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import java.util.Map; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,6 +38,7 @@ void setUp() { Optional.of("-Xmx"), Optional.of("data"), Optional.of(FirebaseEmulatorContainer.ImportExport.EXPORT_ONLY), + Optional.of(Set.of("webframeworks")), Optional.of(true)), Optional.empty(), new TestUI( @@ -89,6 +91,7 @@ void testBuild() { assertEquals("MY_TOKEN", emulatorConfig.cliArguments().token().orElse(null)); assertEquals("-Xmx", emulatorConfig.cliArguments().javaToolOptions().orElse(null)); assertPathEndsWith("data", emulatorConfig.cliArguments().emulatorData().orElse(null)); + assertEquals(Set.of("webframeworks"), emulatorConfig.cliArguments().experiments().orElse(null)); assertEquals(FirebaseEmulatorContainer.ImportExport.EXPORT_ONLY, emulatorConfig.cliArguments().importExport()); assertTrue(emulatorConfig.cliArguments().debug()); @@ -174,6 +177,7 @@ record TestCli( Optional javaToolOptions, Optional emulatorData, Optional importExport, + Optional> experiments, Optional debug) implements FirebaseDevServiceConfig.Firebase.Emulator.Cli { } diff --git a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerCustomConfigTest.java b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerCustomConfigTest.java index 77312a87..c0534afa 100644 --- a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerCustomConfigTest.java +++ b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerCustomConfigTest.java @@ -10,6 +10,7 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.Set; import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Container; @@ -29,6 +30,7 @@ public class FirebaseEmulatorContainerCustomConfigTest { firebaseContainer = testContainer.testBuilder() .withCliArguments() .withEmulatorData(tempEmulatorDataDir.toPath()) + .withExperiments(Set.of("webframeworks")) .done() .readFromFirebaseJson(new File("src/test/firebase.json").toPath()) .build(); diff --git a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerIntegrationTest.java b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerIntegrationTest.java index 122cbba3..bf7a85bf 100644 --- a/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerIntegrationTest.java +++ b/firebase-devservices/deployment/src/test/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainerIntegrationTest.java @@ -153,6 +153,11 @@ private static void validateEmulatorDataWritten() { File[] files = emulatorDataDir.listFiles(); assertNotNull(files); assertTrue(files.length > 0, "Expected files to be present in the emulator data directory"); + + // Verify storage files are written + File[] storageFiles = new File(emulatorDataDir, "storage_export/blobs").listFiles(); + assertNotNull(storageFiles); + assertTrue(storageFiles.length > 0, "Expected storage files to be present in the storage data directory"); } @Test diff --git a/integration-tests/firebase/src/main/resources/application.properties b/integration-tests/firebase/src/main/resources/application.properties index 1e24c613..67e2656b 100644 --- a/integration-tests/firebase/src/main/resources/application.properties +++ b/integration-tests/firebase/src/main/resources/application.properties @@ -6,3 +6,4 @@ quarkus.google.cloud.access-token-enabled=false quarkus.google.cloud.devservices.firebase.auth.enabled=true quarkus.google.cloud.devservices.firebase.firestore.enabled=true quarkus.google.cloud.devservices.pubsub.enabled=true +quarkus.google.cloud.devservices.firebase.emulator.cli.experiments=webframeworks diff --git a/pubsub/runtime/src/main/java/io/quarkiverse/googlecloudservices/pubsub/PubSubProducer.java b/pubsub/runtime/src/main/java/io/quarkiverse/googlecloudservices/pubsub/PubSubProducer.java index 967da977..92b3f764 100644 --- a/pubsub/runtime/src/main/java/io/quarkiverse/googlecloudservices/pubsub/PubSubProducer.java +++ b/pubsub/runtime/src/main/java/io/quarkiverse/googlecloudservices/pubsub/PubSubProducer.java @@ -1,12 +1,13 @@ package io.quarkiverse.googlecloudservices.pubsub; -import com.google.cloud.pubsub.v1.SubscriptionAdminClient; -import com.google.cloud.pubsub.v1.TopicAdminClient; +import java.io.IOException; + import jakarta.enterprise.inject.Disposes; import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import java.io.IOException; +import com.google.cloud.pubsub.v1.SubscriptionAdminClient; +import com.google.cloud.pubsub.v1.TopicAdminClient; /** * Producer class for PubSub beans.