diff --git a/bom/application/pom.xml b/bom/application/pom.xml index c203fada3b809..c2b9e6c00e50d 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -4257,6 +4257,12 @@ jandex ${jandex.version} + + + org.jboss + jandex + ${jandex.version} + org.graalvm.nativeimage diff --git a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java index 4e3873150da34..1f9380d33a961 100644 --- a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java +++ b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -176,8 +177,23 @@ public void accept(Integer integer) { Class appClass = Class.forName(className, true, runtimeClassLoader); Method start = appClass.getMethod("main", String[].class); start.invoke(null, (Object) (args == null ? new String[0] : args)); - Class q = Class.forName(Quarkus.class.getName(), true, runtimeClassLoader); - q.getMethod("blockingExit").invoke(null); + + CountDownLatch latch = new CountDownLatch(1); + new Thread(new Runnable() { + @Override + public void run() { + try { + Class q = Class.forName(Quarkus.class.getName(), true, runtimeClassLoader); + q.getMethod("blockingExit").invoke(null); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + latch.countDown(); + } + } + }).start(); + latch.await(); + Object newApplication = getCurrentApplication.invoke(null); if (oldApplication == newApplication) { //quarkus was not actually started by the main method diff --git a/core/runtime/src/main/java/io/quarkus/runtime/Quarkus.java b/core/runtime/src/main/java/io/quarkus/runtime/Quarkus.java index 123e2047fec22..2494d6cec2089 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/Quarkus.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/Quarkus.java @@ -2,6 +2,7 @@ import java.io.Closeable; import java.io.IOException; +import java.util.Locale; import java.util.function.BiConsumer; import org.jboss.logging.Logger; @@ -179,6 +180,12 @@ public static void waitForExit() { * Must not be called by the main thread, or a deadlock will result. */ public static void blockingExit() { + if (Thread.currentThread().getThreadGroup().getName().equals("main") && + Thread.currentThread().getName().toLowerCase(Locale.ROOT).contains("main")) { + Logger.getLogger(Quarkus.class).error( + "'Quarkus#blockingExit' was called on the main thread. This will result in deadlocking the application!"); + } + Application app = Application.currentApplication(); asyncExit(); if (app != null) { diff --git a/devtools/cli/distribution/release-cli.sh b/devtools/cli/distribution/release-cli.sh index 1867efa18d730..8d717c8df7abd 100755 --- a/devtools/cli/distribution/release-cli.sh +++ b/devtools/cli/distribution/release-cli.sh @@ -13,6 +13,13 @@ then exit 1 fi +MAINTENANCE="$3" +if [ -z "$MAINTENANCE" ] +then + echo "Must specify maintenance mode" + exit 1 +fi + DIST_DIR="$( dirname "${BASH_SOURCE[0]}" )" pushd ${DIST_DIR} @@ -43,9 +50,12 @@ popd export JRELEASER_PROJECT_VERSION=${VERSION} export JRELEASER_BRANCH=${BRANCH} -export JRELEASER_CHOCOLATEY_GITHUB_BRANCH=${BRANCH} +if [ "$MAINTENANCE" == "true" ]; then + export JRELEASER_CHOCOLATEY_GITHUB_BRANCH=${BRANCH} + export JRELEASER_HOMEBREW_GITHUB_BRANCH=${BRANCH} +fi -jbang org.jreleaser:jreleaser:1.1.0 full-release \ +jbang org.jreleaser:jreleaser:1.3.0 full-release \ --git-root-search \ -od target diff --git a/docs/src/main/asciidoc/cdi-reference.adoc b/docs/src/main/asciidoc/cdi-reference.adoc index f2f2087b72656..1d20c5b0aa0e9 100644 --- a/docs/src/main/asciidoc/cdi-reference.adoc +++ b/docs/src/main/asciidoc/cdi-reference.adoc @@ -1083,6 +1083,10 @@ In the development mode, two special endpoints are registered automatically to p NOTE: These endpoints are only available in the development mode, i.e. when you run your application via `mvn quarkus:dev` (or `./gradlew quarkusDev`). +=== Monitoring Business Method Invocations and Events + +In the development mode, it is also possible to enable monitoring of business method invocations and fired events. +Simply set the `quarkus.arc.dev-mode.monitoring-enabled` configuration property to `true` and explore the relevant Dev UI pages. [[arc-configuration-reference]] == ArC Configuration Reference diff --git a/docs/src/main/asciidoc/security.adoc b/docs/src/main/asciidoc/security.adoc index 76f91057c4b9f..6e6815d721c03 100644 --- a/docs/src/main/asciidoc/security.adoc +++ b/docs/src/main/asciidoc/security.adoc @@ -15,7 +15,7 @@ Quarkus Security is a framework that provides the architecture, multiple authent Before you start building security into your Quarkus applications, review the overview information to learn about the Quarkus Security architecture and the different authentication and authorization mechanisms that Quarkus supports. To get started with security in Quarkus, we recommend that you first combine the Quarkus built-in xref:security-basic-auth-concept.adoc[Basic HTTP authentication] with the JPA identity provider to enable role-based access control (RBAC). -Complete the steps in the ref:security-getting-started.adoc[Secure a Quarkus application with Basic authentication] tutorial. +Complete the steps in the xref:security-getting-started.adoc[Secure a Quarkus application with Basic authentication] tutorial. After you have successfully secured your Quarkus application with basic HTTP authentication, you can increase the security further by adding more advanced authentication mechanisms, for example, OpenID Connect (OIDC) authentication. == Security architecture @@ -439,4 +439,4 @@ You can adjust the expiry date if you need to. == Quarkus Security testing When testing Quarkus security, ensure that your `IdentityProvider` is already set with usernames, passwords, and roles in `application.properties`. -For more information about testing Quarkus Security, see xref:security-testing.adoc#configuring-user-information[Configuring user information]. \ No newline at end of file +For more information about testing Quarkus Security, see xref:security-testing.adoc#configuring-user-information[Configuring user information]. diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java index 18ac7917643ca..f5966f30e4921 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcDevModeConfig.java @@ -9,7 +9,7 @@ public class ArcDevModeConfig { /** * If set to true then the container monitors business method invocations and fired events during the development mode. */ - @ConfigItem(defaultValue = "true") + @ConfigItem(defaultValue = "false") public boolean monitoringEnabled; } diff --git a/extensions/container-image/container-image-buildpack/deployment/src/main/java/io/quarkus/container/image/buildpack/deployment/BuildpackProcessor.java b/extensions/container-image/container-image-buildpack/deployment/src/main/java/io/quarkus/container/image/buildpack/deployment/BuildpackProcessor.java index c3b2a0dbf61b4..e3592f9f1fbe6 100644 --- a/extensions/container-image/container-image-buildpack/deployment/src/main/java/io/quarkus/container/image/buildpack/deployment/BuildpackProcessor.java +++ b/extensions/container-image/container-image-buildpack/deployment/src/main/java/io/quarkus/container/image/buildpack/deployment/BuildpackProcessor.java @@ -159,7 +159,7 @@ private String runBuildpackBuild(BuildpackConfig buildpackConfig, log.debug("Using source root of " + dirs.get(ProjectDirs.SOURCE)); log.debug("Using project root of " + dirs.get(ProjectDirs.ROOT)); - String targetImageName = containerImage.getImage().toString(); + String targetImageName = containerImage.getImage(); log.debug("Using Destination image of " + targetImageName); Map envMap = new HashMap<>(buildpackConfig.builderEnv); @@ -204,11 +204,13 @@ private String runBuildpackBuild(BuildpackConfig buildpackConfig, log.info("Buildpack build complete"); if (containerImageConfig.isPushExplicitlyEnabled() || pushRequest.isPresent()) { - if (!containerImageConfig.registry.isPresent()) { - log.info("No container image registry was set, so 'docker.io' will be used"); - } + var registry = containerImage.getRegistry() + .orElseGet(() -> { + log.info("No container image registry was set, so 'docker.io' will be used"); + return "docker.io"; + }); AuthConfig authConfig = new AuthConfig(); - authConfig.withRegistryAddress(containerImageConfig.registry.orElse("docker.io")); + authConfig.withRegistryAddress(registry); containerImageConfig.username.ifPresent(u -> authConfig.withUsername(u)); containerImageConfig.password.ifPresent(p -> authConfig.withPassword(p)); diff --git a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java index 989a4026e6306..194144ed1ac86 100644 --- a/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java +++ b/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/JibProcessor.java @@ -264,14 +264,14 @@ private JibContainer containerize(ContainerImageConfig containerImageConfig, } private Containerizer createContainerizer(ContainerImageConfig containerImageConfig, - JibConfig jibConfig, ContainerImageInfoBuildItem containerImage, + JibConfig jibConfig, ContainerImageInfoBuildItem containerImageInfo, boolean pushRequested) { Containerizer containerizer; - ImageReference imageReference = ImageReference.of(containerImage.getRegistry().orElse(null), - containerImage.getRepository(), containerImage.getTag()); + ImageReference imageReference = ImageReference.of(containerImageInfo.getRegistry().orElse(null), + containerImageInfo.getRepository(), containerImageInfo.getTag()); if (pushRequested || containerImageConfig.isPushExplicitlyEnabled()) { - if (!containerImageConfig.registry.isPresent()) { + if (imageReference.getRegistry() == null) { log.info("No container image registry was set, so 'docker.io' will be used"); } RegistryImage registryImage = toRegistryImage(imageReference, containerImageConfig.username, diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java index aa10bc747552a..a575fdc020394 100644 --- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java +++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java @@ -28,7 +28,10 @@ public Supplier infoSupplier( Map puConfigs = runtimeConfig .getAllPersistenceUnitConfigsAsMap(); Set activePersistenceUnitNames = persistenceUnitNames.stream() - .filter(name -> puConfigs.get(name).active.orElse(true)) + .filter(name -> { + var puConfig = puConfigs.get(name); + return puConfig == null || puConfig.active.orElse(true); + }) .collect(Collectors.toCollection(LinkedHashSet::new)); return new HibernateSearchSupplier(activePersistenceUnitNames); } diff --git a/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java b/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java index 6ea785a37e369..b340c93f349e2 100644 --- a/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java +++ b/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java @@ -213,8 +213,10 @@ void register( if (value != null) { // Add the type-id-resolver class reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, value.asClass().name().toString())); - // Add the whole hierarchy of the annotated class - addReflectiveHierarchyClass(resolverInstance.target().asClass().name(), reflectiveHierarchyClass); + if (resolverInstance.target().kind() == CLASS) { + // Add the whole hierarchy of the annotated class + addReflectiveHierarchyClass(resolverInstance.target().asClass().name(), reflectiveHierarchyClass); + } } } diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/ContainerRequestContextTest.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/ContainerRequestContextTest.java new file mode 100644 index 0000000000000..9943372efa324 --- /dev/null +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/ContainerRequestContextTest.java @@ -0,0 +1,65 @@ +package io.quarkus.resteasy.reactive.server.test.resource.basic; + +import static org.hamcrest.Matchers.equalTo; + +import java.io.IOException; +import java.util.function.Supplier; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.ext.Provider; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class ContainerRequestContextTest { + + @RegisterExtension + static QuarkusUnitTest test = new QuarkusUnitTest() + .setArchiveProducer(new Supplier<>() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class) + .addClass(HelloResource.class); + } + }); + + @Test + public void helloWorldTest() { + RestAssured.get("/hello") + .then() + .body(equalTo("hello foo")); + } + + @Path("/hello") + public static class HelloResource { + + private final ContainerRequestContext containerRequestContext; + + public HelloResource(ContainerRequestContext containerRequestContext) { + this.containerRequestContext = containerRequestContext; + } + + @GET + public String hello() { + return "hello " + containerRequestContext.getProperty("name"); + } + + } + + @Provider + public static class TestFilter implements ContainerRequestFilter { + + @Override + public void filter(ContainerRequestContext context) throws IOException { + context.setProperty("name", "foo"); + } + } +} diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/devmode/DependenciesFilter.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/devmode/DependenciesFilter.java index 3cab0132ecfbf..92b4615717ad3 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/devmode/DependenciesFilter.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/devmode/DependenciesFilter.java @@ -20,6 +20,9 @@ public static List getReloadableModules(ApplicationModel app final Map modules = new HashMap<>(); StringBuilder nonReloadable = null; for (ResolvedDependency d : appModel.getDependencies()) { + if (!d.isJar()) { + continue; + } if (d.isReloadable()) { modules.put(d.getKey(), new WorkspaceDependencies(d)); } else if (d.isWorkspaceModule()) { diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/injection/ContextProducers.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/injection/ContextProducers.java index 9d75017dd3cc4..829306f0baa60 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/injection/ContextProducers.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/injection/ContextProducers.java @@ -4,6 +4,7 @@ import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Produces; import javax.inject.Singleton; +import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ResourceContext; import javax.ws.rs.container.ResourceInfo; import javax.ws.rs.core.Application; @@ -51,6 +52,13 @@ HttpHeaders headers() { return getContext().getHttpHeaders(); } + // this is added for compatibility reasons + @RequestScoped + @Produces + ContainerRequestContext containerRequestContext() { + return getContext().getContainerRequestContext(); + } + @ApplicationScoped @Produces Sse sse() { diff --git a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleArcSmokeTest.java b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleArcSmokeTest.java index 0af2b40ae71e9..4bf054ae3ec32 100644 --- a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleArcSmokeTest.java +++ b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleArcSmokeTest.java @@ -5,6 +5,7 @@ import javax.inject.Named; import org.hamcrest.Matchers; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -20,7 +21,8 @@ public class DevConsoleArcSmokeTest { @RegisterExtension static final QuarkusDevModeTest test = new QuarkusDevModeTest() .withApplicationRoot((jar) -> jar - .addClasses(Foo.class)); + .addClasses(Foo.class).addAsResource(new StringAsset("quarkus.arc.dev-mode.monitoring-enabled=true"), + "application.properties")); @Test public void testPages() {