From e5c8816c9cd1abdd2b3297d6a7ab8a42a4efb4b2 Mon Sep 17 00:00:00 2001 From: Oguzhan Soykan Date: Tue, 5 Nov 2024 11:56:41 +0100 Subject: [PATCH] quarkus: starts but beanManager is not accessible, something is missing --- .../quarkus-recipe/build.gradle.kts | 2 + .../recipes/quarkus/GreetingResource.java | 6 +- .../stove/recipes/quarkus/HelloService.java | 10 +++ .../recipes/quarkus/QuarkusRecipeApp.java | 68 +++++++++++++++++-- .../src/main/resources/application.properties | 5 ++ .../stove/recipes/quarkus/e2e/setup/Stove.kt | 25 ++++--- .../recipes/quarkus/e2e/tests/IndexTests.kt | 6 ++ 7 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/HelloService.java create mode 100644 recipes/java-recipes/quarkus-recipe/src/main/resources/application.properties diff --git a/recipes/java-recipes/quarkus-recipe/build.gradle.kts b/recipes/java-recipes/quarkus-recipe/build.gradle.kts index 60c3a36f..8c490060 100644 --- a/recipes/java-recipes/quarkus-recipe/build.gradle.kts +++ b/recipes/java-recipes/quarkus-recipe/build.gradle.kts @@ -9,6 +9,8 @@ dependencies { implementation(libs.couchbase.client) implementation(libs.jackson.databind) implementation(libs.jackson.core) + implementation(libs.logback.classic) + implementation(libs.slf4j.api) implementation(projects.shared.application) } diff --git a/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/GreetingResource.java b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/GreetingResource.java index e7f1d97a..e8886d1a 100644 --- a/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/GreetingResource.java +++ b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/GreetingResource.java @@ -1,5 +1,6 @@ package com.trendyol.stove.recipes.quarkus; +import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; @@ -8,9 +9,12 @@ @Path("/hello") public class GreetingResource { + @Inject + HelloService helloService; + @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { - return "Hello from Quarkus REST"; + return helloService.hello(); } } diff --git a/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/HelloService.java b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/HelloService.java new file mode 100644 index 00000000..3a3b7937 --- /dev/null +++ b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/HelloService.java @@ -0,0 +1,10 @@ +package com.trendyol.stove.recipes.quarkus; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HelloService { + public String hello() { + return "Hello from Quarkus Service"; + } +} diff --git a/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/QuarkusRecipeApp.java b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/QuarkusRecipeApp.java index abd6df32..c400e393 100644 --- a/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/QuarkusRecipeApp.java +++ b/recipes/java-recipes/quarkus-recipe/src/main/java/com/trendyol/stove/recipes/quarkus/QuarkusRecipeApp.java @@ -1,11 +1,71 @@ package com.trendyol.stove.recipes.quarkus; +import io.quarkus.arc.Arc; +import io.quarkus.dev.appstate.ApplicationStateNotification; +import io.quarkus.runtime.ApplicationLifecycleManager; import io.quarkus.runtime.Quarkus; -import io.quarkus.runtime.annotations.QuarkusMain; +import io.quarkus.runtime.QuarkusApplication; +import jakarta.enterprise.inject.spi.BeanManager; -@QuarkusMain -public class QuarkusRecipeApp { +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; + +import static io.quarkus.dev.appstate.ApplicationStateNotification.State.STARTED; + +class QuarkusApp implements QuarkusApplication { public static void main(String[] args) { - Quarkus.run(args); + var app = new QuarkusApp(); + try { + app.run(args); + } catch (Exception e) { + Logger.getLogger(QuarkusApp.class.getName()).severe("Failed to start Quarkus: " + e.getMessage()); + System.exit(-1); + } + } + + @Override + public int run(String... args) { + QuarkusRecipeApp.run(args, "main"); + return 0; + } +} + + +public class QuarkusRecipeApp { + public static BeanManager run(String[] args, String whereDoesItComeFrom) { + System.out.println("Where does it come from? " + whereDoesItComeFrom); + + CompletableFuture startupComplete = new CompletableFuture<>(); + ApplicationLifecycleManager.setAlreadyStartedCallback(started -> + startupComplete.complete(true) + ); + Thread quarkusThread = new Thread(() -> { + Quarkus.run(args); + }, "quarkus-main"); + quarkusThread.setDaemon(true); + quarkusThread.start(); + + try { + while (ApplicationStateNotification.getState() != STARTED) { + Thread.sleep(100); + } + + while (ApplicationLifecycleManager.getCurrentApplication() == null) { + Thread.sleep(1000); + } + + return Arc.container().beanManager(); + + } catch (Exception e) { + throw new RuntimeException("Failed to start Quarkus", e); + } + } + + public static void stop() { + try { + Arc.shutdown(); + } finally { + Quarkus.asyncExit(); + } } } diff --git a/recipes/java-recipes/quarkus-recipe/src/main/resources/application.properties b/recipes/java-recipes/quarkus-recipe/src/main/resources/application.properties new file mode 100644 index 00000000..2768a38a --- /dev/null +++ b/recipes/java-recipes/quarkus-recipe/src/main/resources/application.properties @@ -0,0 +1,5 @@ +quarkus.profile=prod +quarkus.config.profile.parent=prod +quarkus.live-reload.enabled=false +quarkus.virtual-threads.enabled=true +quarkus.banner.enabled=false diff --git a/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/setup/Stove.kt b/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/setup/Stove.kt index 77edf0b3..69856351 100644 --- a/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/setup/Stove.kt +++ b/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/setup/Stove.kt @@ -1,11 +1,13 @@ package com.trendyol.stove.recipes.quarkus.e2e.setup import com.trendyol.stove.recipes.quarkus.QuarkusRecipeApp +import com.trendyol.stove.testing.e2e.bridge import com.trendyol.stove.testing.e2e.http.* import com.trendyol.stove.testing.e2e.system.* import com.trendyol.stove.testing.e2e.system.abstractions.* import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl import io.kotest.core.config.AbstractProjectConfig +import jakarta.enterprise.inject.spi.BeanManager import kotlinx.coroutines.* class Stove : AbstractProjectConfig() { @@ -17,10 +19,12 @@ class Stove : AbstractProjectConfig() { baseUrl = "http://localhost:8080" ) } + bridge() quarkus( runner = { params -> - QuarkusRecipeApp.main(params) - } + QuarkusRecipeApp.run(params, "e2eTest") + }, + withParameters = listOf() ) }.run() } @@ -32,7 +36,7 @@ class Stove : AbstractProjectConfig() { @StoveDsl internal fun TestSystem.systemUnderTest( - runner: Runner, + runner: Runner, withParameters: List = listOf() ): ReadyTestSystem { this.applicationUnderTest(QuarkusAppUnderTest(this, runner, withParameters)) @@ -41,25 +45,26 @@ internal fun TestSystem.systemUnderTest( @StoveDsl fun WithDsl.quarkus( - runner: Runner, + runner: Runner, withParameters: List = listOf() ): ReadyTestSystem = this.testSystem.systemUnderTest(runner, withParameters) @Suppress("UNCHECKED_CAST") class QuarkusAppUnderTest( private val testSystem: TestSystem, - private val runner: Runner, + private val runner: Runner, private val parameters: List -) : ApplicationUnderTest { - override suspend fun start(configurations: List): Unit = coroutineScope { +) : ApplicationUnderTest { + override suspend fun start(configurations: List): BeanManager = coroutineScope { val allConfigurations = (configurations + parameters).map { "--$it" }.toTypedArray() - runner(allConfigurations) + val di = runner(allConfigurations) testSystem.activeSystems .map { it.value } .filter { it is RunnableSystemWithContext<*> || it is AfterRunAwareWithContext<*> } - .map { it as AfterRunAwareWithContext } - .map { async(context = Dispatchers.IO) { it.afterRun(Unit) } } + .map { it as AfterRunAwareWithContext } + .map { async(context = Dispatchers.IO) { it.afterRun(di) } } .awaitAll() + di } override suspend fun stop(): Unit = Unit diff --git a/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/tests/IndexTests.kt b/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/tests/IndexTests.kt index 26225251..b5a9bea5 100644 --- a/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/tests/IndexTests.kt +++ b/recipes/java-recipes/quarkus-recipe/src/test-e2e/kotlin/com/trendyol/stove/recipes/quarkus/e2e/tests/IndexTests.kt @@ -1,13 +1,19 @@ package com.trendyol.stove.recipes.quarkus.e2e.tests +import com.trendyol.stove.recipes.quarkus.HelloService import com.trendyol.stove.testing.e2e.http.http import com.trendyol.stove.testing.e2e.system.TestSystem.Companion.validate +import com.trendyol.stove.testing.e2e.system.using import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe class IndexTests : FunSpec({ test("Index page should return 200") { validate { + using { + println(this) + } + http { get( "/hello",