diff --git a/bom/application/pom.xml b/bom/application/pom.xml index d634181d9406c..5725b7a262a66 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -174,7 +174,7 @@ 5.8.0 4.9.2 1.1.4.Final - 18.0.1 + 18.0.2 1.15.0 3.22.0 2.13.1 @@ -1203,6 +1203,11 @@ quarkus-jdbc-derby ${project.version} + + io.quarkus + quarkus-jdbc-derby-deployment + ${project.version} + io.quarkus quarkus-kafka-client diff --git a/build-parent/pom.xml b/build-parent/pom.xml index d88c982d73bea..780d4b534f3b2 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -102,7 +102,7 @@ - 18.0.1 + 18.0.2 quay.io/keycloak/keycloak:${keycloak.version} quay.io/keycloak/keycloak:${keycloak.version}-legacy diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index b9cec7ee2d749..f76982c30f6b8 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -650,3 +650,93 @@ include::{generated-dir}/config/quarkus-reactive-oracle-client.adoc[opts=optiona === Reactive PostgreSQL Specific Configuration include::{generated-dir}/config/quarkus-reactive-pg-client.adoc[opts=optional, leveloffset=+1] + + +[[reactive-url]] +== Reactive Datasource URL Reference + +=== DB2 + +`db2://[user[:[password]]@]host[:port][/database][?=[&=]]` + +Example:: `db2://dbuser:secretpassword@database.server.com:50000/mydb` + +Currently, the client supports the following parameter keys: + +* `host` +* `port` +* `user` +* `password` +* `database` + +NOTE: Configuring parameters in connection URL will override the default properties. + +=== Microsoft SQL Server + +`sqlserver://[user[:[password]]@]host[:port][/database][?=[&=]]` + +Example:: `sqlserver://dbuser:secretpassword@database.server.com:1433/mydb` + +Currently, the client supports the following parameter keys: + +* `host` +* `port` +* `user` +* `password` +* `database` + +NOTE: Configuring parameters in connection URL will override the default properties. + +=== MySQL / MariaDB + +`mysql://[user[:[password]]@]host[:port][/database][?=[&=]]` + +Example:: `mysql://dbuser:secretpassword@database.server.com:3211/mydb` + +Currently, the client supports the following parameter keys (case-insensitive): + +* `host` +* `port` +* `user` +* `password` +* `schema` +* `socket` +* `useAffectedRows` + +NOTE: Configuring parameters in connection URL will override the default properties. + +=== Oracle + +==== EZConnect Format + +`oracle:thin:@[[protocol:]//]host[:port][/service_name][:server_mode][/instance_name][?connection properties]` + +Example:: `oracle:thin:@mydbhost1:5521/mydbservice?connect_timeout=10sec` + +==== TNS Alias Format + +`oracle:thin:@[?connection properties]` + +Example:: `oracle:thin:@prod_db?TNS_ADMIN=/work/tns/` + +=== PostgreSQL + +`postgresql://[user[:[password]]@]host[:port][/database][?=[&=]]` + +Example:: `postgresql://dbuser:secretpassword@database.server.com:5432/mydb` + +Currently, the client supports the following parameter keys: + +* `host` +* `port` +* `user` +* `password` +* `dbname` +* `sslmode` +* additional properties, including: +** `application_name` +** `fallback_application_name` +** `search_path` +** `options` + +NOTE: Configuring parameters in connection URL will override the default properties. diff --git a/docs/src/main/asciidoc/grpc-service-consumption.adoc b/docs/src/main/asciidoc/grpc-service-consumption.adoc index 4e47f7e10fa9d..2936a0dfc5307 100644 --- a/docs/src/main/asciidoc/grpc-service-consumption.adoc +++ b/docs/src/main/asciidoc/grpc-service-consumption.adoc @@ -396,3 +396,10 @@ To disable the gRPC client metrics when `quarkus-micrometer` is used, add the fo ---- quarkus.micrometer.binder.grpc-client.enabled=false ---- + +== Dev Mode + +By default, when starting the application in dev mode, a gRPC server is started, even if no services are configured. +You can configure the gRPC extension's dev mode behavior using the following properties. + +include::{generated-dir}/config/quarkus-grpc-config-group-grpc-dev-mode-config.adoc[opts=optional, leveloffset=+1] diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java index 842648b23ae8a..ebec5a4e4e6ac 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java @@ -182,7 +182,7 @@ public static List createDecorators(Optional projec //Handle RBAC if (!roleBindings.isEmpty()) { - result.add(new DecoratorBuildItem(target, new ApplyServiceAccountNameDecorator(name))); + result.add(new DecoratorBuildItem(target, new ApplyServiceAccountNameDecorator(name, name))); result.add(new DecoratorBuildItem(target, new AddServiceAccountResourceDecorator(name))); roles.forEach(r -> result.add(new DecoratorBuildItem(target, new AddRoleResourceDecorator(name, r)))); roleBindings.forEach(rb -> { diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java index cc5c1dee815e8..969be8042a97e 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java @@ -37,6 +37,7 @@ import io.fabric8.openshift.api.model.Route; import io.fabric8.openshift.client.OpenShiftClient; import io.quarkus.container.image.deployment.ContainerImageCapabilitiesUtil; +import io.quarkus.container.image.deployment.ContainerImageConfig; import io.quarkus.container.spi.ContainerImageInfoBuildItem; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; @@ -64,7 +65,9 @@ public class KubernetesDeployer { public void selectDeploymentTarget(ContainerImageInfoBuildItem containerImageInfo, EnabledKubernetesDeploymentTargetsBuildItem targets, Capabilities capabilities, - BuildProducer selectedDeploymentTarget) { + ContainerImageConfig containerImageConfig, + BuildProducer selectedDeploymentTarget, + BuildProducer preventImplicitContainerImagePush) { Optional activeContainerImageCapability = ContainerImageCapabilitiesUtil .getActiveContainerImageCapability(capabilities); @@ -75,8 +78,11 @@ public void selectDeploymentTarget(ContainerImageInfoBuildItem containerImageInf } final DeploymentTargetEntry selectedTarget = determineDeploymentTarget( - containerImageInfo, targets, activeContainerImageCapability.get()); + containerImageInfo, targets, activeContainerImageCapability.get(), containerImageConfig); selectedDeploymentTarget.produce(new SelectedKubernetesDeploymentTargetBuildItem(selectedTarget)); + if (MINIKUBE.equals(selectedTarget.getName())) { + preventImplicitContainerImagePush.produce(new PreventImplicitContainerImagePushBuildItem()); + } } @BuildStep @@ -141,7 +147,8 @@ public void deploy(KubernetesClientBuildItem kubernetesClient, */ private DeploymentTargetEntry determineDeploymentTarget( ContainerImageInfoBuildItem containerImageInfo, - EnabledKubernetesDeploymentTargetsBuildItem targets, String activeContainerImageCapability) { + EnabledKubernetesDeploymentTargetsBuildItem targets, String activeContainerImageCapability, + ContainerImageConfig containerImageConfig) { final DeploymentTargetEntry selectedTarget; boolean checkForMissingRegistry = true; @@ -180,6 +187,8 @@ private DeploymentTargetEntry determineDeploymentTarget( } else if (MINIKUBE.equals(selectedTarget.getName())) { checkForMissingRegistry = false; + } else if (containerImageConfig.isPushExplicitlyDisabled()) { + checkForMissingRegistry = false; } if (checkForMissingRegistry && !containerImageInfo.getRegistry().isPresent()) { diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployerPrerequisite.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployerPrerequisite.java index ce0665e9d0882..6a28b164fcc7e 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployerPrerequisite.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployerPrerequisite.java @@ -1,5 +1,6 @@ package io.quarkus.kubernetes.deployment; +import java.util.List; import java.util.Optional; import io.quarkus.container.spi.ContainerImageBuildRequestBuildItem; @@ -16,6 +17,7 @@ public class KubernetesDeployerPrerequisite { public void prepare(ContainerImageInfoBuildItem containerImage, Optional selectedDeploymentTarget, Optional fallbackRegistry, + List preventImplicitContainerImagePush, BuildProducer buildRequestProducer, BuildProducer pushRequestProducer) { @@ -28,11 +30,10 @@ public void prepare(ContainerImageInfoBuildItem containerImage, //Let's communicate to the container-image plugin that we need an image build and an image push. buildRequestProducer.produce(new ContainerImageBuildRequestBuildItem()); // When a registry is present, we want to push the image - // However we need to make sure we don't push to the registry when deploying to Minikube + // However we need to make sure we don't push to the registry when deploying to a local cluster // since all updates are meant to find the image from the docker daemon boolean registryIsPresent = containerImage.getRegistry().isPresent() || fallbackRegistry.isPresent(); - if (registryIsPresent && - !selectedDeploymentTarget.get().getEntry().getName().equals(Constants.MINIKUBE)) { + if (registryIsPresent && preventImplicitContainerImagePush.isEmpty()) { pushRequestProducer.produce(new ContainerImagePushRequestBuildItem()); } } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java index 1f960afac0c2f..e9af827ba7082 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesProcessor.java @@ -31,6 +31,7 @@ import io.dekorate.project.Project; import io.dekorate.utils.Maps; import io.dekorate.utils.Strings; +import io.quarkus.container.image.deployment.ContainerImageConfig; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Feature; import io.quarkus.deployment.IsTest; @@ -81,6 +82,14 @@ public EnabledKubernetesDeploymentTargetsBuildItem enabledKubernetesDeploymentTa return new EnabledKubernetesDeploymentTargetsBuildItem(entries); } + @BuildStep + public void preventContainerPush(ContainerImageConfig containerImageConfig, + BuildProducer producer) { + if (containerImageConfig.isPushExplicitlyDisabled()) { + producer.produce(new PreventImplicitContainerImagePushBuildItem()); + } + } + @BuildStep(onlyIfNot = IsTest.class) public void build(ApplicationInfoBuildItem applicationInfo, OutputTargetBuildItem outputTarget, diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PreventImplicitContainerImagePushBuildItem.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PreventImplicitContainerImagePushBuildItem.java new file mode 100644 index 0000000000000..b02b4eddef128 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PreventImplicitContainerImagePushBuildItem.java @@ -0,0 +1,13 @@ +package io.quarkus.kubernetes.deployment; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * A build item that is used to prevent the Kubernetes processing from requesting + * a container image push request. + * This is useful for cases where the kubernetes cluster is local and the container image + * is built directly into a context (i.e. a docker daemon) which the cluster has access to. + */ +public final class PreventImplicitContainerImagePushBuildItem extends MultiBuildItem { + +} diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java index e9bd0e73fc22d..6c34ae344bf45 100644 --- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java +++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java @@ -28,7 +28,7 @@ public class DevServicesConfig { * * Image with a Quarkus based distribution is used by default. * Image with a WildFly based distribution can be selected instead, for example: - * 'quay.io/keycloak/keycloak:18.0.1-legacy'. + * 'quay.io/keycloak/keycloak:18.0.2-legacy'. *

* Note Keycloak Quarkus and Keycloak WildFly images are initialized differently. * By default, Dev Services for Keycloak will assume it is a Keycloak Quarkus image if the image version does not end with a @@ -36,7 +36,7 @@ public class DevServicesConfig { * string. * Set 'quarkus.keycloak.devservices.keycloak-x-image' to override this check. */ - @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:18.0.1") + @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:18.0.2") public String imageName; /** diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/customexceptions/SecurityExceptionMapperWithResourceInfoTest.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/customexceptions/SecurityExceptionMapperWithResourceInfoTest.java new file mode 100644 index 0000000000000..0eb03f18d6ea0 --- /dev/null +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/customexceptions/SecurityExceptionMapperWithResourceInfoTest.java @@ -0,0 +1,57 @@ +package io.quarkus.resteasy.reactive.server.test.customexceptions; + +import static org.hamcrest.Matchers.is; + +import java.util.function.Supplier; + +import javax.annotation.security.DenyAll; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.reactive.server.ServerExceptionMapper; +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 SecurityExceptionMapperWithResourceInfoTest { + + @RegisterExtension + static QuarkusUnitTest test = new QuarkusUnitTest() + .setArchiveProducer(new Supplier<>() { + @Override + public JavaArchive get() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(Resource.class); + } + }); + + @Test + void test() { + RestAssured.get("/test/denied") + .then().statusCode(403).body(is(Resource.class.getName())); + } + + @Path("test") + public static class Resource { + @GET + @Path("denied") + @Produces("text/plain") + @DenyAll + public String denied() { + return "denied"; + } + + @ServerExceptionMapper(SecurityException.class) + Response handle(SecurityException t, ResourceInfo resourceInfo) { + return Response.status(403).entity(resourceInfo.getResourceClass().getName()).build(); + } + } + +} diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/EagerSecurityHandler.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/EagerSecurityHandler.java index 21078343d3390..17d9126e8a08a 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/EagerSecurityHandler.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/EagerSecurityHandler.java @@ -91,7 +91,7 @@ public void onItem(Object item) { @Override public void onFailure(Throwable failure) { - requestContext.resume(failure); + requestContext.resume(failure, true); } }); } diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/AbstractResteasyReactiveContext.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/AbstractResteasyReactiveContext.java index a0529d63f83b9..29d5efa755abd 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/AbstractResteasyReactiveContext.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/AbstractResteasyReactiveContext.java @@ -51,8 +51,7 @@ public void resume() { } public synchronized void resume(Throwable throwable) { - handleException(throwable); - resume((Executor) null); + resume(throwable, false); } public synchronized void resume(Throwable throwable, boolean keepTarget) { @@ -303,13 +302,7 @@ public H[] getHandlers() { * a response result and switch to the abort chain */ public void handleException(Throwable t) { - if (abortHandlerChainStarted) { - handleUnrecoverableError(unwrapException(t)); - } else { - this.throwable = unwrapException(t); - abortHandlerChainStarted = true; - restart(abortHandlerChain); - } + handleException(t, false); } public void handleException(Throwable t, boolean keepSameTarget) { diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/WithKubernetesClientAndExistingResourcesTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/WithKubernetesClientAndExistingResourcesTest.java index 76c9d1f1d12d3..70edcdce96b52 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/WithKubernetesClientAndExistingResourcesTest.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/WithKubernetesClientAndExistingResourcesTest.java @@ -51,7 +51,12 @@ public void assertGeneratedResources() throws IOException { assertThat(kubernetesList).filteredOn(h -> "Deployment".equals(h.getKind())).allSatisfy(h -> { Deployment deployment = (Deployment) h; - assertThat(deployment.getSpec().getTemplate().getSpec().getServiceAccountName()).isEqualTo(APPLICATION_NAME); + String serviceAccountName = deployment.getSpec().getTemplate().getSpec().getServiceAccountName(); + if (h.getMetadata().getName().equals(APPLICATION_NAME)) { + assertThat(serviceAccountName).isEqualTo(APPLICATION_NAME); + } else { + assertThat(serviceAccountName).isNull(); + } }); assertThat(kubernetesList).filteredOn(h -> "ServiceAccount".equals(h.getKind())).singleElement().satisfies(h -> { diff --git a/integration-tests/main/src/test/java/io/quarkus/it/main/QuarkusTestNestedPerClassLifecycleTestCase.java b/integration-tests/main/src/test/java/io/quarkus/it/main/QuarkusTestNestedPerClassLifecycleTestCase.java index 19fc04c59aeb2..06085de5f96c7 100644 --- a/integration-tests/main/src/test/java/io/quarkus/it/main/QuarkusTestNestedPerClassLifecycleTestCase.java +++ b/integration-tests/main/src/test/java/io/quarkus/it/main/QuarkusTestNestedPerClassLifecycleTestCase.java @@ -4,6 +4,7 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; @@ -27,7 +28,16 @@ public class QuarkusTestNestedPerClassLifecycleTestCase { private final AtomicInteger counter = new AtomicInteger(0); @BeforeAll - public void increment() { + public void incrementInBeforeAll() { + counter.incrementAndGet(); + } + + /** + * We're doing nothing with this code, but we want to keep it to verify the methods annotated + * with `@AfterAll` work for nested tests. + */ + @AfterAll + public void incrementInAfterAll() { counter.incrementAndGet(); } diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java index b9ef9bfbbd014..62270cec1b3e9 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/QuarkusTestExtension.java @@ -15,8 +15,10 @@ import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.AbstractMap; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; +import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -121,7 +123,7 @@ public class QuarkusTestExtension extends AbstractJvmQuarkusTestExtension private static Class actualTestClass; private static Object actualTestInstance; // needed for @Nested - private static List outerInstances = new ArrayList<>(1); + private static Deque outerInstances = new ArrayDeque<>(1); private static RunningQuarkusApplication runningQuarkusApplication; private static Pattern clonePattern; private static Throwable firstException; //if this is set then it will be thrown from the very first test that is run, the rest are aborted @@ -561,7 +563,7 @@ public void afterEach(ExtensionContext context) throws Exception { Constructor constructor = quarkusTestMethodContextClass.getConstructor(Object.class, List.class, Method.class); return new AbstractMap.SimpleEntry<>(quarkusTestMethodContextClass, - constructor.newInstance(actualTestInstance, outerInstances, actualTestMethod)); + constructor.newInstance(actualTestInstance, new ArrayList<>(outerInstances), actualTestMethod)); } private boolean isNativeOrIntegrationTest(Class clazz) { @@ -1078,7 +1080,9 @@ public void afterAll(ExtensionContext context) throws Exception { } } finally { currentTestClassStack.pop(); - outerInstances.clear(); + if (!outerInstances.isEmpty()) { + actualTestInstance = outerInstances.pop(); + } } } @@ -1093,7 +1097,7 @@ private void runAfterAllCallbacks(ExtensionContext context) throws Exception { Class quarkusTestContextClass = Class.forName(QuarkusTestContext.class.getName(), true, runningQuarkusApplication.getClassLoader()); Object quarkusTestContextInstance = quarkusTestContextClass.getConstructor(Object.class, List.class) - .newInstance(actualTestInstance, outerInstances); + .newInstance(actualTestInstance, new ArrayList<>(outerInstances)); ClassLoader original = setCCL(runningQuarkusApplication.getClassLoader()); try {