Merge pull request #4771 from senivam/3x_merged

master merge into 3.x
diff --git a/bom/pom.xml b/bom/pom.xml
index 78dbebd..49dd766 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -239,6 +239,11 @@
                 <version>${project.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.glassfish.jersey.ext.cdi</groupId>
+                <artifactId>jersey-cdi-rs-inject</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.glassfish.jersey.ext.rx</groupId>
                 <artifactId>jersey-rx-client-guava</artifactId>
                 <version>${project.version}</version>
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
index 3ee79d7..17e55a9 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -29,12 +29,20 @@
     /**
      * <p>
      *    This property determines the maximum number of idle connections that will be simultaneously kept alive
-     *    in total, rather than per destination. The default is 60.
+     *    in total, rather than per destination. The default is 60. Specify 0 to disable.
      * </p>
      */
     public static final String MAX_CONNECTIONS_TOTAL = "jersey.config.client.maxTotalConnections";
 
     /**
+     * <p>
+     *    This property determines the number of seconds the idle connections are kept in the pool before pruned.
+     *    The default is 60. Specify 0 to disable.
+     *  </p>
+     */
+    public static final String IDLE_CONNECTION_PRUNE_TIMEOUT = "jersey.config.client.idleConnectionPruneTimeout";
+
+    /**
      *  <p>
      *    This property determines the maximum number of idle connections that will be simultaneously kept alive, per destination.
      *    The default is 5.
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
index c0d6cba..581f8af 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -94,9 +94,12 @@
     // http.maxConnections (default: 5)
     private static final int DEFAULT_MAX_POOL_SIZE = 5;
     private static final int MAX_POOL_SIZE = Integer.getInteger("http.maxConnections", DEFAULT_MAX_POOL_SIZE);
-    private static final int MAX_POOL_IDLE = 60;
+    private static final int DEFAULT_MAX_POOL_IDLE = 60; // seconds
+    private static final int DEFAULT_MAX_POOL_SIZE_TOTAL = 60; // connections
+
 
     private final Integer maxPoolSize; // either from system property, or from Jersey config, or default
+    private final Integer maxPoolSizeTotal; //either from Jersey config, or default
     private final Integer maxPoolIdle; // either from Jersey config, or default
 
     private static final String INACTIVE_POOLED_CONNECTION_HANDLER = "inactive_pooled_connection_handler";
@@ -119,20 +122,22 @@
 
         this.client = client;
 
-        final Object maxPoolIdleProperty = properties.get(NettyClientProperties.MAX_CONNECTIONS_TOTAL);
+        final Object maxPoolSizeTotalProperty = properties.get(NettyClientProperties.MAX_CONNECTIONS_TOTAL);
+        final Object maxPoolIdleProperty = properties.get(NettyClientProperties.IDLE_CONNECTION_PRUNE_TIMEOUT);
         final Object maxPoolSizeProperty = properties.get(NettyClientProperties.MAX_CONNECTIONS);
 
-        maxPoolIdle = maxPoolIdleProperty != null ? (Integer) maxPoolIdleProperty : MAX_POOL_IDLE;
+        maxPoolSizeTotal = maxPoolSizeTotalProperty != null ? (Integer) maxPoolSizeTotalProperty : DEFAULT_MAX_POOL_SIZE_TOTAL;
+        maxPoolIdle = maxPoolIdleProperty != null ? (Integer) maxPoolIdleProperty : DEFAULT_MAX_POOL_IDLE;
         maxPoolSize = maxPoolSizeProperty != null
                 ? (Integer) maxPoolSizeProperty
                 : (HTTP_KEEPALIVE ? MAX_POOL_SIZE : DEFAULT_MAX_POOL_SIZE);
 
-        if (maxPoolIdle == null || maxPoolIdle < 0) {
-            throw new ProcessingException(LocalizationMessages.WRONG_MAX_POOL_IDLE(maxPoolIdle));
+        if (maxPoolSizeTotal < 0) {
+            throw new ProcessingException(LocalizationMessages.WRONG_MAX_POOL_TOTAL(maxPoolSizeTotal));
         }
 
-        if (maxPoolSize == null || maxPoolSize < 0) {
-            throw new ProcessingException(LocalizationMessages.WRONG_MAX_POOL_SIZE(maxPoolIdle));
+        if (maxPoolSize < 0) {
+            throw new ProcessingException(LocalizationMessages.WRONG_MAX_POOL_SIZE(maxPoolSize));
         }
     }
 
@@ -270,7 +275,7 @@
                         connections.put(key, conns1);
                      } else {
                         synchronized (conns1) {
-                           if (conns1.size() < maxPoolSize) {
+                           if ((maxPoolSizeTotal == 0 || connections.size() < maxPoolSizeTotal) && conns1.size() < maxPoolSize) {
                               conns1.add(ch);
                            } else { // else do not add the Channel to the idle pool
                               added = false;
diff --git a/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties b/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties
index 8f9bf8f..bf12db6 100644
--- a/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties
+++ b/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
 #
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,5 +17,6 @@
 wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI.
 wrong.read.timeout=Unexpected ("{0}") READ_TIMEOUT.
 wrong.max.pool.size=Unexpected ("{0}") maximum number of connections per destination.
-wrong.max.pool.idle=Unexpected ("{0}") maximum number of connections total.
+wrong.max.pool.total=Unexpected ("{0}") maximum number of connections total.
+wrong.max.pool.idle=Unexpected ("{0}") maximum number of idle seconds.
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java
new file mode 100644
index 0000000..03912ad
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/EnumMessageProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.message.internal;
+
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+/**
+ * Default provider for enum types.
+ * @since 2.34
+ */
+@Singleton
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+final class EnumMessageProvider extends AbstractMessageReaderWriterProvider<Enum> {
+
+    @Override
+    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+        return type.isEnum();
+    }
+
+    @Override
+    public Enum readFrom(
+            Class<Enum> type,
+            Type genericType,
+            Annotation[] annotations,
+            MediaType mediaType,
+            MultivaluedMap<String, String> httpHeaders,
+            InputStream entityStream) throws IOException, WebApplicationException {
+        final String value = readFromAsString(entityStream, mediaType);
+        return Enum.valueOf(type, value);
+    }
+
+    @Override
+    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+        return type.isEnum();
+    }
+
+    @Override
+    public void writeTo(
+            Enum anEnum, Class<?> type,
+            Type genericType,
+            Annotation[] annotations,
+            MediaType mediaType,
+            MultivaluedMap<String, Object> httpHeaders,
+            OutputStream entityStream) throws IOException, WebApplicationException {
+        writeToAsString(anEnum.name(), entityStream, mediaType);
+    }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
index 9e7f39c..e6ce303 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
@@ -89,6 +89,7 @@
             bindSingletonWorker(ReaderProvider.class);
             // bindSingletonWorker(RenderedImageProvider.class); - enabledProvidersBinder
             bindSingletonWorker(StringMessageProvider.class);
+            bindSingletonWorker(EnumMessageProvider.class);
 
             // Message body readers -- enabledProvidersBinder
             // bind(SourceProvider.StreamSourceReader.class).to(MessageBodyReader.class).in(Singleton.class);
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringEventListener.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringEventListener.java
index da267cc..bcff62e 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringEventListener.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,14 +20,14 @@
 import java.util.List;
 import java.util.Queue;
 import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
-import jakarta.ws.rs.ProcessingException;
-
 import jakarta.annotation.Priority;
 import jakarta.inject.Inject;
+import jakarta.ws.rs.ProcessingException;
 
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.server.internal.LocalizationMessages;
@@ -68,6 +68,8 @@
     private final Queue<Integer> responseStatuses = new ArrayBlockingQueue<>(EVENT_QUEUE_SIZE);
     private final Queue<RequestEvent> exceptionMapperEvents = new ArrayBlockingQueue<>(EVENT_QUEUE_SIZE);
     private volatile MonitoringStatisticsProcessor monitoringStatisticsProcessor;
+    // By default new events can arrive before MonitoringStatisticsProcessor is running.
+    private final AtomicBoolean processorFailed = new AtomicBoolean(false);
 
     /**
      * Time statistics.
@@ -185,6 +187,7 @@
             case RELOAD_FINISHED:
             case INITIALIZATION_FINISHED:
                 this.monitoringStatisticsProcessor = new MonitoringStatisticsProcessor(injectionManager, this);
+                processorFailed.set(false);
                 this.monitoringStatisticsProcessor.startMonitoringWorker();
                 break;
             case DESTROY_FINISHED:
@@ -238,13 +241,13 @@
                     methodStats = new MethodStats(method, methodTimeStart, now - methodTimeStart);
                     break;
                 case EXCEPTION_MAPPING_FINISHED:
-                    if (!exceptionMapperEvents.offer(event)) {
+                    if (!offer(exceptionMapperEvents, event)) {
                         LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_MAPPER());
                     }
                     break;
                 case FINISHED:
                     if (event.isResponseWritten()) {
-                        if (!responseStatuses.offer(event.getContainerResponse().getStatus())) {
+                        if (!offer(responseStatuses, event.getContainerResponse().getStatus())) {
                             LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_RESPONSE());
                         }
                     }
@@ -264,8 +267,7 @@
                         }
                         sb.setLength(sb.length() - 1);
                     }
-
-                    if (!requestQueuedItems.offer(new RequestStats(new TimeStats(requestTimeStart, now - requestTimeStart),
+                    if (!offer(requestQueuedItems, new RequestStats(new TimeStats(requestTimeStart, now - requestTimeStart),
                             methodStats, sb.toString()))) {
                         LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_REQUEST());
                     }
@@ -274,6 +276,21 @@
         }
     }
 
+    private <T> boolean offer(Queue<T> queue, T event) {
+        if (!processorFailed.get()) {
+            return queue.offer(event);
+        }
+        // Don't need to warn that the event was not queued because an Exception was thrown by MonitoringStatisticsProcessor
+        return true;
+    }
+
+    /**
+     * Invoked by {@link MonitoringStatisticsProcessor} when there is one exception consuming from queues.
+     */
+    void processorFailed() {
+        processorFailed.set(true);
+    }
+
     /**
      * Get the exception mapper event queue.
      *
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringStatisticsProcessor.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringStatisticsProcessor.java
index b66eae3..8ee3414 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringStatisticsProcessor.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/MonitoringStatisticsProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,6 +35,7 @@
 import org.glassfish.jersey.server.ExtendedResourceContext;
 import org.glassfish.jersey.server.ServerProperties;
 import org.glassfish.jersey.server.internal.LocalizationMessages;
+import org.glassfish.jersey.server.internal.monitoring.MonitoringEventListener.RequestStats;
 import org.glassfish.jersey.server.model.ResourceMethod;
 import org.glassfish.jersey.server.model.ResourceModel;
 import org.glassfish.jersey.server.monitoring.MonitoringStatisticsListener;
@@ -94,6 +95,7 @@
                     processResponseCodeEvents();
                     processExceptionMapperEvents();
                 } catch (final Throwable t) {
+                    monitoringEventListener.processorFailed();
                     LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_MONITORING_STATISTICS_GENERATION(), t);
                     // rethrowing exception stops further task execution
                     throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_STATISTICS_GENERATION(), t);
@@ -120,11 +122,9 @@
     private void processExceptionMapperEvents() {
         final Queue<RequestEvent> eventQueue = monitoringEventListener.getExceptionMapperEvents();
         final FloodingLogger floodingLogger = new FloodingLogger(eventQueue);
-
-        while (!eventQueue.isEmpty()) {
+        RequestEvent event = null;
+        while ((event = eventQueue.poll()) != null) {
             floodingLogger.conditionallyLogFlooding();
-
-            final RequestEvent event = eventQueue.remove();
             final ExceptionMapperStatisticsImpl.Builder mapperStats = statisticsBuilder.getExceptionMapperStatisticsBuilder();
 
             if (event.getExceptionMapper() != null) {
@@ -138,12 +138,9 @@
     private void processRequestItems() {
         final Queue<MonitoringEventListener.RequestStats> requestQueuedItems = monitoringEventListener.getRequestQueuedItems();
         final FloodingLogger floodingLogger = new FloodingLogger(requestQueuedItems);
-
-        while (!requestQueuedItems.isEmpty()) {
+        RequestStats event = null;
+        while ((event = requestQueuedItems.poll()) != null) {
             floodingLogger.conditionallyLogFlooding();
-
-            final MonitoringEventListener.RequestStats event = requestQueuedItems.remove();
-
             final MonitoringEventListener.TimeStats requestStats = event.getRequestStats();
             statisticsBuilder.addRequestExecution(requestStats.getStartTime(), requestStats.getDuration());
 
@@ -160,11 +157,9 @@
     private void processResponseCodeEvents() {
         final Queue<Integer> responseEvents = monitoringEventListener.getResponseStatuses();
         final FloodingLogger floodingLogger = new FloodingLogger(responseEvents);
-
-        while (!responseEvents.isEmpty()) {
+        Integer code = null;
+        while ((code = responseEvents.poll()) != null) {
             floodingLogger.conditionallyLogFlooding();
-
-            final Integer code = responseEvents.remove();
             statisticsBuilder.addResponseCode(code);
         }
 
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
index 90877e3..9194c47 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -30,6 +30,7 @@
 
 import org.glassfish.jersey.internal.BootstrapBag;
 import org.glassfish.jersey.internal.BootstrapConfigurator;
+import org.glassfish.jersey.internal.PropertiesDelegate;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.process.internal.RequestScoped;
@@ -132,7 +133,7 @@
 
             // Bind proxiable HttpHeaders, Request and ContainerRequestContext injection injection points
             bindFactory(ContainerRequestFactory.class)
-                    .to(HttpHeaders.class).to(Request.class)
+                    .to(HttpHeaders.class).to(Request.class).to(PropertiesDelegate.class)
                     .proxy(true).proxyForSameScope(false)
                     .in(RequestScoped.class);
 
diff --git a/ext/cdi/jersey-cdi-rs-inject/pom.xml b/ext/cdi/jersey-cdi-rs-inject/pom.xml
new file mode 100644
index 0000000..7990855
--- /dev/null
+++ b/ext/cdi/jersey-cdi-rs-inject/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+    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
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.ext.cdi</groupId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-cdi-rs-inject</artifactId>
+    <name>jersey-ext-cdi-rs-inject</name>
+    <description>Allow to annotate by Inject instead of Context</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-cdi1x</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.enterprise</groupId>
+            <artifactId>jakarta.enterprise.cdi-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <show>package</show>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/ext/cdi/jersey-cdi-rs-inject/src/main/java/org/glassfish/jersey/ext/cdi1x/inject/internal/InjectExtension.java b/ext/cdi/jersey-cdi-rs-inject/src/main/java/org/glassfish/jersey/ext/cdi1x/inject/internal/InjectExtension.java
new file mode 100644
index 0000000..ad76ddb
--- /dev/null
+++ b/ext/cdi/jersey-cdi-rs-inject/src/main/java/org/glassfish/jersey/ext/cdi1x/inject/internal/InjectExtension.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.ext.cdi1x.inject.internal;
+
+import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+
+import jakarta.enterprise.event.Observes;
+import jakarta.enterprise.inject.Alternative;
+import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.enterprise.inject.spi.BeforeBeanDiscovery;
+import jakarta.enterprise.inject.spi.Extension;
+import jakarta.enterprise.inject.spi.ProcessAnnotatedType;
+import jakarta.ws.rs.container.ContainerRequestContext;
+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.ParamConverterProvider;
+import jakarta.ws.rs.ext.Providers;
+import jakarta.ws.rs.sse.Sse;
+import java.security.AccessController;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>
+ * A utility class that makes sure {@code @Inject} can be used instead of {@code @Context} for the Jakarta REST API classes
+ * and interfaces, such as for {@code Configuration}, or {@code Providers}.
+ * </p>
+ * <p>
+ * Note that {@code ContextResolver} can be injected using {@code @Context}, but the Jakarta REST specification does not require
+ * the implementation to be capable of doing so. Since {@code ContextResolver} is parametrized type, the injection using CDI's
+ * {@Inject} is not supported. The {@code ContextResolver} can be obtained from {@code Providers}.
+ * </p>
+ */
+@SuppressWarnings("unused")
+class InjectExtension implements Extension {
+    private void processAnnotatedType(@Observes ProcessAnnotatedType<?> processAnnotatedType, BeanManager beanManager) {
+        final Class<?> baseClass = (Class<?>) processAnnotatedType.getAnnotatedType().getBaseType();
+        if (Application.class.isAssignableFrom(baseClass) && Configuration.class.isAssignableFrom(baseClass)) {
+            if (!baseClass.isAnnotationPresent(Alternative.class)) {
+                processAnnotatedType.veto(); // Filter bean annotated ResourceConfig
+            }
+        }
+    }
+
+    private void beforeDiscoveryObserver(@Observes final BeforeBeanDiscovery bbf, final BeanManager beanManager) {
+        final CdiComponentProvider cdiComponentProvider = beanManager.getExtension(CdiComponentProvider.class);
+        cdiComponentProvider.addHK2DepenendencyCheck(InjectExtension::isHK2Dependency);
+    }
+
+    private static final boolean isHK2Dependency(Class<?> clazz) {
+        return JERSEY_BOUND_INJECTABLES.get().contains(clazz);
+    }
+
+    private static final LazyValue<Set<Class<?>>> JERSEY_BOUND_INJECTABLES
+            = Values.lazy((Value<Set<Class<?>>>) () -> sumNonJerseyBoundInjectables());
+
+    private static Set<Class<?>> sumNonJerseyBoundInjectables() {
+        final Set<Class<?>> injectables = new HashSet<>();
+
+        //JAX-RS
+        injectables.add(Application.class);
+        injectables.add(Configuration.class);
+        injectables.add(ContainerRequestContext.class);
+        injectables.add(HttpHeaders.class);
+        injectables.add(ParamConverterProvider.class);
+        injectables.add(Providers.class);
+        injectables.add(Request.class);
+        injectables.add(ResourceContext.class);
+        injectables.add(ResourceInfo.class);
+        injectables.add(SecurityContext.class);
+        injectables.add(Sse.class);
+        injectables.add(UriInfo.class);
+
+        //Servlet if available
+        addOptionally("jakarta.servlet.http.HttpServletRequest", injectables);
+        addOptionally("jakarta.servlet.http.HttpServletResponse", injectables);
+        addOptionally("jakarta.servlet.ServletConfig", injectables);
+        addOptionally("jakarta.servlet.ServletContext", injectables);
+        addOptionally("jakarta.servlet.FilterConfig", injectables);
+
+        return injectables;
+    }
+
+    private static void addOptionally(String className, Set<Class<?>> set) {
+        final Class<?> optionalClass = AccessController.doPrivileged(ReflectionHelper.classForNamePA(className));
+        if (optionalClass != null) {
+            set.add(optionalClass);
+        }
+    }
+}
diff --git a/ext/cdi/jersey-cdi-rs-inject/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension b/ext/cdi/jersey-cdi-rs-inject/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..4613a21
--- /dev/null
+++ b/ext/cdi/jersey-cdi-rs-inject/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.glassfish.jersey.ext.cdi1x.inject.internal.InjectExtension
\ No newline at end of file
diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
index cbf74d5..28403be 100644
--- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
+++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,11 +19,14 @@
 import java.lang.annotation.Annotation;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Set;
 
+import jakarta.enterprise.context.spi.Contextual;
 import jakarta.enterprise.context.spi.CreationalContext;
 import jakarta.enterprise.inject.spi.AnnotatedType;
 import jakarta.enterprise.inject.spi.Bean;
 import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.enterprise.inject.spi.InjectionPoint;
 import jakarta.enterprise.inject.spi.InjectionTarget;
 import jakarta.enterprise.inject.spi.InjectionTargetFactory;
 
@@ -83,11 +86,17 @@
             public T getInstance(final Class<T> clazz) {
                 final CreationalContext<T> creationalContext = beanManager.createCreationalContext(null);
                 final T instance = injectionTarget.produce(creationalContext);
-                injectionTarget.inject(instance, creationalContext);
-                if (injectionManager != null) {
-                    injectionManager.inject(instance, CdiComponentProvider.CDI_CLASS_ANALYZER);
-                }
-                injectionTarget.postConstruct(instance);
+                final CdiComponentProvider cdiComponentProvider = beanManager.getExtension(CdiComponentProvider.class);
+                final CdiComponentProvider.InjectionManagerInjectedCdiTarget hk2managedTarget =
+                     cdiComponentProvider.new InjectionManagerInjectedCdiTarget(injectionTarget) {
+                        @Override
+                        public Set<InjectionPoint> getInjectionPoints() {
+                            return injectionTarget.getInjectionPoints();
+                        }
+                    };
+                hk2managedTarget.setInjectionManager(injectionManager);
+                hk2managedTarget.inject(instance, creationalContext);
+                hk2managedTarget.postConstruct(instance);
                 return instance;
             }
 
diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
index 46f5893..4128501 100644
--- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
+++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
@@ -31,10 +31,12 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -125,6 +127,8 @@
     private final Set<Type> jaxrsInjectableTypes = new HashSet<>();
     private final Set<Type> hk2ProvidedTypes = Collections.synchronizedSet(new HashSet<Type>());
     private final Set<Type> jerseyVetoedTypes = Collections.synchronizedSet(new HashSet<Type>());
+    private final Set<DependencyPredicate> jerseyOrDependencyTypes = Collections.synchronizedSet(new LinkedHashSet<>());
+    private final ThreadLocal<InjectionManager> threadInjectionManagers = new ThreadLocal<>();
 
     /**
      * set of request scoped components
@@ -153,6 +157,7 @@
     public CdiComponentProvider() {
         customHk2TypesProvider = CdiUtil.lookupService(Hk2CustomBoundTypesProvider.class);
         injectionManagerStore = CdiUtil.createHk2InjectionManagerStore();
+        addHK2DepenendencyCheck(CdiComponentProvider::isJerseyOrDependencyType);
     }
 
     @Override
@@ -550,7 +555,7 @@
             } else {
                 if (injectedType instanceof Class<?>) {
                     final Class<?> injectedClass = (Class<?>) injectedType;
-                    if (isJerseyOrDependencyType(injectedClass)) {
+                    if (testDependencyType(injectedClass)) {
                         //remember the type, we would need to mock it's CDI binding at runtime
                         hk2ProvidedTypes.add(injectedType);
                     } else {
@@ -699,6 +704,15 @@
                 && !pkgName.startsWith("com.sun.jersey.tests")));
     }
 
+    private boolean testDependencyType(Class<?> clazz) {
+        for (Predicate<Class<?>> predicate : jerseyOrDependencyTypes) {
+            if (predicate.test(clazz)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void bindHk2ClassAnalyzer() {
         ClassAnalyzer defaultClassAnalyzer =
                 injectionManager.getInstance(ClassAnalyzer.class, ClassAnalyzer.DEFAULT_IMPLEMENTATION_NAME);
@@ -729,7 +743,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    private abstract class InjectionManagerInjectedCdiTarget implements InjectionManagerInjectedTarget {
+    /* package */ abstract class InjectionManagerInjectedCdiTarget implements InjectionManagerInjectedTarget {
 
         private final InjectionTarget delegate;
         private volatile InjectionManager effectiveInjectionManager;
@@ -743,16 +757,19 @@
 
         @Override
         public void inject(final Object t, final CreationalContext cc) {
-            delegate.inject(t, cc);
-
             InjectionManager injectingManager = getEffectiveInjectionManager();
             if (injectingManager == null) {
                 injectingManager = effectiveInjectionManager;
+                threadInjectionManagers.set(injectingManager);
             }
 
+            delegate.inject(t, cc); // here the injection manager is used in HK2Bean
+
             if (injectingManager != null) {
                 injectingManager.inject(t, CdiComponentProvider.CDI_CLASS_ANALYZER);
             }
+
+            threadInjectionManagers.remove();
         }
 
         @Override
@@ -806,7 +823,12 @@
 
         @Override
         public Object create(final CreationalContext creationalContext) {
-            return getEffectiveInjectionManager().getInstance(t);
+            InjectionManager injectionManager = getEffectiveInjectionManager();
+            if (injectionManager == null) {
+                injectionManager = threadInjectionManagers.get();
+            }
+
+            return injectionManager.getInstance(t);
         }
 
         @Override
@@ -925,5 +947,39 @@
                 "Jersey " + ProcessJAXRSAnnotatedTypes.class.getName()
         );
     }
+
+    /**
+     * Add a predicate to test HK2 dependency to create a CDI bridge bean to HK2 for it.
+     * @param predicate to test whether given class is a HK2 dependency.
+     */
+    public void addHK2DepenendencyCheck(Predicate<Class<?>> predicate) {
+        jerseyOrDependencyTypes.add(new DependencyPredicate(predicate));
+    }
+
+    private final class DependencyPredicate implements Predicate<Class<?>> {
+        private final Predicate<Class<?>> predicate;
+
+        public DependencyPredicate(Predicate<Class<?>> predicate) {
+            this.predicate = predicate;
+        }
+
+        @Override
+        public boolean test(Class<?> aClass) {
+            return predicate.test(aClass);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            DependencyPredicate that = (DependencyPredicate) o;
+            return predicate.getClass().equals(that.predicate);
+        }
+
+        @Override
+        public int hashCode() {
+            return predicate.getClass().hashCode();
+        }
+    }
 }
 
diff --git a/ext/cdi/pom.xml b/ext/cdi/pom.xml
index 0d86bfb..7dcbac2 100644
--- a/ext/cdi/pom.xml
+++ b/ext/cdi/pom.xml
@@ -36,6 +36,7 @@
     <modules>
         <module>jersey-cdi1x</module>
         <module>jersey-cdi1x-ban-custom-hk2-binding</module>
+        <module>jersey-cdi-rs-inject</module>
         <module>jersey-cdi1x-servlet</module>
         <module>jersey-cdi1x-transaction</module>
         <module>jersey-cdi1x-validation</module>
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java
new file mode 100644
index 0000000..abc66cd
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EnumEntityTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.e2e.entity;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.util.runner.ConcurrentRunner;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+@RunWith(ConcurrentRunner.class)
+public class EnumEntityTest extends JerseyTest {
+
+    public enum SimpleEnum {
+        VALUE1,
+        VALUE2
+    }
+
+    public enum ValueEnum {
+        VALUE100(100),
+        VALUE200(200);
+
+        private final int value;
+
+        ValueEnum(int value) {
+            this.value = value;
+        }
+    }
+
+    @Path("/")
+    public static class EnumResource {
+        @POST
+        @Path("/simple")
+        public String postSimple(SimpleEnum simpleEnum) {
+            return simpleEnum.name();
+        }
+
+        @POST
+        @Path("/value")
+        public String postValue(ValueEnum valueEnum) {
+            return valueEnum.name();
+        }
+
+        @POST
+        @Path("/echo")
+        public String echo(String value) {
+            return value;
+        }
+
+        @PUT
+        @Path("/simple")
+        public SimpleEnum putSimple(String simple) {
+            return SimpleEnum.valueOf(simple);
+        }
+
+        @PUT
+        @Path("value")
+        public ValueEnum putValue(String value) {
+            return ValueEnum.valueOf(value);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(EnumResource.class);
+    }
+
+    // Server side tests
+
+    @Test
+    public void testSimpleEnumServerReader() {
+        for (SimpleEnum value : SimpleEnum.values()) {
+            try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+    @Test
+    public void testValueEnumServerReader() {
+        for (ValueEnum value : ValueEnum.values()) {
+            try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+    @Test
+    public void testSimpleEnumServerWriter() {
+        for (SimpleEnum value : SimpleEnum.values()) {
+            try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE)
+                    .put(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+    @Test
+    public void testValueEnumServerWriter() {
+        for (ValueEnum value : ValueEnum.values()) {
+            try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE)
+                    .put(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+    // Client side tests
+
+    @Test
+    public void testSimpleEnumClientReader() {
+        for (SimpleEnum value : SimpleEnum.values()) {
+            try (Response r = target("simple").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value, r.readEntity(SimpleEnum.class));
+            }
+        }
+    }
+
+    @Test
+    public void testValueEnumClientReader() {
+        for (ValueEnum value : ValueEnum.values()) {
+            try (Response r = target("value").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value.name(), MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value, r.readEntity(ValueEnum.class));
+            }
+        }
+    }
+
+    @Test
+    public void testSimpleEnumClientWriter() {
+        for (SimpleEnum value : SimpleEnum.values()) {
+            try (Response r = target("echo").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value, MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+    @Test
+    public void testValueEnumClientWriter() {
+        for (ValueEnum value : ValueEnum.values()) {
+            try (Response r = target("echo").request(MediaType.TEXT_PLAIN_TYPE)
+                    .post(Entity.entity(value, MediaType.TEXT_PLAIN_TYPE))) {
+                Assert.assertEquals(value.name(), r.readEntity(String.class));
+            }
+        }
+    }
+
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/pom.xml b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
new file mode 100644
index 0000000..a5775da
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+    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
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
+        <artifactId>cdi-integration-project</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-inject-on-server</artifactId>
+    <name>jersey-tests-context-inject-on-server</name>
+
+    <description>CDI works on a client on a server resource</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.enterprise</groupId>
+            <artifactId>jakarta.enterprise.cdi-api</artifactId>
+            <version>${cdi.api.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <version>${servlet5.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-weld2-se</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <!-- latest 3.x -->
+            <version>${weld.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-cdi1x</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-cdi-rs-inject</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-sse</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-servlet-core</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java
new file mode 100644
index 0000000..25e2038
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ApplicationInjectParent.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.servlet.WebConfig;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.inject.Inject;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+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.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+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.ParamConverterProvider;
+import jakarta.ws.rs.ext.Providers;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class ApplicationInjectParent extends Application {
+    @Context
+    protected HttpHeaders contextHttpHeaders;
+
+    @Inject
+    protected HttpHeaders injectHttpHeaders;
+
+    @Context
+    ParamConverterProvider contextParamConverterProvider;
+
+    @Inject
+    ParamConverterProvider injectParamConverterProvider;
+
+    @Context
+    protected Providers contextProviders;
+
+    @Inject
+    protected Providers injectProviders;
+
+    @Context
+    protected ResourceContext contextResourceContext;
+
+    @Inject
+    protected ResourceContext injectResourceContext;
+
+    @Context
+    protected Request contextRequest;
+
+    @Inject
+    protected Request injectRequest;
+
+    @Context
+    protected ResourceInfo contextResourceInfo;
+
+    @Inject
+    protected ResourceInfo injectResourceInfo;
+
+    @Context
+    protected SecurityContext contextSecurityContext;
+
+    @Inject
+    protected SecurityContext injectSecurityContext;
+
+    @Context
+    protected UriInfo contextUriInfo;
+
+    @Inject
+    protected UriInfo injectUriInfo;
+
+    @Context
+    protected HttpServletRequest contextHttpServletRequest;
+
+    @Inject
+    protected HttpServletRequest injectHttpServletRequest;
+
+    @Context
+    protected WebConfig contextWebConfig;
+
+    @Inject
+    protected WebConfig injectWebConfig;
+
+    @Context
+    protected HttpServletResponse contextHttpServletResponse;
+
+    @Inject
+    protected HttpServletResponse injectHttpServletResponse;
+
+    @Context
+    protected ServletConfig contextServletConfig;
+
+    @Inject
+    protected ServletConfig injectServletConfig;
+
+    @Context
+    protected ServletContext contextServletContext;
+
+    @Inject
+    protected ServletContext injectServletContext;
+
+    static class InjectHolder extends ParentInject {
+
+        @Override
+        protected boolean checkApplication(Application application, StringBuilder stringBuilder) {
+            return true;
+        }
+
+        @Override
+        protected boolean checkConfiguration(Configuration configuration, StringBuilder stringBuilder) {
+            return true;
+        }
+
+        @Override
+        protected boolean checkPropertiesDelegate(PropertiesDelegate propertiesDelegate, StringBuilder stringBuilder) {
+            return true;
+        }
+    };
+
+    private InjectHolder injectHolder = new InjectHolder();
+
+    @PostConstruct
+    void postConstruct() {
+        try {
+            setInjectHolder("context");
+            setInjectHolder("inject");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void setInjectHolder(String prefix) throws NoSuchFieldException, IllegalAccessException {
+        for (Field field : ApplicationInjectParent.class.getDeclaredFields()) {
+            if (field.getType() != InjectHolder.class && field.getName().startsWith(prefix)) {
+                Field holders = InjectHolder.class.getSuperclass().getDeclaredField(field.getName());
+                holders.setAccessible(true);
+                holders.set(injectHolder, field.get(this));
+            }
+        }
+    }
+
+    @Override
+    public Set<Object> getSingletons() {
+        final Set<Object> set = new LinkedHashSet<>();
+        set.add(injectHolder);
+        return set;
+    }
+
+    public static class ResourceParent {
+        @Context
+        Application contextApplication;
+
+        @Inject
+        Application injectApplication;
+
+        @Context
+        PropertiesDelegate propertiesDelegate;
+
+        @GET
+        @Path("context")
+        public Response checkAppContexted() {
+            return checkApp(true);
+        }
+
+        @GET
+        @Path("inject")
+        public Response checkAppInjected() {
+            return checkApp(false);
+        }
+
+        private Response checkApp(boolean contexted) {
+            StringBuilder sb = new StringBuilder();
+            Iterator<Object> singletons = contextApplication.getSingletons().iterator();
+            final InjectHolder injectHolder = (InjectHolder) singletons.next();
+            final boolean injected = contexted ? injectHolder.checkContexted(sb) : injectHolder.checkInjected(sb);
+            if (injected) {
+                return Response.ok().entity("All injected").build();
+            } else {
+                propertiesDelegate.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+                return Response.status(Response.Status.EXPECTATION_FAILED).entity(sb.toString()).build();
+            }
+        }
+    }
+
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/InjectionChecker.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/InjectionChecker.java
new file mode 100644
index 0000000..2d18f7c
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/InjectionChecker.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.servlet.ServletContainer;
+import org.glassfish.jersey.servlet.WebConfig;
+
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.container.ContainerRequestContext;
+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.MessageBodyWriter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Providers;
+import java.lang.annotation.Annotation;
+import java.util.Iterator;
+
+class InjectionChecker {
+    static final String APPLICATION_PROPERTY = "ApplicationProperty";
+    static final String HEADER = "HttpHeader";
+    static final String ROOT = "resource";
+
+    static boolean checkApplication(Application application, StringBuilder sb) {
+        if (application == null) {
+            sb.append("Application is null.");
+            return false;
+        }
+        if (!application.getProperties().containsKey(APPLICATION_PROPERTY)) {
+            sb.append("Application does not contain expected key.");
+            return false;
+        }
+        if (!APPLICATION_PROPERTY.equals(application.getProperties().get(APPLICATION_PROPERTY))) {
+            sb.append("Application does not contain expected value.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkConfiguration(Configuration configuration, StringBuilder sb) {
+        if (configuration == null) {
+            sb.append("Configuration is null.");
+            return false;
+        }
+        if (!configuration.getProperties().containsKey(APPLICATION_PROPERTY)) {
+            sb.append("Configuration does not contain expected key.");
+            return false;
+        }
+        if (!APPLICATION_PROPERTY.equals(configuration.getProperties().get(APPLICATION_PROPERTY))) {
+            sb.append("Configuration does not contain expected value.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkContainerRequestContext(ContainerRequestContext containerRequestContext, StringBuilder sb) {
+        if (containerRequestContext == null) {
+            sb.append("ContainerRequestContext is null.");
+            return false;
+        }
+
+        return checkRequest(containerRequestContext.getRequest(), sb) && checkUriInfo(containerRequestContext.getUriInfo(), sb);
+    }
+
+    static boolean checkHttpHeaders(HttpHeaders headers, StringBuilder sb) {
+        if (headers == null) {
+            sb.append("HttpHeaders is null.");
+            return false;
+        }
+        if (headers.getHeaderString(HEADER) == null) {
+            sb.append("HttpHeaders does not contain expected header.");
+            return false;
+        }
+        if (!HEADER.equals(headers.getHeaderString(HEADER))) {
+            sb.append("HttpHeaders does not contain expected header value.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkParamConverterProvider(ParamConverterProvider provider, StringBuilder sb) {
+        if (provider == null) {
+            sb.append("ParamConverterProvider is null.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkPropertiesDelegate(PropertiesDelegate propertiesDelegate, StringBuilder sb) {
+        if (propertiesDelegate == null) {
+            sb.append("PropertiesDelegate is null.");
+            return false;
+        }
+        if (null == propertiesDelegate.getProperty(APPLICATION_PROPERTY)) {
+            sb.append("PropertiesDelegate does not contain expected key.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkProviders(Providers providers, StringBuilder sb) {
+        if (providers == null) {
+            sb.append("Providers is null.");
+            return false;
+        }
+        MessageBodyWriter<String> mbw =
+                providers.getMessageBodyWriter(String.class, String.class, new Annotation[]{}, MediaType.TEXT_PLAIN_TYPE);
+        if (mbw == null) {
+            sb.append("String MessageBodyWriter is null.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkRequest(Request request, StringBuilder sb) {
+        if (request == null) {
+            sb.append("Request is null.");
+            return false;
+        }
+        final String method = request.getMethod();
+        if (method == null) {
+            sb.append("Request did not get a method.");
+            return false;
+        }
+        if (!HttpMethod.GET.equals(method)) {
+            sb.append("Request did not correct method, but ").append(method).append(" .");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkResourceContext(ResourceContext context, StringBuilder sb) {
+        if (context == null) {
+            sb.append("ResourceContext is null.");
+            return false;
+        }
+        ScopedResource resource = context.getResource(ScopedResource.class);
+        if (resource == null) {
+            sb.append("ResourceContext did not get the resource.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkResourceInfo(ResourceInfo info, StringBuilder sb) {
+        if (info == null) {
+            sb.append("ResourceInfo is null.");
+            return false;
+        }
+        final Class<?> resourceClass = info.getResourceClass();
+        if (resourceClass == null) {
+            sb.append("ResourceInfo did not get the resource.");
+            return false;
+        }
+        if (!resourceClass.getSimpleName().endsWith("ScopedResource")) {
+            sb.append("ResourceInfo did not get the proper resource.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkSecurityContext(SecurityContext context, StringBuilder sb) {
+        if (context == null) {
+            sb.append("SecurityContext is null.");
+            return false;
+        }
+        if (context.isSecure()) {
+            sb.append("SecurityContext returned unexpected security.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkUriInfo(UriInfo info, StringBuilder sb) {
+        if (info == null) {
+            sb.append("UriInfo is null.");
+            return false;
+        }
+        if (!info.getPath().startsWith(ROOT)) {
+            sb.append("UriInfo does not start with expected ").append(ROOT)
+                    .append(" but it is ").append(info.getPath()).append(".");
+        }
+        return true;
+    }
+
+    static boolean checkWebConfig(WebConfig config, StringBuilder sb) {
+        if (config == null) {
+            sb.append("WebConfig is null.");
+            return false;
+        }
+        if (config.getServletContext() == null) {
+            sb.append("WebConfig#getServletContext() is null.");
+            return false;
+        }
+        if (!checkServletContext(config.getServletContext(), sb)) {
+            return false;
+        }
+        if (!checkServletConfig(config.getServletConfig(), sb)) {
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkServletContext(ServletContext context, StringBuilder sb) {
+        if (context == null) {
+            sb.append("ServletContext is null.");
+            return false;
+        }
+        if (context.getServletRegistrations() == null) {
+            sb.append("ServletContext#getServletRegistrations is null.");
+            return false;
+        }
+        Iterator<String> it = context.getServletRegistrations().keySet().iterator();
+        if (!it.hasNext()) {
+            sb.append("ServletContext#getServletRegistrations is empty.");
+            return false;
+        }
+        if (!ServletContainer.class.getName().equals(it.next())) {
+            sb.append("ServletContext#getServletRegistrations does not contain ServletContainer registration.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkServletConfig(ServletConfig config, StringBuilder sb) {
+        if (config == null) {
+            sb.append("ServletConfig is null.");
+            return false;
+        }
+        if (!ServletContainer.class.getName().equals(config.getServletName())) {
+            sb.append("ServletConfig has unexpected servlet name ").append(config.getServletName()).append(" .");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkHttpServletRequest(HttpServletRequest request, StringBuilder sb) {
+        if (request == null) {
+            sb.append("HttpServletRequest is null.");
+            return false;
+        }
+        if (request.getHeaderNames() == null) {
+            sb.append("HttpServletRequest header names is null.");
+            return false;
+        }
+        if (request.getHeader(HEADER) == null) {
+            sb.append("HttpServletRequest does not contain expected header.");
+            return false;
+        }
+        if (!HEADER.equals(request.getHeader(HEADER))) {
+            sb.append("HttpServletRequest does not contain expected header value.");
+            return false;
+        }
+        return true;
+    }
+
+    static boolean checkHttpServletResponse(HttpServletResponse response, StringBuilder sb) {
+        if (response == null) {
+            sb.append("HttpServletResponse is null.");
+            return false;
+        }
+        if (response.getStatus() != 200) {
+            sb.append("HttpServletResponse has unexpectes status.");
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplication.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplication.java
new file mode 100644
index 0000000..8fd1a04
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplication.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+public class NonScopedApplication extends ResourceConfig {
+    public NonScopedApplication() {
+        register(PropertySettingFilter.class);
+        register(NonScopedResource.class);
+        register(NonScopedContainerRequestFilter.class);
+        register(NonScopedContainerResponseFilter.class);
+        register(NonScopedExceptionMapper.class);
+        register(NonScopedWriterInterceptor.class);
+        property(InjectionChecker.APPLICATION_PROPERTY, InjectionChecker.APPLICATION_PROPERTY);
+        property(ServerProperties.WADL_FEATURE_DISABLE, true);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInject.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInject.java
new file mode 100644
index 0000000..ca97ed2
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInject.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.Path;
+import java.util.Collections;
+import java.util.Set;
+
+public class NonScopedApplicationInject extends ApplicationInjectParent {
+    @Path(InjectionChecker.ROOT + "/nonscoped")
+    public static class NonScopedResource extends ApplicationInjectParent.ResourceParent {
+
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return Collections.singleton(NonScopedResource.class);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerRequestFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerRequestFilter.java
new file mode 100644
index 0000000..efe5bb9
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerRequestFilter.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+public class NonScopedContainerRequestFilter extends ParentInject implements ParentContainerRequestFilter {
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerResponseFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerResponseFilter.java
new file mode 100644
index 0000000..1601786
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedContainerResponseFilter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+public class NonScopedContainerResponseFilter extends ParentInject implements ParentContainerResponseFilter {
+
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedExceptionMapper.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedExceptionMapper.java
new file mode 100644
index 0000000..37a8dfb
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedExceptionMapper.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+public class NonScopedExceptionMapper extends ParentExceptionMapper {
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedResource.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedResource.java
new file mode 100644
index 0000000..a387b39
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedResource.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.Path;
+
+
+@Path(InjectionChecker.ROOT + "/nonscope")
+public class NonScopedResource extends ParentResource {
+
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedWriterInterceptor.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedWriterInterceptor.java
new file mode 100644
index 0000000..b1fc6ac
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/NonScopedWriterInterceptor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import java.net.URI;
+
+public class NonScopedWriterInterceptor extends ParentInject implements ParentWriterInterceptor {
+
+    @Override
+    public URI getRequestUri() {
+        return contextUriInfo.getRequestUri();
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentChecker.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentChecker.java
new file mode 100644
index 0000000..b8314eb
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentChecker.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+public interface ParentChecker {
+    boolean checkInjected(StringBuilder stringBuilder);
+    boolean checkContexted(StringBuilder stringBuilder);
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java
new file mode 100644
index 0000000..34b7d8a
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerRequestFilter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+
+public interface ParentContainerRequestFilter extends ParentChecker, ContainerRequestFilter {
+
+    @Override
+    default void filter(ContainerRequestContext requestContext) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean injected = false;
+
+        if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("injected")) {
+            injected = checkInjected(stringBuilder);
+        }
+
+        if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("contexted")) {
+            injected = checkContexted(stringBuilder);
+        }
+
+        if (!injected) {
+            requestContext.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+            stringBuilder.insert(0, "InjectContainerRequestFilter: ");
+            requestContext.abortWith(
+                    Response.status(Response.Status.EXPECTATION_FAILED).entity(stringBuilder.toString()).build()
+            );
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java
new file mode 100644
index 0000000..8443b86
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentContainerResponseFilter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+
+public interface ParentContainerResponseFilter extends ParentChecker, ContainerResponseFilter {
+    @Override
+    default void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean injected = false;
+
+        if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("injected")) {
+            injected = checkInjected(stringBuilder);
+        }
+
+        if (requestContext.getUriInfo().getRequestUri().toASCIIString().contains("contexted")) {
+            injected = checkContexted(stringBuilder);
+        }
+
+        if (!injected) {
+            requestContext.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+            stringBuilder.insert(0, "InjectContainerResponseFilter: ");
+            responseContext.setEntity(stringBuilder.toString());
+            responseContext.setStatus(Response.Status.EXPECTATION_FAILED.getStatusCode());
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentExceptionMapper.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentExceptionMapper.java
new file mode 100644
index 0000000..e9e7f14
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentExceptionMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+
+public class ParentExceptionMapper extends RequestScopedParentInject implements ExceptionMapper<IllegalArgumentException> {
+
+    @Override
+    public Response toResponse(IllegalArgumentException exception) {
+        StringBuilder sb = new StringBuilder();
+        boolean injected = true;
+        switch (exception.getMessage()) {
+            case "inject":
+                injected = checkInjected(sb);
+                break;
+            default:
+                injected = checkContexted(sb);
+                break;
+        }
+
+        if (!injected) {
+            contextContainerRequestContext.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+            sb.insert(0, exception.getMessage() + "ExceptionMapper: ");
+            return Response.status(Response.Status.EXPECTATION_FAILED).entity(sb.toString()).build();
+        }
+        return Response.ok("All " + exception.getMessage() + "ed on ExceptionMapper.").build();
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java
new file mode 100644
index 0000000..ec39b45
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentInject.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.glassfish.jersey.servlet.WebConfig;
+
+import jakarta.inject.Inject;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+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.Context;
+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.ParamConverterProvider;
+import jakarta.ws.rs.ext.Providers;
+
+public class ParentInject implements ParentChecker {
+    @Context
+    protected Application contextApplication;
+
+    @Inject
+    protected Application injectApplication;
+
+    @Context
+    protected Configuration contextConfiguration;
+
+    @Inject
+    protected Configuration injectConfiguration;
+
+    @Context
+    protected HttpHeaders contextHttpHeaders;
+
+    @Inject
+    protected HttpHeaders injectHttpHeaders;
+
+    @Context
+    protected ParamConverterProvider contextParamConverterProvider;
+
+    @Inject
+    protected ParamConverterProvider injectParamConverterProvider;
+
+    @Context
+    protected PropertiesDelegate contextPropertiesDelegate;
+
+    @Inject
+    protected PropertiesDelegate injectPropertiesDelegate;
+
+    @Context
+    protected Providers contextProviders;
+
+    @Inject
+    protected Providers injectProviders;
+
+    @Context
+    protected ResourceContext contextResourceContext;
+
+    @Inject
+    protected ResourceContext injectResourceContext;
+
+    @Context
+    protected Request contextRequest;
+
+    @Inject
+    protected Request injectRequest;
+
+    @Context
+    protected ResourceInfo contextResourceInfo;
+
+    @Inject
+    protected ResourceInfo injectResourceInfo;
+
+    @Context
+    protected SecurityContext contextSecurityContext;
+
+    @Inject
+    protected SecurityContext injectSecurityContext;
+
+    @Context
+    protected UriInfo contextUriInfo;
+
+    @Inject
+    protected UriInfo injectUriInfo;
+
+    @Context
+    protected HttpServletRequest contextHttpServletRequest;
+
+    @Inject
+    protected HttpServletRequest injectHttpServletRequest;
+
+    @Context
+    protected WebConfig contextWebConfig;
+
+    @Inject
+    protected WebConfig injectWebConfig;
+
+    @Context
+    protected HttpServletResponse contextHttpServletResponse;
+
+    @Inject
+    protected HttpServletResponse injectHttpServletResponse;
+
+    @Context
+    protected ServletConfig contextServletConfig;
+
+    @Inject
+    protected ServletConfig injectServletConfig;
+
+    @Context
+    protected ServletContext contextServletContext;
+
+    @Inject
+    protected ServletContext injectServletContext;
+
+    @Override
+    public boolean checkInjected(StringBuilder stringBuilder) {
+        boolean injected = true;
+        injected &= checkApplication(injectApplication, stringBuilder);
+        injected &= checkConfiguration(injectConfiguration, stringBuilder);
+        injected &= InjectionChecker.checkHttpHeaders(injectHttpHeaders, stringBuilder);
+        injected &= checkPropertiesDelegate(injectPropertiesDelegate, stringBuilder);
+        injected &= InjectionChecker.checkParamConverterProvider(injectParamConverterProvider, stringBuilder);
+        injected &= InjectionChecker.checkProviders(injectProviders, stringBuilder);
+        injected &= InjectionChecker.checkRequest(injectRequest, stringBuilder);
+        injected &= InjectionChecker.checkResourceContext(injectResourceContext, stringBuilder);
+        injected &= InjectionChecker.checkResourceInfo(injectResourceInfo, stringBuilder);
+        injected &= InjectionChecker.checkSecurityContext(injectSecurityContext, stringBuilder);
+        injected &= InjectionChecker.checkUriInfo(injectUriInfo, stringBuilder);
+
+        injected &= InjectionChecker.checkHttpServletRequest(injectHttpServletRequest, stringBuilder);
+        injected &= InjectionChecker.checkHttpServletResponse(injectHttpServletResponse, stringBuilder);
+        injected &= InjectionChecker.checkWebConfig(injectWebConfig, stringBuilder);
+        injected &= InjectionChecker.checkServletConfig(injectServletConfig, stringBuilder);
+        injected &= InjectionChecker.checkServletContext(injectServletContext, stringBuilder);
+
+        return injected;
+    }
+
+    @Override
+    public boolean checkContexted(StringBuilder stringBuilder) {
+        boolean injected = true;
+        injected &= checkApplication(contextApplication, stringBuilder);
+        injected &= checkConfiguration(contextConfiguration, stringBuilder);
+        injected &= InjectionChecker.checkHttpHeaders(contextHttpHeaders, stringBuilder);
+        injected &= InjectionChecker.checkParamConverterProvider(contextParamConverterProvider, stringBuilder);
+        injected &= checkPropertiesDelegate(contextPropertiesDelegate, stringBuilder);
+        injected &= InjectionChecker.checkProviders(contextProviders, stringBuilder);
+        injected &= InjectionChecker.checkRequest(contextRequest, stringBuilder);
+        injected &= InjectionChecker.checkResourceContext(contextResourceContext, stringBuilder);
+        injected &= InjectionChecker.checkResourceInfo(contextResourceInfo, stringBuilder);
+        injected &= InjectionChecker.checkSecurityContext(contextSecurityContext, stringBuilder);
+        injected &= InjectionChecker.checkUriInfo(contextUriInfo, stringBuilder);
+
+        injected &= InjectionChecker.checkHttpServletRequest(contextHttpServletRequest, stringBuilder);
+        injected &= InjectionChecker.checkHttpServletResponse(contextHttpServletResponse, stringBuilder);
+        injected &= InjectionChecker.checkWebConfig(contextWebConfig, stringBuilder);
+        injected &= InjectionChecker.checkServletConfig(contextServletConfig, stringBuilder);
+        injected &= InjectionChecker.checkServletContext(contextServletContext, stringBuilder);
+
+        return injected;
+    }
+
+    protected boolean checkApplication(Application application, StringBuilder stringBuilder) {
+        return InjectionChecker.checkApplication(contextApplication, stringBuilder);
+    }
+
+    protected boolean checkConfiguration(Configuration configuration, StringBuilder stringBuilder) {
+        return InjectionChecker.checkConfiguration(configuration, stringBuilder);
+    }
+
+    protected boolean checkPropertiesDelegate(PropertiesDelegate propertiesDelegate, StringBuilder stringBuilder) {
+        return InjectionChecker.checkPropertiesDelegate(propertiesDelegate, stringBuilder);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentResource.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentResource.java
new file mode 100644
index 0000000..a1c5640
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentResource.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+
+public class ParentResource extends RequestScopedParentInject {
+
+    @Context
+    ContainerRequestContext requestContext;
+
+    @GET
+    @Path("injected")
+    public Response areInjected() {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean injected = checkInjected(stringBuilder);
+
+        if (injected) {
+            return Response.ok().entity("All injected").build();
+        } else {
+            requestContext.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+            return Response.status(Response.Status.EXPECTATION_FAILED).entity(stringBuilder.toString()).build();
+        }
+    }
+
+    @GET
+    @Path("contexted")
+    public Response areContexted() {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean contexted = checkContexted(stringBuilder);
+
+        if (contexted) {
+            return Response.ok().entity("All contexted").build();
+        } else {
+            requestContext.setProperty(ParentWriterInterceptor.STATUS, Response.Status.EXPECTATION_FAILED);
+            return Response.status(Response.Status.EXPECTATION_FAILED).entity(stringBuilder.toString()).build();
+        }
+    }
+
+    @GET
+    @Path("iae/{x}")
+    public Response iae(@PathParam("x") String injected) {
+        throw new IllegalArgumentException(injected);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentWriterInterceptor.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentWriterInterceptor.java
new file mode 100644
index 0000000..fbad503
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ParentWriterInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.ext.WriterInterceptor;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
+import java.io.IOException;
+import java.net.URI;
+
+public interface ParentWriterInterceptor extends ParentChecker, WriterInterceptor {
+
+    static final String STATUS = "status";
+
+    @Override
+    default void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean injected = false;
+
+        if (context.getProperty(STATUS) == null) {
+            if (getRequestUri().toASCIIString().contains("injected")) {
+                injected = checkInjected(stringBuilder);
+            }
+
+            if (getRequestUri().toASCIIString().contains("contexted")) {
+                injected = checkContexted(stringBuilder);
+            }
+
+            if (injected) {
+                context.setEntity(context.getEntity().toString().replace("All", "Everything"));
+            } else {
+                stringBuilder.insert(0, "InjectWriterInterceptor: ");
+                context.setEntity(stringBuilder.toString());
+            }
+        }
+        context.proceed();
+    }
+
+    URI getRequestUri();
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/PropertySettingFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/PropertySettingFilter.java
new file mode 100644
index 0000000..f871e23
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/PropertySettingFilter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.internal.PropertiesDelegate;
+
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.PreMatching;
+import jakarta.ws.rs.core.Context;
+import java.io.IOException;
+
+@PreMatching
+public class PropertySettingFilter implements ContainerRequestFilter {
+    @Context
+    PropertiesDelegate contextPropertiesDelegate;
+
+    @Override
+    public void filter(ContainerRequestContext requestContext) throws IOException {
+        contextPropertiesDelegate.setProperty(InjectionChecker.APPLICATION_PROPERTY, InjectionChecker.APPLICATION_PROPERTY);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/RequestScopedParentInject.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/RequestScopedParentInject.java
new file mode 100644
index 0000000..e26c36b
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/RequestScopedParentInject.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Context;
+
+public abstract class RequestScopedParentInject extends ParentInject {
+    @Context
+    ContainerRequestContext contextContainerRequestContext;
+
+    @Inject
+    ContainerRequestContext injectContainerRequestContext;
+
+    //  CDI Scoped only
+//    @Inject
+//    protected jakarta.enterprise.inject.spi.BeanManager beanManager;
+
+    @Override
+    public boolean checkContexted(StringBuilder stringBuilder) {
+        boolean contexted = super.checkContexted(stringBuilder);
+        contexted &= InjectionChecker.checkContainerRequestContext(contextContainerRequestContext, stringBuilder);
+        return contexted;
+    }
+
+    @Override
+    public boolean checkInjected(StringBuilder stringBuilder) {
+        boolean injected = super.checkInjected(stringBuilder);
+        injected &= InjectionChecker.checkContainerRequestContext(injectContainerRequestContext, stringBuilder);
+        return injected;
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplication.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplication.java
new file mode 100644
index 0000000..3b83f09
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplication.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ScopedApplication extends ResourceConfig {
+    public ScopedApplication() {
+        register(PropertySettingFilter.class);
+        register(ScopedResource.class);
+        register(ScopedContainerRequestFilter.class);
+        register(ScopedContainerResponseFilter.class);
+        register(ScopedExceptionMapper.class);
+        register(ScopedWriterInterceptor.class);
+        property(InjectionChecker.APPLICATION_PROPERTY, InjectionChecker.APPLICATION_PROPERTY);
+        property(ServerProperties.WADL_FEATURE_DISABLE, true);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInject.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInject.java
new file mode 100644
index 0000000..0552727
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInject.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.enterprise.inject.Alternative;
+import jakarta.ws.rs.Path;
+import java.util.Collections;
+import java.util.Set;
+
+@ApplicationScoped
+@Alternative
+public class ScopedApplicationInject extends ApplicationInjectParent {
+    @RequestScoped
+    @Path(InjectionChecker.ROOT + "/scoped")
+    public static class ScopedResource extends ResourceParent {
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return Collections.singleton(ScopedResource.class);
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerRequestFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerRequestFilter.java
new file mode 100644
index 0000000..702c559
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerRequestFilter.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.RequestScoped;
+
+@RequestScoped
+public class ScopedContainerRequestFilter extends RequestScopedParentInject implements ParentContainerRequestFilter {
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerResponseFilter.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerResponseFilter.java
new file mode 100644
index 0000000..6dffc92
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedContainerResponseFilter.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.RequestScoped;
+
+@RequestScoped
+public class ScopedContainerResponseFilter extends RequestScopedParentInject implements ParentContainerResponseFilter {
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedExceptionMapper.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedExceptionMapper.java
new file mode 100644
index 0000000..3e711f6
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedExceptionMapper.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class ScopedExceptionMapper extends ParentExceptionMapper {
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedResource.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedResource.java
new file mode 100644
index 0000000..63d2135
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedResource.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.ws.rs.Path;
+
+
+@RequestScoped
+@Path(InjectionChecker.ROOT + "/scope")
+public class ScopedResource extends ParentResource {
+
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedWriterInterceptor.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedWriterInterceptor.java
new file mode 100644
index 0000000..6d25742
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/ScopedWriterInterceptor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import jakarta.enterprise.context.RequestScoped;
+import java.net.URI;
+
+@RequestScoped
+public class ScopedWriterInterceptor extends RequestScopedParentInject implements ParentWriterInterceptor {
+    @Override
+    public URI getRequestUri() {
+        return injectUriInfo.getRequestUri();
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/SseAplication.java b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/SseAplication.java
new file mode 100644
index 0000000..4d40021
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/java/org/glassfish/jersey/tests/cdi/inject/SseAplication.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.server.ServerProperties;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.sse.Sse;
+import jakarta.ws.rs.sse.SseBroadcaster;
+import jakarta.ws.rs.sse.SseEventSink;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class SseAplication extends Application {
+
+    @Path(InjectionChecker.ROOT)
+    @ApplicationScoped
+    public static class ApplicationScopedResource {
+        @Context
+        Sse contextSse;
+
+        @Inject
+        Sse injectSse;
+
+        private static SseBroadcaster contextSseBroadcaster;
+        private static SseBroadcaster injectSseBroadcaster;
+
+        @GET
+        @Path("register/{x}")
+        @Produces(MediaType.SERVER_SENT_EVENTS)
+        public void register(@PathParam("x") String inject, @Context SseEventSink eventSink) {
+            if (inject.contains("context")) {
+                contextSseBroadcaster = contextSse.newBroadcaster();
+                contextSseBroadcaster.register(eventSink);
+                eventSink.send(contextSse.newEvent(inject));
+            } else {
+                injectSseBroadcaster = injectSse.newBroadcaster();
+                injectSseBroadcaster.register(eventSink);
+                eventSink.send(injectSse.newEvent(inject));
+            }
+        }
+
+        @POST
+        @Path("broadcast/{x}")
+        @Consumes(MediaType.MULTIPART_FORM_DATA)
+        public void broadcast(@PathParam("x") String inject, String event) {
+            if (inject.contains("context")) {
+                if (contextSseBroadcaster == null) {
+                    throw new IllegalStateException("contextSseBroadcaster is null");
+                } else if (contextSse == null) {
+                    throw new IllegalStateException("contextSse is null");
+                }
+                contextSseBroadcaster.broadcast(contextSse.newEvent(event));
+                contextSseBroadcaster.close();
+            } else {
+                if (injectSseBroadcaster == null) {
+                    throw new IllegalStateException("injectSseBroadcaster is null");
+                } else if (injectSse == null) {
+                    throw new IllegalStateException("injectSse is null");
+                }
+                injectSseBroadcaster.broadcast(injectSse.newEvent(event));
+                injectSseBroadcaster.close();
+            }
+        }
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return Collections.singleton(ApplicationScopedResource.class);
+    }
+
+    @Override
+    public Map<String, Object> getProperties() {
+        Map<String, Object> props = new HashMap<>(1);
+        props.put(ServerProperties.WADL_FEATURE_DISABLE, true);
+        return props;
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/context-inject-on-server/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..70897bd
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+    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
+
+-->
+
+<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+	   http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
+       bean-discovery-mode="annotated">
+</beans>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInjectTest.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInjectTest.java
new file mode 100644
index 0000000..60c7a1c
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedApplicationInjectTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+public class NonScopedApplicationInjectTest extends JerseyTest {
+    private Weld weld;
+
+    @Before
+    public void setup() {
+        Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld = new Weld();
+            weld.initialize();
+            super.setUp();
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld.shutdown();
+            super.tearDown();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new NonScopedApplicationInject();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        return ServletDeploymentContext.builder(configure())
+                .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, NonScopedApplicationInject.class.getName())
+                .build();
+    }
+
+    @Test
+    public void testIsInjectedOnApplication() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscoped").path("inject").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedOnApplication() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscoped").path("context").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedInjectionTest.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedInjectionTest.java
new file mode 100644
index 0000000..5fc2af1
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/NonScopedInjectionTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+public class NonScopedInjectionTest extends JerseyTest {
+    private Weld weld;
+
+    @Before
+    public void setup() {
+        Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld = new Weld();
+            weld.initialize();
+            super.setUp();
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld.shutdown();
+            super.tearDown();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new NonScopedApplication();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        return ServletDeploymentContext.builder(configure())
+//                .initParam(ServerProperties.PROVIDER_PACKAGES, this.getClass().getPackage().getName())
+                .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, NonScopedApplication.class.getName())
+                .build();
+    }
+
+    @Test
+    public void testIsInjectedOnResource() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscope").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedOnResource() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscope").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testNegativeContext() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonexisting").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.EXPECTATION_FAILED.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testNegativeInject() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonexisting").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.EXPECTATION_FAILED.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsInjectedMapper() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscope").path("iae").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedMapper() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonscope").path("iae").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInjectTest.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInjectTest.java
new file mode 100644
index 0000000..bc7eef7
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedApplicationInjectTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+public class ScopedApplicationInjectTest extends JerseyTest {
+    private Weld weld;
+
+    @Before
+    public void setup() {
+        Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld = new Weld();
+            weld.initialize();
+            super.setUp();
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld.shutdown();
+            super.tearDown();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ScopedApplicationInject();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        return ServletDeploymentContext.builder(configure())
+                .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, ScopedApplicationInject.class.getName())
+                .build();
+    }
+
+    @Test
+    public void testIsInjectedOnApplication() {
+        try (Response r = target(InjectionChecker.ROOT).path("scoped").path("inject").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedOnApplication() {
+        try (Response r = target(InjectionChecker.ROOT).path("scoped").path("context").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedInjectionTest.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedInjectionTest.java
new file mode 100644
index 0000000..660335f
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/ScopedInjectionTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+public class ScopedInjectionTest extends JerseyTest {
+    private Weld weld;
+
+    @Before
+    public void setup() {
+        Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld = new Weld();
+            weld.initialize();
+            super.setUp();
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld.shutdown();
+            super.tearDown();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ScopedApplication();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        return ServletDeploymentContext.builder(configure())
+                .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, ScopedApplication.class.getName())
+                .build();
+    }
+
+    @Test
+    public void testIsInjectedOnResource() {
+        try (Response r = target(InjectionChecker.ROOT).path("scope").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedOnResource() {
+        try (Response r = target(InjectionChecker.ROOT).path("scope").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testNegativeContext() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonexisting").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.EXPECTATION_FAILED.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testNegativeInject() {
+        try (Response r = target(InjectionChecker.ROOT).path("nonexisting").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.EXPECTATION_FAILED.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsInjectedMapper() {
+        try (Response r = target(InjectionChecker.ROOT).path("scope").path("iae").path("injected").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testIsContextedMapper() {
+        try (Response r = target(InjectionChecker.ROOT).path("scope").path("iae").path("contexted").request()
+                .header(InjectionChecker.HEADER, InjectionChecker.HEADER).get()) {
+            System.out.println(r.readEntity(String.class));
+            Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/SseTest.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/SseTest.java
new file mode 100644
index 0000000..b4cadfc
--- /dev/null
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/org/glassfish/jersey/tests/cdi/inject/SseTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.cdi.inject;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.sse.SseEventSource;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class SseTest extends JerseyTest {
+    private Weld weld;
+
+    @Before
+    public void setup() {
+        Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld = new Weld();
+            weld.initialize();
+            super.setUp();
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+            weld.shutdown();
+            super.tearDown();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new SseAplication();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyWebTestContainerFactory();
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        return ServletDeploymentContext.builder(configure())
+                .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, SseAplication.class.getName())
+                .build();
+    }
+
+    @Test
+    public void testContextSse() throws InterruptedException {
+        testSse("contexted");
+    }
+
+    @Test
+    public void testInjectSse() throws InterruptedException {
+        testSse("injected");
+    }
+
+    private void testSse(String injectType) throws InterruptedException {
+        final String entity = "Everyone !!!";
+        final CountDownLatch broadcastLatch = new CountDownLatch(2);
+        final CountDownLatch registerLatch = new CountDownLatch(1);
+        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+        final WebTarget target = target(InjectionChecker.ROOT).path("register").path(injectType);
+        try (SseEventSource source = SseEventSource.target(target).build()) {
+            source.register(inboundSseEvent -> {
+                try {
+                    byteArrayOutputStream.write(inboundSseEvent.readData(String.class).getBytes());
+                    registerLatch.countDown();
+                    broadcastLatch.countDown();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            });
+            source.open();
+            registerLatch.await(5000, TimeUnit.MILLISECONDS);
+            Assert.assertEquals(0, registerLatch.getCount());
+
+            try (Response response = target(InjectionChecker.ROOT).path("broadcast").path(injectType)
+                    .request()
+                    .post(Entity.entity(entity, MediaType.MULTIPART_FORM_DATA_TYPE))) {
+                String readEntity = response.readEntity(String.class);
+                // System.out.println(readEntity);
+                Assert.assertEquals(readEntity, response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+
+            }
+            broadcastLatch.await(5000, TimeUnit.MILLISECONDS);
+        }
+        Assert.assertTrue(byteArrayOutputStream.toString().contains(entity));
+        Assert.assertEquals(0, broadcastLatch.getCount());
+    }
+}
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml
index afc6b5f..51a6ff4 100644
--- a/tests/integration/cdi-integration/pom.xml
+++ b/tests/integration/cdi-integration/pom.xml
@@ -45,6 +45,7 @@
         <module>cdi-with-jersey-injection-custom-cfg-webapp</module>
         <module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>
         <module>cdi-with-jersey-injection-webapp</module>
+        <module>context-inject-on-server</module>
     </modules>
 
     <build>
diff --git a/tests/integration/jersey-4697/pom.xml b/tests/integration/jersey-4697/pom.xml
new file mode 100644
index 0000000..88e62a1
--- /dev/null
+++ b/tests/integration/jersey-4697/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+    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
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.tests.integration</groupId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-4697</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-bundle</artifactId>
+            <type>pom</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/tests/integration/jersey-4697/src/test/java/org/glassfish/jersey/tests/integration/jersey4697/MonitoringEventListenerTest.java b/tests/integration/jersey-4697/src/test/java/org/glassfish/jersey/tests/integration/jersey4697/MonitoringEventListenerTest.java
new file mode 100644
index 0000000..14fa3bc
--- /dev/null
+++ b/tests/integration/jersey-4697/src/test/java/org/glassfish/jersey/tests/integration/jersey4697/MonitoringEventListenerTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 org.glassfish.jersey.tests.integration.jersey4697;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Map;
+
+import jakarta.inject.Inject;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeDataSupport;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.monitoring.MonitoringEventListener;
+import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
+import org.glassfish.jersey.server.monitoring.ExceptionMapperMXBean;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.glassfish.jersey.server.monitoring.RequestEventListener;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class MonitoringEventListenerTest extends JerseyTest {
+
+    private static final long TIMEOUT = 500;
+    private static final String MBEAN_EXCEPTION =
+            "org.glassfish.jersey:type=MonitoringEventListenerTest,subType=Global,exceptions=ExceptionMapper";
+
+    @Path("/example")
+    public static class ExampleResource {
+        @Inject
+        private InjectionManager injectionManager;
+        @GET
+        @Path("/error")
+        public Response error() {
+            throw new RuntimeException("Any exception to be counted in ExceptionMapper");
+        }
+        @GET
+        @Path("/poison")
+        public Response poison() {
+            MonitoringEventListener monitoringEventListener = listener();
+            RequestEvent requestEvent = mock(RequestEvent.class);
+            when(requestEvent.getType()).thenReturn(RequestEvent.Type.START);
+            RequestEventListener eventListener = monitoringEventListener.onRequest(requestEvent);
+            RequestEvent poisonEvent = mock(RequestEvent.class);
+            when(poisonEvent.getType()).thenReturn(RequestEvent.Type.EXCEPTION_MAPPING_FINISHED);
+            when(poisonEvent.getExceptionMapper())
+                .thenThrow(new IllegalStateException("This causes the scheduler to stop working"));
+            eventListener.onEvent(poisonEvent);
+            return Response.ok().build();
+        }
+        @GET
+        @Path("/queueSize")
+        public Response queueSize() throws Exception {
+            MonitoringEventListener monitoringEventListener = listener();
+            Method method = MonitoringEventListener.class.getDeclaredMethod("getExceptionMapperEvents");
+            method.setAccessible(true);
+            Collection<?> queue = (Collection<?>) method.invoke(monitoringEventListener);
+            return Response.ok(queue.size()).build();
+        }
+        private MonitoringEventListener listener() {
+            Iterable<ApplicationEventListener> listeners =
+                    Providers.getAllProviders(injectionManager, ApplicationEventListener.class);
+            for (ApplicationEventListener listener : listeners) {
+                if (listener instanceof MonitoringEventListener) {
+                    return (MonitoringEventListener) listener;
+                }
+            }
+            throw new IllegalStateException("MonitoringEventListener was not found");
+        }
+    }
+
+    @Provider
+    public static class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
+        @Override
+        public Response toResponse(RuntimeException e) {
+            return Response.status(500).entity("RuntimeExceptionMapper: " + e.getMessage()).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig resourceConfig = new ResourceConfig(ExampleResource.class);
+        // Need to map the exception to be counted by ExceptionMapper
+        resourceConfig.register(RuntimeExceptionMapper.class);
+        resourceConfig.property(ServerProperties.MONITORING_ENABLED, true);
+        resourceConfig.property(ServerProperties.MONITORING_STATISTICS_ENABLED, true);
+        resourceConfig.property(ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED, true);
+        resourceConfig.property(ServerProperties.MONITORING_STATISTICS_REFRESH_INTERVAL, 1);
+        resourceConfig.setApplicationName("MonitoringEventListenerTest");
+        return resourceConfig;
+    }
+
+    @Test
+    public void exceptionInScheduler() throws Exception {
+        final Long ERRORS_BEFORE_FAIL = 10L;
+        // Send some requests to process some statistics.
+        request(ERRORS_BEFORE_FAIL);
+        // Give some time to the scheduler to collect data.
+        Thread.sleep(TIMEOUT);
+        // All events were consumed by scheduler
+        queueIsEmpty();
+        // Make the scheduler to fail. No more statistics are collected.
+        makeFailure();
+        // Sending again requests
+        request(20);
+        Thread.sleep(TIMEOUT);
+        // No new events should be accepted because scheduler is not working.
+        queueIsEmpty();
+        Long monitoredErrors = mappedErrorsFromJMX(MBEAN_EXCEPTION);
+        assertEquals(ERRORS_BEFORE_FAIL, monitoredErrors);
+    }
+
+    private void makeFailure() {
+        Response response = target("/example/poison").request().get();
+        assertEquals(200, response.getStatus());
+    }
+
+    private void queueIsEmpty() {
+        Response response = target("/example/queueSize").request().get();
+        assertEquals(200, response.getStatus());
+        assertEquals(Integer.valueOf(0), response.readEntity(Integer.class));
+    }
+
+    private Long mappedErrorsFromJMX(String name) throws Exception {
+        Long monitoredErrors = null;
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        ObjectName objectName = new ObjectName(name);
+        ExceptionMapperMXBean bean = JMX.newMBeanProxy(mbs, objectName, ExceptionMapperMXBean.class);
+        Map<?, ?> counter = bean.getExceptionMapperCount();
+        CompositeDataSupport value = (CompositeDataSupport) counter.entrySet().iterator().next().getValue();
+        for (Object obj : value.values()) {
+            if (obj instanceof Long) {
+                // Messy way to get the errors, but generic types doesn't match and there is no nice way
+                monitoredErrors = (Long) obj;
+                break;
+            }
+        }
+        return monitoredErrors;
+    }
+
+    private void request(long requests) {
+        for (long i = 0; i < requests; i++) {
+            Response response = target("/example/error").request().get();
+            assertEquals(500, response.getStatus());
+        }
+    }
+}
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
index 437eb2c..19415ed 100644
--- a/tests/integration/pom.xml
+++ b/tests/integration/pom.xml
@@ -54,6 +54,7 @@
         <module>jersey-4321</module>
         <module>jersey-4507</module>
         <module>jersey-4542</module>
+        <module>jersey-4697</module>
         <module>jersey-4722</module>
         <module>microprofile</module>
 <!--        <module>spring4</module>-->