Add tests for required context injection with CDI.

Signed-off-by: James R. Perkins <jperkins@ibm.com>
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/common/util/CdiSupport.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/common/util/CdiSupport.java
new file mode 100644
index 0000000..619c2fb
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/common/util/CdiSupport.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.common.util;
+
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+public class CdiSupport {
+
+    public static final StringAsset BEANS_XML = new StringAsset("""
+            <?xml version="1.0" encoding="UTF-8"?>
+            <beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
+                   version="4.0" bean-discovery-mode="annotated">
+            </beans>""");
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectFilter.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectFilter.java
new file mode 100644
index 0000000..6fc5158
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectFilter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.client.inject;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Providers;
+
+/**
+ * A client-side filter that verifies {@code @Inject} works for {@link Configuration} and {@link Providers} as a
+ * replacement for the deprecated {@code @Context} annotation on the client side. The Jakarta REST runtime is
+ * responsible for resolving these injection points regardless of whether a CDI container is present.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+public class ClientInjectFilter implements ClientRequestFilter {
+
+    @Inject
+    private Configuration configuration;
+
+    @Inject
+    private Providers providers;
+
+    @Override
+    public void filter(final ClientRequestContext requestContext) {
+        final ClientInjectionDescriptor descriptor = ClientInjectionDescriptor.of(configuration, providers);
+        requestContext.abortWith(Response.ok(descriptor).type(MediaType.APPLICATION_JSON_TYPE).build());
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionDescriptor.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionDescriptor.java
new file mode 100644
index 0000000..b9db055
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.client.inject;
+
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.ext.Providers;
+
+public record ClientInjectionDescriptor(String configuration, String providers) {
+
+    public static ClientInjectionDescriptor of(final Configuration configuration, final Providers providers) {
+        return new ClientInjectionDescriptor(
+                configuration == null ? null : String.valueOf(configuration.getRuntimeType()),
+                providers == null ? null : providers.getClass().getName());
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionIT.java
new file mode 100644
index 0000000..8d9bed7
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/client/inject/ClientInjectionIT.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.client.inject;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MediaType;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests that {@code @Inject} works for {@link jakarta.ws.rs.core.Configuration} and
+ * {@link jakarta.ws.rs.ext.Providers} in client-side providers. The Jakarta REST runtime is responsible for
+ * resolving these injection points regardless of whether a CDI container is present.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@Tag("client")
+public class ClientInjectionIT {
+
+    @Test
+    void clientFilterInjection() {
+        try (Client client = ClientBuilder.newBuilder().register(ClientInjectFilter.class).build()) {
+            // We abort the client response so any URI should be acceptable.
+            final ClientInjectionDescriptor descriptor = client.target("http://localhost:8080")
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(ClientInjectionDescriptor.class);
+            Assertions.assertAll(
+                    () -> Assertions.assertNotNull(descriptor.configuration(),
+                            "Configuration not injected into client filter"),
+                    () -> Assertions.assertEquals(RuntimeType.CLIENT.name(), descriptor.configuration(),
+                            "Configuration runtime type should be CLIENT"),
+                    () -> Assertions.assertNotNull(descriptor.providers(),
+                            "Providers not injected into client filter")
+            );
+        }
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/ContextInjectionDescriptor.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/ContextInjectionDescriptor.java
new file mode 100644
index 0000000..3696af7
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/ContextInjectionDescriptor.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
+import jakarta.ws.rs.sse.Sse;
+
+public record ContextInjectionDescriptor(
+        String application,
+        String configuration,
+        String httpHeaders,
+        String providers,
+        String request,
+        String resourceContext,
+        String resourceInfo,
+        String securityContext,
+        String sse,
+        String uriInfo) {
+
+    public static ContextInjectionDescriptor of(final Application application,
+                                                final Configuration configuration,
+                                                final HttpHeaders httpHeaders,
+                                                final Providers providers,
+                                                final Request request,
+                                                final ResourceContext resourceContext,
+                                                final ResourceInfo resourceInfo,
+                                                final SecurityContext securityContext,
+                                                final Sse sse,
+                                                final UriInfo uriInfo) {
+        return new ContextInjectionDescriptor(
+                application == null ? null : application.getClass().getName(),
+                configuration == null ? null : String.valueOf(configuration.getRuntimeType()),
+                httpHeaders == null ? null : httpHeaders.getHeaderString("test-header"),
+                providers == null ? null : providers.getClass().getName(),
+                request == null ? null : request.getMethod(),
+                resourceContext == null ? null : resourceContext.getClass().getName(),
+                resourceInfo == null ? null : resourceInfo.getResourceMethod().getName(),
+                securityContext == null ? null : String.valueOf(securityContext.isSecure()),
+                sse == null ? null : sse.getClass().getName(),
+                uriInfo == null ? null : uriInfo.getPath());
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextApplication.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextApplication.java
new file mode 100644
index 0000000..25fe628
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextApplication.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import java.util.Collections;
+import java.util.Map;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
+
+@ApplicationPath("/")
+public class RequiredContextApplication extends Application {
+
+    @Inject
+    UriInfo info;
+
+    @Inject
+    Request request;
+
+    @Inject
+    HttpHeaders headers;
+
+    @Inject
+    SecurityContext security;
+
+    @Inject
+    Providers providers;
+
+    @Inject
+    ResourceContext resources;
+
+    @Override
+    public Map<String, Object> getProperties() {
+        return Collections.singletonMap("test.property", "test value");
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextConstructorResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextConstructorResource.java
new file mode 100644
index 0000000..e18989f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextConstructorResource.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
+import jakarta.ws.rs.sse.Sse;
+
+@Path("/inject-constructor")
+public class RequiredContextConstructorResource {
+
+    private final Application application;
+    private final Configuration configuration;
+    private final HttpHeaders httpHeaders;
+    private final Providers providers;
+    private final Request request;
+    private final ResourceContext resourceContext;
+    private final ResourceInfo resourceInfo;
+    private final SecurityContext securityContext;
+    private final Sse sse;
+    private final UriInfo uriInfo;
+
+    RequiredContextConstructorResource() {
+        this.application = null;
+        this.configuration = null;
+        this.httpHeaders = null;
+        this.providers = null;
+        this.request = null;
+        this.resourceContext = null;
+        this.resourceInfo = null;
+        this.securityContext = null;
+        this.sse = null;
+        this.uriInfo = null;
+    }
+
+    @Inject
+    public RequiredContextConstructorResource(final Application application,
+                                              final Configuration configuration,
+                                              final HttpHeaders httpHeaders,
+                                              final Providers providers,
+                                              final Request request,
+                                              final ResourceContext resourceContext,
+                                              final ResourceInfo resourceInfo,
+                                              final SecurityContext securityContext,
+                                              final Sse sse,
+                                              final UriInfo uriInfo) {
+        this.application = application;
+        this.configuration = configuration;
+        this.httpHeaders = httpHeaders;
+        this.providers = providers;
+        this.request = request;
+        this.resourceContext = resourceContext;
+        this.resourceInfo = resourceInfo;
+        this.securityContext = securityContext;
+        this.sse = sse;
+        this.uriInfo = uriInfo;
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public ContextInjectionDescriptor get() {
+        return ContextInjectionDescriptor.of(application, configuration, httpHeaders, providers,
+                request, resourceContext, resourceInfo, securityContext, sse, uriInfo);
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextInjectionIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextInjectionIT.java
new file mode 100644
index 0000000..596466b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextInjectionIT.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import ee.jakarta.tck.ws.rs.common.provider.PrintingErrorHandler;
+import ee.jakarta.tck.ws.rs.common.provider.StringBean;
+import ee.jakarta.tck.ws.rs.common.provider.StringBeanEntityProvider;
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import ee.jakarta.tck.ws.rs.lib.util.TestUtil;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.sse.SseEventSource;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+@ArquillianTest
+@Tag("cdi")
+class RequiredContextInjectionIT {
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() throws IOException {
+        return ShrinkWrap.create(WebArchive.class, "rest-cdi-injection.war")
+                .addClasses(RequiredContextApplication.class,
+                        RequiredContextResource.class,
+                        RequiredContextConstructorResource.class,
+                        ContextInjectionDescriptor.class,
+                        StringBeanEntityProviderWithInjectables.class,
+                        StringBeanEntityProvider.class,
+                        PrintingErrorHandler.class,
+                        StringBean.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    private static Client client;
+
+    @ArquillianResource
+    private URI baseUri;
+
+    @BeforeAll
+    static void createClient() {
+        client = ClientBuilder.newBuilder()
+                .build();
+    }
+
+    @AfterAll
+    static void closeClient() {
+        if (client != null) {
+            client.close();
+        }
+    }
+
+    @BeforeEach
+    void logStartTest(final TestInfo testInfo) {
+        TestUtil.logMsg("STARTING TEST : " + testInfo.getDisplayName());
+    }
+
+    @AfterEach
+    void logFinishTest(final TestInfo testInfo) {
+        TestUtil.logMsg("FINISHED TEST : " + testInfo.getDisplayName());
+    }
+
+    @Test
+    void constructorInjection() {
+        final ContextInjectionDescriptor descriptor = getDescriptor("inject-constructor");
+        assertAllInjected(descriptor, "constructor");
+        Assertions.assertEquals("GET", descriptor.request(),
+                () -> "Request method incorrect via constructor injection: %s".formatted(descriptor));
+        Assertions.assertEquals(RuntimeType.SERVER.name(), descriptor.configuration(),
+                () -> "Configuration runtime type incorrect via constructor injection: %s".formatted(descriptor));
+        Assertions.assertEquals("test-value", descriptor.httpHeaders(),
+                () -> "HttpHeaders value incorrect via constructor injection: %s".formatted(descriptor));
+        Assertions.assertEquals("get", descriptor.resourceInfo(),
+                () -> "ResourceInfo method name incorrect via constructor injection: %s".formatted(descriptor));
+    }
+
+    @Test
+    void fieldInjection() {
+        final ContextInjectionDescriptor descriptor = getDescriptor("inject/field");
+        assertAllInjected(descriptor, "field");
+        Assertions.assertEquals("GET", descriptor.request(),
+                () -> "Request method incorrect via field injection: %s".formatted(descriptor));
+        Assertions.assertEquals(RuntimeType.SERVER.name(), descriptor.configuration(),
+                () -> "Configuration runtime type incorrect via field injection: %s".formatted(descriptor));
+        Assertions.assertEquals("test-value", descriptor.httpHeaders(),
+                () -> "HttpHeaders value incorrect via field injection: %s".formatted(descriptor));
+        Assertions.assertEquals("field", descriptor.resourceInfo(),
+                () -> "ResourceInfo method name incorrect via field injection: %s".formatted(descriptor));
+    }
+
+    @Test
+    void methodInjection() {
+        final ContextInjectionDescriptor descriptor = getDescriptor("inject/method");
+        assertAllInjected(descriptor, "method parameter");
+        Assertions.assertEquals("GET", descriptor.request(),
+                () -> "Request method incorrect via method parameter injection: %s".formatted(descriptor));
+        Assertions.assertEquals(RuntimeType.SERVER.name(), descriptor.configuration(),
+                () -> "Configuration runtime type incorrect via method parameter injection: %s".formatted(descriptor));
+        Assertions.assertEquals("test-value", descriptor.httpHeaders(),
+                () -> "HttpHeaders value incorrect via method parameter injection: %s".formatted(descriptor));
+        Assertions.assertEquals("method", descriptor.resourceInfo(),
+                () -> "ResourceInfo method name incorrect via method parameter injection: %s".formatted(descriptor));
+    }
+
+    @Test
+    void providerInjection() {
+        final Response response = getJson("inject/providers");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus(),
+                () -> "Failed to look up provider: " + response.readEntity(String.class));
+        final ContextInjectionDescriptor descriptor = response.readEntity(ContextInjectionDescriptor.class);
+        Assertions.assertAll(
+                () -> Assertions.assertNotNull(descriptor.application(), () -> "Application not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.configuration(), () -> "Configuration not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.httpHeaders(), () -> "HttpHeaders not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.providers(), () -> "Providers not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.request(), () -> "Request not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.resourceContext(), () -> "ResourceContext not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.securityContext(), () -> "SecurityContext not injected into provider: %s".formatted(descriptor)),
+                () -> Assertions.assertNotNull(descriptor.uriInfo(), () -> "UriInfo not injected into provider: %s".formatted(descriptor))
+        );
+    }
+
+    @Test
+    void application() {
+        final Response response = get("inject/application/test.property");
+        final var found = response.readEntity(String.class);
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus(), found);
+        Assertions.assertEquals("test value", found);
+    }
+
+    @Test
+    void configuration() {
+        final Response response = get("inject/configuration");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals(RuntimeType.SERVER.name(), response.readEntity(String.class));
+    }
+
+    @Test
+    void httpHeader() {
+        final Response response = get("inject/httpHeaders/test-header");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals("test-value", response.readEntity(String.class));
+    }
+
+    @Test
+    void request() {
+        final Response response = get("inject/request");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    void resourceContext() {
+        final Response response = get("inject/resourceContext");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertTrue(response.readEntity(String.class)
+                .startsWith(RequiredContextResource.class.getCanonicalName()));
+    }
+
+    @Test
+    void resourceInfo() {
+        final Response response = get("inject/resourceInfo");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals("resourceInfo", response.readEntity(String.class));
+    }
+
+    @Test
+    void securityContext() {
+        final Response response = get("inject/securityContext");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals("false", response.readEntity(String.class));
+    }
+
+    @Test
+    void uriInfo() {
+        final Response response = get("inject/uriInfo");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assertions.assertEquals("/inject/uriInfo", response.readEntity(String.class));
+    }
+
+    @Test
+    void sse() throws Exception {
+        final WebTarget target = client.target(generateUri("inject/sse"));
+        final CompletableFuture<String> cf = new CompletableFuture<>();
+        try (SseEventSource source = SseEventSource.target(target).build()) {
+            source.register(event -> {
+                try {
+                    cf.complete(event.readData());
+                } catch (Throwable t) {
+                    cf.completeExceptionally(t);
+                }
+            });
+            source.open();
+            Assertions.assertEquals("test", cf.get(5, TimeUnit.SECONDS));
+        }
+    }
+
+    @Test
+    void asyncResponseByTypeAlone() {
+        final Response response = get("inject/async");
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus(),
+                () -> "AsyncResponse by type alone failed: %s".formatted(response.readEntity(String.class)));
+        Assertions.assertEquals("async-test", response.readEntity(String.class));
+    }
+
+    private static void assertAllInjected(final ContextInjectionDescriptor descriptor, final String injectionType) {
+        Assertions.assertAll(
+                () -> Assertions.assertNotNull(descriptor.application(), () -> "Application not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.configuration(), () -> "Configuration not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.httpHeaders(), () -> "HttpHeaders not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.providers(), () -> "Providers not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.request(), () -> "Request not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.resourceContext(), () -> "ResourceContext not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.resourceInfo(), () -> "ResourceInfo not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.securityContext(), () -> "SecurityContext not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.sse(), () -> "Sse not injected via %s: %s".formatted(injectionType, descriptor)),
+                () -> Assertions.assertNotNull(descriptor.uriInfo(), () -> "UriInfo not injected via %s: %s".formatted(injectionType, descriptor))
+        );
+    }
+
+    private ContextInjectionDescriptor getDescriptor(final String path) {
+        final Response response = getJson(path);
+        Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus(),
+                () -> "Unexpected status for " + path + ": " + response.readEntity(String.class));
+        return response.readEntity(ContextInjectionDescriptor.class);
+    }
+
+    private Response get(final String path) {
+        return client.target(generateUri(path))
+                .request()
+                .header("test-header", "test-value")
+                .get();
+    }
+
+    private Response getJson(final String path) {
+        return client.target(generateUri(path))
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .header("test-header", "test-value")
+                .get();
+    }
+
+    private URI generateUri(final String path) {
+        return UriBuilder.fromUri(baseUri).path(path).build();
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextResource.java
new file mode 100644
index 0000000..ec12e62
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/RequiredContextResource.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.function.BiConsumer;
+
+import ee.jakarta.tck.ws.rs.common.provider.StringBean;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
+import jakarta.ws.rs.sse.Sse;
+import jakarta.ws.rs.sse.SseEventSink;
+
+@Path("/inject")
+public class RequiredContextResource {
+
+    @Inject
+    Application application;
+
+    @Inject
+    UriInfo uriInfo;
+
+    @Inject
+    Request request;
+
+    @Inject
+    HttpHeaders httpHeaders;
+
+    @Inject
+    SecurityContext securityContext;
+
+    @Inject
+    Providers providers;
+
+    @Inject
+    ResourceContext resourceContext;
+
+    @Inject
+    Configuration configuration;
+
+    @Inject
+    ResourceInfo resourceInfo;
+
+    @Inject
+    Sse sse;
+
+    @GET
+    @Path("field")
+    @Produces(MediaType.APPLICATION_JSON)
+    public ContextInjectionDescriptor field() {
+        return ContextInjectionDescriptor.of(application, configuration, httpHeaders, providers,
+                request, resourceContext, resourceInfo, securityContext, sse, uriInfo);
+    }
+
+    @GET
+    @Path("method")
+    @Produces(MediaType.APPLICATION_JSON)
+    public ContextInjectionDescriptor method(final Application application, final UriInfo uriInfo,
+                                             final Request request, final HttpHeaders httpHeaders,
+                                             final SecurityContext securityContext, final Providers providers,
+                                             final ResourceContext resourceContext, final Configuration configuration,
+                                             final ResourceInfo resourceInfo, final Sse sse) {
+        return ContextInjectionDescriptor.of(application, configuration, httpHeaders, providers,
+                request, resourceContext, resourceInfo, securityContext, sse, uriInfo);
+    }
+
+    @GET
+    @Path("/application/{propertyName}")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response application(@PathParam("propertyName") final String propertyName) {
+        final var properties = application.getProperties();
+        if (properties.containsKey(propertyName)) {
+            return Response.ok(properties.get(propertyName)).build();
+        }
+        return Response.status(Response.Status.BAD_REQUEST)
+                .entity("Failed to find property %s in %s".formatted(propertyName, properties))
+                .build();
+    }
+
+    @GET
+    @Path("/configuration")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response configuration() {
+        if (configuration == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The configuration field is null.").build();
+        }
+        return Response.ok(configuration.getRuntimeType().toString()).build();
+    }
+
+    @GET
+    @Path("/httpHeaders/{name}")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response httpHeaders(@PathParam("name") final String name) {
+        if (httpHeaders == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The httpHeaders field is null.").build();
+        }
+        return Response.ok(httpHeaders.getHeaderString(name)).build();
+    }
+
+    @GET
+    @Path("/providers")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response providers() {
+        final var mbw = providers.getMessageBodyWriter(StringBean.class, null, null, MediaType.WILDCARD_TYPE);
+        if (!(mbw instanceof StringBeanEntityProviderWithInjectables instance)) {
+            return Response.status(Response.Status.BAD_REQUEST)
+                    .entity("Failed to find MessageBodyWriter for StringBean. This should be %s, but was %s"
+                            .formatted(StringBeanEntityProviderWithInjectables.class, mbw))
+                    .build();
+        }
+        return Response.ok(instance.describe()).build();
+    }
+
+    @GET
+    @Path("/request")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response request() {
+        if (request == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The request field is null.").build();
+        }
+        return Response.ok(request.getMethod()).build();
+    }
+
+    @GET
+    @Path("resourceContext")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response resourceContext() {
+        if (resourceContext == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The resourceContext field is null.").build();
+        }
+        return Response.ok(resourceContext.getResource(getClass()).getClass().getCanonicalName()).build();
+    }
+
+    @GET
+    @Path("resourceInfo")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response resourceInfo() {
+        if (resourceInfo == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The resourceInfo field is null.").build();
+        }
+        return Response.ok(resourceInfo.getResourceMethod().getName()).build();
+    }
+
+    @GET
+    @Path("/securityContext")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response securityContext() {
+        if (securityContext == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The securityContext field is null.").build();
+        }
+        return Response.ok(securityContext.isSecure()).build();
+    }
+
+    @GET
+    @Path("/sse")
+    @Produces(MediaType.SERVER_SENT_EVENTS)
+    public CompletionStage<?> sse(final SseEventSink eventSink) throws IOException {
+        if (eventSink == null) {
+            return CompletableFuture.failedFuture(new WebApplicationException("The eventSink parameter is null"));
+        }
+        if (sse == null) {
+            return CompletableFuture.failedFuture(new WebApplicationException("The sse field is null"));
+        }
+        return eventSink.send(sse.newEvent("test"))
+                .whenComplete((BiConsumer<Object, Throwable>) (unused, throwable) -> {
+                    try {
+                        eventSink.close();
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                });
+    }
+
+    @GET
+    @Path("/async")
+    @Produces(MediaType.TEXT_PLAIN)
+    public void async(final AsyncResponse asyncResponse) {
+        if (asyncResponse == null) {
+            throw new WebApplicationException("The asyncResponse parameter is null");
+        }
+        asyncResponse.resume("async-test");
+    }
+
+    @GET
+    @Path("/uriInfo")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response uriInfo() {
+        if (uriInfo == null) {
+            return Response.status(Response.Status.BAD_REQUEST).entity("The uriInfo field is null.").build();
+        }
+        return Response.ok(uriInfo.getPath()).build();
+    }
+
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/StringBeanEntityProviderWithInjectables.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/StringBeanEntityProviderWithInjectables.java
new file mode 100644
index 0000000..7ab9de0
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/StringBeanEntityProviderWithInjectables.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi;
+
+import ee.jakarta.tck.ws.rs.common.provider.StringBeanEntityProvider;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.Providers;
+
+@Provider
+public class StringBeanEntityProviderWithInjectables extends StringBeanEntityProvider {
+
+    @Inject
+    Application application;
+
+    @Inject
+    UriInfo uriInfo;
+
+    @Inject
+    Request request;
+
+    @Inject
+    HttpHeaders httpHeaders;
+
+    @Inject
+    SecurityContext securityContext;
+
+    @Inject
+    Providers providers;
+
+    @Inject
+    ResourceContext resourceContext;
+
+    @Inject
+    Configuration configuration;
+
+    public ContextInjectionDescriptor describe() {
+        return ContextInjectionDescriptor.of(application, configuration, httpHeaders, providers,
+                request, resourceContext, null, securityContext, null, uriInfo);
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/AbstractParamIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/AbstractParamIT.java
new file mode 100644
index 0000000..c543299
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/AbstractParamIT.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.net.URI;
+
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriBuilder;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@Tag("cdi")
+abstract class AbstractParamIT {
+
+    private final String contextPath;
+
+    @ArquillianResource
+    protected URI baseUri;
+
+    AbstractParamIT(final String contextPath) {
+        this.contextPath = contextPath;
+    }
+
+    static WebArchive defaultDeployment(final Class<? extends AbstractParamIT> testClass) {
+        return ShrinkWrap.create(WebArchive.class, testClass.getSimpleName() + ".war")
+                .addClasses(ParamApplication.class, ParamDescriptor.class, ParamResource.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    @Test
+    void constructorParameters() {
+        final ParamDescriptor param = invokeRequest("constructor");
+        // Check the parameters
+        Assertions.assertEquals("cookieParamValue", param.getCookieParam(),
+                () -> "@CookieParam parameter was not set on the constructor: %s".formatted(param));
+        Assertions.assertEquals("formParamValue", param.getFormParam(),
+                () -> "@FormParam parameter was not set on the constructor: %s".formatted(param));
+        Assertions.assertEquals("headerParamValue", param.getHeaderParam(),
+                () -> "@HeaderParam parameter was not set on the constructor: %s".formatted(param));
+        Assertions.assertEquals(10, param.getMatrixParam(),
+                () -> "@MatrixParam parameter was not set on the constructor: %s".formatted(param));
+        Assertions.assertEquals("constructorParameters", param.getPathParam(),
+                () -> "@PathParam parameter was not set on the constructor: %s".formatted(param));
+        Assertions.assertEquals(100, param.getQueryParam(),
+                () -> "@QueryParam parameter was not set on the constructor: %s".formatted(param));
+    }
+
+    @Test
+    void fieldParameters() {
+        final ParamDescriptor param = invokeRequest("field/fieldParamValue");
+        // Check the parameters
+        Assertions.assertEquals("fieldCookieParamValue", param.getCookieParam(),
+                () -> "@CookieParam parameter was not set on the field: %s".formatted(param));
+        Assertions.assertEquals("fieldFormParamValue", param.getFormParam(),
+                () -> "@FormParam parameter was not set on the field: %s".formatted(param));
+        Assertions.assertEquals("fieldHeaderParamValue", param.getHeaderParam(),
+                () -> "@HeaderParam parameter was not set on the field: %s".formatted(param));
+        Assertions.assertEquals(20, param.getMatrixParam(),
+                () -> "@MatrixParam parameter was not set on the field: %s".formatted(param));
+        Assertions.assertEquals("fieldParamValue", param.getPathParam(),
+                () -> "@PathParam parameter was not set on the field: %s".formatted(param));
+        Assertions.assertEquals(200, param.getQueryParam(),
+                () -> "@QueryParam parameter was not set on the field: %s".formatted(param));
+    }
+
+    @Test
+    void methodParameters() {
+        final ParamDescriptor param = invokeRequest("method/methodParamValue");
+        // Check the parameters
+        Assertions.assertEquals("methodCookieParamValue", param.getCookieParam(),
+                () -> "@CookieParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodFormParamValue", param.getFormParam(),
+                () -> "@FormParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodHeaderParamValue", param.getHeaderParam(),
+                () -> "@HeaderParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals(30, param.getMatrixParam(),
+                () -> "@MatrixParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodParamValue", param.getPathParam(),
+                () -> "@PathParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals(300, param.getQueryParam(),
+                () -> "@QueryParam parameter was not set on the method: %s".formatted(param));
+    }
+
+    @Test
+    void methodParametersAnnotated() {
+        final ParamDescriptor param = invokeRequest("method-param/methodParamValuePa");
+        // Check the parameters
+        Assertions.assertEquals("methodCookieParamValuePa", param.getCookieParam(),
+                () -> "@CookieParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodFormParamValuePa", param.getFormParam(),
+                () -> "@FormParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodHeaderParamValuePa", param.getHeaderParam(),
+                () -> "@HeaderParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals(40, param.getMatrixParam(),
+                () -> "@MatrixParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals("methodParamValuePa", param.getPathParam(),
+                () -> "@PathParam parameter was not set on the method: %s".formatted(param));
+        Assertions.assertEquals(400, param.getQueryParam(),
+                () -> "@QueryParam parameter was not set on the method: %s".formatted(param));
+    }
+
+    private ParamDescriptor invokeRequest(final String path) {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path(contextPath + "/constructorParameters/" + path)
+                    .matrixParam("matrixParam", 10)
+                    .matrixParam("fieldMatrixParam", 20)
+                    .matrixParam("methodMatrixParam", 30)
+                    .matrixParam("methodMatrixParamPa", 40)
+                    .queryParam("queryParam", 100)
+                    .queryParam("fieldQueryParam", 200)
+                    .queryParam("methodQueryParam", 300)
+                    .queryParam("methodQueryParamPa", 400);
+            final Form form = new Form()
+                    .param("formParam", "formParamValue")
+                    .param("fieldFormParam", "fieldFormParamValue")
+                    .param("methodFormParam", "methodFormParamValue")
+                    .param("methodFormParamPa", "methodFormParamValuePa");
+            final WebTarget target = client.target(uriBuilder);
+            final ParamDescriptor param = target.request(MediaType.APPLICATION_JSON_TYPE)
+                    .cookie("cookieParam", "cookieParamValue")
+                    .cookie("fieldCookieParam", "fieldCookieParamValue")
+                    .cookie("methodCookieParam", "methodCookieParamValue")
+                    .cookie("methodCookieParamPa", "methodCookieParamValuePa")
+                    .header("headerParam", "headerParamValue")
+                    .header("fieldHeaderParam", "fieldHeaderParamValue")
+                    .header("methodHeaderParam", "methodHeaderParamValue")
+                    .header("methodHeaderParamPa", "methodHeaderParamValuePa")
+                    .post(Entity.form(form), ParamDescriptor.class);
+            Assertions.assertNotNull(param, () -> "Failed to find the parameters with URI %s".formatted(uriBuilder.build()));
+            return param;
+        }
+    }
+
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamIT.java
new file mode 100644
index 0000000..3998cac
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamIT.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.net.URI;
+
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriBuilder;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests that a {@link jakarta.ws.rs.BeanParam @BeanParam} works with CDI.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ArquillianTest
+@Tag("cdi")
+class CdiBeanParamIT {
+
+    @ArquillianResource
+    private URI baseUri;
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        return ShrinkWrap.create(WebArchive.class, CdiBeanParamIT.class.getSimpleName() + ".war")
+                .addClasses(ParamApplication.class, CdiBeanParamResource.class, SearchParams.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    @Test
+    void beanParam() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("bean-param")
+                    .queryParam("q", "testValue")
+                    .queryParam("limit", 25);
+            final SearchParams result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .header("Accept-Language", "en-US")
+                    .get(SearchParams.class);
+            Assertions.assertNotNull(result);
+            Assertions.assertEquals("testValue", result.getQuery(),
+                    () -> "Expected a result of 'testValue' in the query parameter: %s".formatted(result));
+            Assertions.assertEquals(25, result.getLimit(),
+                    () -> "Expected a result of '25' in the limit parameter: %s".formatted(result));
+            Assertions.assertEquals("en-US", result.getLanguage(),
+                    () -> "Expected a result of 'en-US' in the Accepted-Language parameter: %s".formatted(result));
+        }
+    }
+
+    @Test
+    void beanParamDefaults() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("bean-param")
+                    .queryParam("q", "test");
+            final SearchParams result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(SearchParams.class);
+            Assertions.assertNotNull(result);
+            Assertions.assertEquals("test", result.getQuery(),
+                    () -> "Expected a result of 'test' in the query parameter: %s".formatted(result));
+            Assertions.assertEquals(10, result.getLimit(),
+                    () -> "Expected a result of '10', @DefaultValue, in the limit parameter: %s".formatted(result));
+            Assertions.assertNull(result.getLanguage(), () -> "Accept-Language header should be null: %s".formatted(result));
+        }
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamResource.java
new file mode 100644
index 0000000..a4fe70f
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiBeanParamResource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.BeanParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/bean-param")
+@RequestScoped
+public class CdiBeanParamResource {
+
+    @Inject
+    @BeanParam
+    private SearchParams params;
+
+    CdiBeanParamResource() {
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public SearchParams get() {
+        return params;
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedIT.java
new file mode 100644
index 0000000..21af788
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedIT.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.net.URI;
+
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests that CDI injected parameters work with {@link jakarta.ws.rs.Encoded @Encoded}
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ArquillianTest
+@Tag("cdi")
+class CdiParamEncodedIT {
+
+    @ArquillianResource
+    private URI baseUri;
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        return ShrinkWrap.create(WebArchive.class, CdiParamEncodedIT.class.getSimpleName() + ".war")
+                .addClasses(ParamApplication.class, CdiParamEncodedResource.class,
+                        CdiParamNotEncodedResource.class, EncodedDescriptor.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    @Test
+    void classLevelEncoded() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("encoded/hello%20world")
+                    .queryParam("q", "hello%20world");
+            final EncodedDescriptor result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(EncodedDescriptor.class);
+            Assertions.assertNotNull(result);
+            Assertions.assertTrue(result.getQueryValue().contains("%20"),
+                    () -> "Class-level @Encoded query should retain %%20, got: %s".formatted(result.getQueryValue()));
+            Assertions.assertTrue(result.getPathValue().contains("%20"),
+                    () -> "Class-level @Encoded path should retain %%20, got: %s".formatted(result.getPathValue()));
+        }
+    }
+
+    @Test
+    void fieldLevelEncoded() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("not-encoded/hello%20world")
+                    .queryParam("q", "hello%20world")
+                    .queryParam("q2", "hello%20world");
+            final EncodedDescriptor result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(EncodedDescriptor.class);
+            Assertions.assertNotNull(result);
+            Assertions.assertTrue(result.getQueryValue().contains("%20"),
+                    () -> "Field-level @Encoded query should retain %%20, got: %s".formatted(result.getQueryValue()));
+            Assertions.assertEquals("hello world", result.getDecodedQuery(),
+                    () -> "non-encoded query should decode %%20 to space: %s".formatted(result));
+            Assertions.assertEquals("hello world", result.getPathValue(),
+                    () -> "non-encoded path should decode %%20 to space: %s".formatted(result));
+        }
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedResource.java
new file mode 100644
index 0000000..64d1102
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamEncodedResource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Encoded;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/encoded/{p}")
+@RequestScoped
+@Encoded
+public class CdiParamEncodedResource {
+
+    @Inject
+    @QueryParam("q")
+    private String queryValue;
+
+    @Inject
+    @PathParam("p")
+    private String pathValue;
+
+    CdiParamEncodedResource() {
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public EncodedDescriptor get() {
+        return EncodedDescriptor.of()
+                .setQueryValue(queryValue)
+                .setPathValue(pathValue);
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamIT.java
new file mode 100644
index 0000000..1728b40
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamIT.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+
+/**
+ * Test that parameter extraction annotation annotated fields, constructor parameters and method parameters are injected.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ArquillianTest
+class CdiParamIT extends AbstractParamIT {
+
+    CdiParamIT() {
+        super("params");
+    }
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        return defaultDeployment(CdiParamIT.class).addClass(CdiParamResource.class);
+    }
+
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedIT.java
new file mode 100644
index 0000000..bc9ca14
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedIT.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.net.URI;
+
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import jakarta.json.JsonObject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests that CDI injection works on a constructor with both parameter extraction annotations and standard CDI beans.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ArquillianTest
+@Tag("cdi")
+class CdiParamMixedIT {
+
+    @ArquillianResource
+    private URI baseUri;
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        return ShrinkWrap.create(WebArchive.class, CdiParamMixedIT.class.getSimpleName() + ".war")
+                .addClasses(ParamApplication.class, CdiParamMixedResource.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    @Test
+    void mixedConstructor() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("mixed")
+                    .queryParam("q", "testValue");
+            final JsonObject result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .header("Custom", "custom-value")
+                    .get(JsonObject.class);
+            Assertions.assertNotNull(result);
+            Assertions.assertEquals("testValue", result.getString("query"),
+                    () -> "@QueryParam should be injected in mixed constructor: %s".formatted(result));
+            Assertions.assertFalse(result.getString("path").isEmpty(),
+                    () -> "UriInfo should be injected in mixed constructor: %s".formatted(result));
+            Assertions.assertEquals("custom-value", result.getString("customHeader"),
+                    () -> "@HeaderParam should be injected in mixed constructor: %s".formatted(result));
+        }
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedResource.java
new file mode 100644
index 0000000..5aa85bd
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamMixedResource.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriInfo;
+
+@Path("/mixed")
+@RequestScoped
+public class CdiParamMixedResource {
+
+    private final String query;
+    private final UriInfo uriInfo;
+    private final String customHeader;
+
+    CdiParamMixedResource() {
+        this.query = null;
+        this.uriInfo = null;
+        this.customHeader = null;
+    }
+
+    @Inject
+    public CdiParamMixedResource(@QueryParam("q") final String query,
+                                 final UriInfo uriInfo,
+                                 @HeaderParam("Custom") final String customHeader) {
+        this.query = query;
+        this.uriInfo = uriInfo;
+        this.customHeader = customHeader;
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject get() {
+        return Json.createObjectBuilder()
+                .add("query", query != null ? query : "")
+                .add("path", uriInfo != null ? uriInfo.getPath() : "")
+                .add("customHeader", customHeader != null ? customHeader : "")
+                .build();
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamNotEncodedResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamNotEncodedResource.java
new file mode 100644
index 0000000..49262b0
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamNotEncodedResource.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Encoded;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/not-encoded/{p}")
+@RequestScoped
+public class CdiParamNotEncodedResource {
+
+    @Inject
+    @Encoded
+    @QueryParam("q")
+    private String encodedQuery;
+
+    @Inject
+    @QueryParam("q2")
+    private String decodedQuery;
+
+    @Inject
+    @PathParam("p")
+    private String pathValue;
+
+    CdiParamNotEncodedResource() {
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public EncodedDescriptor get() {
+        return EncodedDescriptor.of()
+                .setQueryValue(encodedQuery)
+                .setDecodedQuery(decodedQuery)
+                .setPathValue(pathValue);
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamResource.java
new file mode 100644
index 0000000..f3c1bd9
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamResource.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.io.InputStream;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.CookieParam;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.MatrixParam;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.QueryParam;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@Path("/params/{pathParam}")
+@RequestScoped
+public class CdiParamResource implements ParamResource {
+    private final String cookieParam;
+    private final String formParam;
+    private final String headerParam;
+    private final long matrixParam;
+    private final String pathParam;
+    private final int queryParam;
+
+    @Inject
+    @CookieParam("fieldCookieParam")
+    private String fieldCookieParam;
+    @Inject
+    @FormParam("fieldFormParam")
+    private String fieldFormParam;
+    @Inject
+    @HeaderParam("fieldHeaderParam")
+    private String fieldHeaderParam;
+    @Inject
+    @MatrixParam("fieldMatrixParam")
+    private int fieldMatrixParam;
+    @Inject
+    @PathParam("fieldPathParam")
+    private String fieldPathParam;
+    @Inject
+    @QueryParam("fieldQueryParam")
+    private int fieldQueryParam;
+
+    private String methodCookieParam;
+    private String methodFormParam;
+    private String methodHeaderParam;
+    private int methodMatrixParam;
+    private String methodPathParam;
+    private int methodQueryParam;
+
+    private String methodCookieParamPa;
+    private String methodFormParamPa;
+    private String methodHeaderParamPa;
+    private int methodMatrixParamPa;
+    private String methodPathParamPa;
+    private int methodQueryParamPa;
+
+    CdiParamResource() {
+        cookieParam = null;
+        formParam = null;
+        headerParam = null;
+        matrixParam = -1;
+        pathParam = null;
+        queryParam = -1;
+    }
+
+    @Inject
+    public CdiParamResource(@CookieParam("cookieParam") final String cookieParam,
+                            @FormParam("formParam") final String formParam,
+                            @HeaderParam("headerParam") final String headerParam,
+                            @MatrixParam("matrixParam") final long matrixParam,
+                            @PathParam("pathParam") final String pathParam,
+                            @QueryParam("queryParam") final int queryParam) {
+        this.cookieParam = cookieParam;
+        this.formParam = formParam;
+        this.headerParam = headerParam;
+        this.matrixParam = matrixParam;
+        this.pathParam = pathParam;
+        this.queryParam = queryParam;
+    }
+
+    @Override
+    public ParamDescriptor constructor(final InputStream body) {
+        return ParamDescriptor.of()
+                .setCookieParam(cookieParam)
+                .setFormParam(formParam)
+                .setHeaderParam(headerParam)
+                .setMatrixParam(matrixParam)
+                .setPathParam(pathParam)
+                .setQueryParam(queryParam);
+    }
+
+    @Override
+    public ParamDescriptor field(final InputStream body) {
+        return ParamDescriptor.of()
+                .setCookieParam(fieldCookieParam)
+                .setFormParam(fieldFormParam)
+                .setHeaderParam(fieldHeaderParam)
+                .setMatrixParam(fieldMatrixParam)
+                .setPathParam(fieldPathParam)
+                .setQueryParam(fieldQueryParam);
+    }
+
+    @Override
+    public ParamDescriptor method(final InputStream body) {
+        return ParamDescriptor.of()
+                .setCookieParam(methodCookieParam)
+                .setFormParam(methodFormParam)
+                .setHeaderParam(methodHeaderParam)
+                .setMatrixParam(methodMatrixParam)
+                .setPathParam(methodPathParam)
+                .setQueryParam(methodQueryParam);
+    }
+
+    @Override
+    public ParamDescriptor methodParamsAnnotated(final InputStream body) {
+        return ParamDescriptor.of()
+                .setCookieParam(methodCookieParamPa)
+                .setFormParam(methodFormParamPa)
+                .setHeaderParam(methodHeaderParamPa)
+                .setMatrixParam(methodMatrixParamPa)
+                .setPathParam(methodPathParamPa)
+                .setQueryParam(methodQueryParamPa);
+    }
+
+    @Inject
+    @CookieParam("methodCookieParam")
+    public void setCookieParam(final String methodCookieParam) {
+        this.methodCookieParam = methodCookieParam;
+    }
+
+    @Inject
+    @FormParam("methodFormParam")
+    public void setFormParam(final String methodFormParam) {
+        this.methodFormParam = methodFormParam;
+    }
+
+    @Inject
+    @HeaderParam("methodHeaderParam")
+    public void setHeaderParam(final String methodHeaderParam) {
+        this.methodHeaderParam = methodHeaderParam;
+    }
+
+    @Inject
+    @MatrixParam("methodMatrixParam")
+    public void setMatrixParam(final int methodMatrixParam) {
+        this.methodMatrixParam = methodMatrixParam;
+    }
+
+    @Inject
+    @PathParam("methodPathParam")
+    public void setPathParam(final String methodPathParam) {
+        this.methodPathParam = methodPathParam;
+    }
+
+    @Inject
+    @QueryParam("methodQueryParam")
+    public void setQueryParam(final int methodQueryParam) {
+        this.methodQueryParam = methodQueryParam;
+    }
+
+    @Inject
+    public void setCookieParamPa(@CookieParam("methodCookieParamPa") final String cookieParam) {
+        this.methodCookieParamPa = cookieParam;
+    }
+
+    @Inject
+    public void setFormParamPa(@FormParam("methodFormParamPa") final String formParam) {
+        this.methodFormParamPa = formParam;
+    }
+
+    @Inject
+    public void setHeaderParamPa(@HeaderParam("methodHeaderParamPa") final String headerParam) {
+        this.methodHeaderParamPa = headerParam;
+    }
+
+    @Inject
+    public void setMatrixParamPa(@MatrixParam("methodMatrixParamPa") final int matrixParam) {
+        this.methodMatrixParamPa = matrixParam;
+    }
+
+    @Inject
+    public void setPathParamPa(@PathParam("methodPathParamPa") final String pathParam) {
+        this.methodPathParamPa = pathParam;
+    }
+
+    @Inject
+    public void setQueryParamPa(@QueryParam("methodQueryParamPa") final int queryParam) {
+        this.methodQueryParamPa = queryParam;
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesIT.java
new file mode 100644
index 0000000..1fa5961
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesIT.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import ee.jakarta.tck.ws.rs.common.util.CdiSupport;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit5.container.annotation.ArquillianTest;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests various parameter extraction annotation injections work with various required types.
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ArquillianTest
+@Tag("cdi")
+class CdiParamTypesIT {
+
+    @ArquillianResource
+    private URI baseUri;
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        return ShrinkWrap.create(WebArchive.class, CdiParamTypesIT.class.getSimpleName() + ".war")
+                .addClasses(ParamApplication.class, CdiParamTypesResource.class,
+                        TypesDescriptor.class, ParamEnum.class)
+                .addAsWebInfResource(CdiSupport.BEANS_XML, "beans.xml");
+    }
+
+    @Test
+    void allTypes() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("types/path1/path2")
+                    .queryParam("list", "a", "b", "c")
+                    .queryParam("set", "x", "y", "z")
+                    .queryParam("sortedSet", "c", "a", "b")
+                    .queryParam("array", "one", "two")
+                    .queryParam("wrapper", 99)
+                    .queryParam("bool", true)
+                    .queryParam("enum", "VALUE_ONE")
+                    .queryParam("default", "explicit")
+                    .queryParam("defaultInt", 7);
+            final TypesDescriptor result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(TypesDescriptor.class);
+            Assertions.assertNotNull(result);
+
+            // Collection types
+            Assertions.assertNotNull(result.getListParam(), () -> "List should not be null: %s".formatted(result));
+            Assertions.assertEquals(3, result.getListParam().size(),
+                    () -> "Expected list size of 3: %s".formatted(result));
+            Assertions.assertTrue(result.getListParam().containsAll(List.of("a", "b", "c")),
+                    () -> "Expected list to contain [a, b, c]: %s".formatted(result));
+
+            Assertions.assertNotNull(result.getSetParam(),
+                    () -> "Set should not be null: %s".formatted(result));
+            Assertions.assertEquals(3, result.getSetParam().size(),
+                    () -> "Expected set size of 3: %s".formatted(result));
+            Assertions.assertTrue(result.getSetParam().containsAll(Set.of("x", "y", "z")),
+                    () -> "Expected set to contain [x, y, z]: %s".formatted(result));
+
+            Assertions.assertNotNull(result.getSortedSetParam(),
+                    () -> "SortedSet should not be null: %s".formatted(result));
+            Assertions.assertEquals(3, result.getSortedSetParam().size(),
+                    () -> "Expected sortedSet size of 3: %s".formatted(result));
+            Assertions.assertEquals("a", result.getSortedSetParam().first(),
+                    () -> "SortedSet should be sorted, expected 'a' first: %s".formatted(result));
+
+            // Array
+            Assertions.assertNotNull(result.getArrayParam(),
+                    () -> "Array should not be null: %s".formatted(result));
+            Assertions.assertArrayEquals(new String[] {"one", "two"}, result.getArrayParam(),
+                    () -> "Expected array [one, two]: %s".formatted(result));
+
+            // Wrapper and primitive types
+            Assertions.assertEquals(99, result.getWrapperParam(),
+                    () -> "Expected wrapper value of 99: %s".formatted(result));
+            Assertions.assertEquals(true, result.getBooleanParam(),
+                    () -> "Expected boolean value of true: %s".formatted(result));
+
+            // Enum
+            Assertions.assertEquals(ParamEnum.VALUE_ONE, result.getEnumParam(),
+                    () -> "Expected enum VALUE_ONE: %s".formatted(result));
+
+            // Explicit values override @DefaultValue
+            Assertions.assertEquals("explicit", result.getDefaultParam(),
+                    () -> "Expected default string to be 'explicit': %s".formatted(result));
+            Assertions.assertEquals(7, result.getDefaultIntParam(),
+                    () -> "Expected default int to be 7: %s".formatted(result));
+
+            // PathSegment
+            final List<String> listPaths = result.getListPaths();
+            Assertions.assertEquals(2, listPaths.size(), () -> "Expected two PathSegments in %s".formatted(result));
+            Assertions.assertEquals("path1", listPaths.get(0),
+                    () -> "Expected the first PathSegment to be path1 in %s".formatted(result));
+            Assertions.assertEquals("path2", listPaths.get(1),
+                    () -> "Expected the first PathSegment to be path2 in %s".formatted(result));
+            Assertions.assertEquals("path2", result.getSinglePath(),
+                    () -> "Expected the single PathSegment to be path2 in %s".formatted(result));
+        }
+    }
+
+    @Test
+    void defaultValues() {
+        try (Client client = ClientBuilder.newClient()) {
+            final UriBuilder uriBuilder = UriBuilder.fromUri(baseUri)
+                    .path("types/ignored");
+            final TypesDescriptor result = client.target(uriBuilder)
+                    .request(MediaType.APPLICATION_JSON_TYPE)
+                    .get(TypesDescriptor.class);
+            Assertions.assertNotNull(result);
+
+            // @DefaultValue should apply when params are absent
+            Assertions.assertEquals("fallback", result.getDefaultParam(),
+                    () -> "Expected default string 'fallback' when param is absent: %s".formatted(result));
+            Assertions.assertEquals(42, result.getDefaultIntParam(),
+                    () -> "Expected default int 42 when param is absent: %s".formatted(result));
+
+            // Absent optional params without @DefaultValue
+            Assertions.assertNull(result.getWrapperParam(),
+                    () -> "Absent wrapper should be null: %s".formatted(result));
+            Assertions.assertNull(result.getBooleanParam(),
+                    () -> "Absent boolean should be null: %s".formatted(result));
+            Assertions.assertNull(result.getEnumParam(),
+                    () -> "Absent enum should be null: %s".formatted(result));
+        }
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesResource.java
new file mode 100644
index 0000000..7f022f2
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/CdiParamTypesResource.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.PathSegment;
+
+@Path("/types/{paths:.+}")
+@RequestScoped
+public class CdiParamTypesResource {
+
+    @Inject
+    @QueryParam("list")
+    private List<String> listParam;
+
+    @Inject
+    @QueryParam("set")
+    private Set<String> setParam;
+
+    @Inject
+    @QueryParam("sortedSet")
+    private SortedSet<String> sortedSetParam;
+
+    @Inject
+    @QueryParam("array")
+    private String[] arrayParam;
+
+    @Inject
+    @QueryParam("wrapper")
+    private Integer wrapperParam;
+
+    @Inject
+    @QueryParam("bool")
+    private Boolean booleanParam;
+
+    @Inject
+    @QueryParam("enum")
+    private ParamEnum enumParam;
+
+    @Inject
+    @QueryParam("default")
+    @DefaultValue("fallback")
+    private String defaultParam;
+
+    @Inject
+    @QueryParam("defaultInt")
+    @DefaultValue("42")
+    private int defaultIntParam;
+
+    @Inject
+    @PathParam("paths")
+    private List<PathSegment> listPaths;
+
+    @Inject
+    @PathParam("paths")
+    private PathSegment singlePath;
+
+    CdiParamTypesResource() {
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public TypesDescriptor get() {
+        return TypesDescriptor.of()
+                .setListParam(listParam)
+                .setSetParam(setParam)
+                .setSortedSetParam(sortedSetParam)
+                .setArrayParam(arrayParam)
+                .setWrapperParam(wrapperParam)
+                .setBooleanParam(booleanParam)
+                .setEnumParam(enumParam)
+                .setDefaultParam(defaultParam)
+                .setDefaultIntParam(defaultIntParam)
+                .setListPaths(listPaths.stream().map(PathSegment::getPath).toList())
+                .setSinglePath(singlePath.getPath());
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/EncodedDescriptor.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/EncodedDescriptor.java
new file mode 100644
index 0000000..b24e122
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/EncodedDescriptor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+public class EncodedDescriptor {
+    private String queryValue;
+    private String pathValue;
+    private String decodedQuery;
+
+    public static EncodedDescriptor of() {
+        return new EncodedDescriptor();
+    }
+
+    public String getQueryValue() {
+        return queryValue;
+    }
+
+    public EncodedDescriptor setQueryValue(final String queryValue) {
+        this.queryValue = queryValue;
+        return this;
+    }
+
+    public String getPathValue() {
+        return pathValue;
+    }
+
+    public EncodedDescriptor setPathValue(final String pathValue) {
+        this.pathValue = pathValue;
+        return this;
+    }
+
+    public String getDecodedQuery() {
+        return decodedQuery;
+    }
+
+    public EncodedDescriptor setDecodedQuery(final String decodedQuery) {
+        this.decodedQuery = decodedQuery;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "EncodedDescriptor{" + "queryValue='" + queryValue + '\'' +
+                ", pathValue='" + pathValue + '\'' +
+                ", decodedQuery='" + decodedQuery + '\'' +
+                '}';
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamApplication.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamApplication.java
new file mode 100644
index 0000000..e6891d0
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamApplication.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Application;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@ApplicationPath("/")
+public class ParamApplication extends Application {
+
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamDescriptor.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamDescriptor.java
new file mode 100644
index 0000000..2b88f12
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamDescriptor.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+public class ParamDescriptor {
+    private String cookieParam;
+    private String formParam;
+    private String headerParam;
+    private long matrixParam;
+    private String pathParam;
+    private int queryParam;
+
+    public static ParamDescriptor of() {
+        return new ParamDescriptor();
+    }
+
+    public String getCookieParam() {
+        return cookieParam;
+    }
+
+    public ParamDescriptor setCookieParam(final String cookieParam) {
+        this.cookieParam = cookieParam;
+        return this;
+    }
+
+    public String getFormParam() {
+        return formParam;
+    }
+
+    public ParamDescriptor setFormParam(final String formParam) {
+        this.formParam = formParam;
+        return this;
+    }
+
+    public String getHeaderParam() {
+        return headerParam;
+    }
+
+    public ParamDescriptor setHeaderParam(final String headerParam) {
+        this.headerParam = headerParam;
+        return this;
+    }
+
+    public long getMatrixParam() {
+        return matrixParam;
+    }
+
+    public ParamDescriptor setMatrixParam(final long matrixParam) {
+        this.matrixParam = matrixParam;
+        return this;
+    }
+
+    public String getPathParam() {
+        return pathParam;
+    }
+
+    public ParamDescriptor setPathParam(final String pathParam) {
+        this.pathParam = pathParam;
+        return this;
+    }
+
+    public int getQueryParam() {
+        return queryParam;
+    }
+
+    public ParamDescriptor setQueryParam(final int queryParam) {
+        this.queryParam = queryParam;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "ParamDescriptor{" + "cookieParam='" + cookieParam + '\'' +
+                ", formParam='" + formParam + '\'' +
+                ", headerParam='" + headerParam + '\'' +
+                ", matrixParam=" + matrixParam +
+                ", pathParam='" + pathParam + '\'' +
+                ", queryParam=" + queryParam +
+                '}';
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamEnum.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamEnum.java
new file mode 100644
index 0000000..dba4258
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamEnum.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+public enum ParamEnum {
+    VALUE_ONE,
+    VALUE_TWO
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamResource.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamResource.java
new file mode 100644
index 0000000..f029413
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/ParamResource.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.io.InputStream;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ *
+ * @author <a href="mailto:jperkins@ibm.com">James R. Perkins</a>
+ */
+@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+@Produces(MediaType.APPLICATION_JSON)
+public interface ParamResource {
+
+    @Path("constructor")
+    @POST
+    ParamDescriptor constructor(InputStream body);
+
+    @Path("field/{fieldPathParam}")
+    @POST
+    ParamDescriptor field(InputStream body);
+
+    @Path("method/{methodPathParam}")
+    @POST
+    ParamDescriptor method(InputStream body);
+
+    @Path("method-param/{methodPathParamPa}")
+    @POST
+    ParamDescriptor methodParamsAnnotated(InputStream body);
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/SearchParams.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/SearchParams.java
new file mode 100644
index 0000000..cbcddc1
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/SearchParams.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.QueryParam;
+
+@RequestScoped
+public class SearchParams {
+
+    @Inject
+    @QueryParam("q")
+    private String query;
+
+    @Inject
+    @QueryParam("limit")
+    @DefaultValue("10")
+    private int limit;
+
+    @Inject
+    @HeaderParam("Accept-Language")
+    private String language;
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(final String query) {
+        this.query = query;
+    }
+
+    public int getLimit() {
+        return limit;
+    }
+
+    public void setLimit(final int limit) {
+        this.limit = limit;
+    }
+
+    public String getLanguage() {
+        return language;
+    }
+
+    public void setLanguage(final String language) {
+        this.language = language;
+    }
+
+    @Override
+    public String toString() {
+        return "SearchParams{" + "query='" + query + '\'' +
+                ", limit=" + limit +
+                ", language='" + language + '\'' +
+                '}';
+    }
+}
diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/TypesDescriptor.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/TypesDescriptor.java
new file mode 100644
index 0000000..4d2306b
--- /dev/null
+++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/spec/context/cdi/param/TypesDescriptor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.ws.rs.spec.context.cdi.param;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+public class TypesDescriptor {
+    private List<String> listParam;
+    private Set<String> setParam;
+    private SortedSet<String> sortedSetParam;
+    private String[] arrayParam;
+    private Integer wrapperParam;
+    private Boolean booleanParam;
+    private ParamEnum enumParam;
+    private String defaultParam;
+    private int defaultIntParam;
+    private List<String> listPaths;
+    private String singlePath;
+
+    public static TypesDescriptor of() {
+        return new TypesDescriptor();
+    }
+
+    public List<String> getListParam() {
+        return listParam;
+    }
+
+    public TypesDescriptor setListParam(final List<String> listParam) {
+        this.listParam = listParam;
+        return this;
+    }
+
+    public Set<String> getSetParam() {
+        return setParam;
+    }
+
+    public TypesDescriptor setSetParam(final Set<String> setParam) {
+        this.setParam = setParam;
+        return this;
+    }
+
+    public SortedSet<String> getSortedSetParam() {
+        return sortedSetParam;
+    }
+
+    public TypesDescriptor setSortedSetParam(final SortedSet<String> sortedSetParam) {
+        this.sortedSetParam = sortedSetParam;
+        return this;
+    }
+
+    public String[] getArrayParam() {
+        return arrayParam;
+    }
+
+    public TypesDescriptor setArrayParam(final String[] arrayParam) {
+        this.arrayParam = arrayParam;
+        return this;
+    }
+
+    public Integer getWrapperParam() {
+        return wrapperParam;
+    }
+
+    public TypesDescriptor setWrapperParam(final Integer wrapperParam) {
+        this.wrapperParam = wrapperParam;
+        return this;
+    }
+
+    public Boolean getBooleanParam() {
+        return booleanParam;
+    }
+
+    public TypesDescriptor setBooleanParam(final Boolean booleanParam) {
+        this.booleanParam = booleanParam;
+        return this;
+    }
+
+    public ParamEnum getEnumParam() {
+        return enumParam;
+    }
+
+    public TypesDescriptor setEnumParam(final ParamEnum enumParam) {
+        this.enumParam = enumParam;
+        return this;
+    }
+
+    public String getDefaultParam() {
+        return defaultParam;
+    }
+
+    public TypesDescriptor setDefaultParam(final String defaultParam) {
+        this.defaultParam = defaultParam;
+        return this;
+    }
+
+    public int getDefaultIntParam() {
+        return defaultIntParam;
+    }
+
+    public TypesDescriptor setDefaultIntParam(final int defaultIntParam) {
+        this.defaultIntParam = defaultIntParam;
+        return this;
+    }
+
+    public List<String> getListPaths() {
+        return listPaths;
+    }
+
+    public TypesDescriptor setListPaths(final List<String> listPaths) {
+        this.listPaths = listPaths;
+        return this;
+    }
+
+    public String getSinglePath() {
+        return singlePath;
+    }
+
+    public TypesDescriptor setSinglePath(final String singlePath) {
+        this.singlePath = singlePath;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "TypesDescriptor{" + "listParam=" + listParam +
+                ", setParam=" + setParam +
+                ", sortedSetParam=" + sortedSetParam +
+                ", arrayParam=" + Arrays.toString(arrayParam) +
+                ", wrapperParam=" + wrapperParam +
+                ", booleanParam=" + booleanParam +
+                ", enumParam=" + enumParam +
+                ", defaultParam='" + defaultParam + '\'' +
+                ", defaultIntParam=" + defaultIntParam +
+                ", listPaths=" + listPaths +
+                ", singlePath=" + singlePath +
+                '}';
+    }
+}