update the 3.x branch with actual master

diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
index 504fb0e..c2b881d 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
+++ b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -422,8 +422,8 @@
         final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
         final Throwable failure;
         try {
-            final CompletableFuture<ClientResponse> responseFuture =
-                    new CompletableFuture<ClientResponse>().whenComplete(
+            final CompletableFuture<ClientResponse> responseFuture = new CompletableFuture<ClientResponse>();
+            responseFuture.whenComplete(
                             (clientResponse, throwable) -> {
                                 if (throwable != null && throwable instanceof CancellationException) {
                                     // take care of future cancellation
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
index 4eb458d..28d03d4 100644
--- a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
@@ -194,6 +194,31 @@
     /**
      * Create new {@link HttpServer} instance.
      *
+     * @param uri                   uri on which the {@link ApplicationHandler} will be deployed. Only first path
+     *                              segment will be used as context path, the rest will be ignored.
+     * @param config                web application configuration.
+     * @param secure                used for call {@link NetworkListener#setSecure(boolean)}.
+     * @param sslEngineConfigurator Ssl settings to be passed to {@link NetworkListener#setSSLEngineConfig}.
+     * @param parentContext         DI provider specific context with application's registered bindings.
+     * @param start                 if set to false, server will not get started, this allows end users to set
+     *                              additional properties on the underlying listener.
+     * @return newly created {@code HttpServer}.
+     * @throws ProcessingException in case of any failure when creating a new {@code HttpServer} instance.
+     * @see GrizzlyHttpContainer
+     * @since 2.37
+     */
+    public static HttpServer createHttpServer(final URI uri,
+                                              final ResourceConfig config,
+                                              final boolean secure,
+                                              final SSLEngineConfigurator sslEngineConfigurator,
+                                              final Object parentContext,
+                                              final boolean start) {
+        return createHttpServer(uri, new GrizzlyHttpContainer(config, parentContext), secure, sslEngineConfigurator, start);
+    }
+
+    /**
+     * Create new {@link HttpServer} instance.
+     *
      * @param uri           uri on which the {@link ApplicationHandler} will be deployed. Only first path
      *                      segment will be used as context path, the rest will be ignored.
      * @param config        web application configuration.
@@ -212,6 +237,27 @@
     /**
      * Create new {@link HttpServer} instance.
      *
+     * @param uri           uri on which the {@link ApplicationHandler} will be deployed. Only first path
+     *                      segment will be used as context path, the rest will be ignored.
+     * @param config        web application configuration.
+     * @param parentContext DI provider specific context with application's registered bindings.
+     * @param start         if set to false, server will not get started, this allows end users to set
+     *                      additional properties on the underlying listener.
+     * @return newly created {@code HttpServer}.
+     * @throws ProcessingException in case of any failure when creating a new {@code HttpServer} instance.
+     * @see GrizzlyHttpContainer
+     * @since 2.37
+     */
+    public static HttpServer createHttpServer(final URI uri,
+                                              final ResourceConfig config,
+                                              final Object parentContext,
+                                              final boolean start) {
+        return createHttpServer(uri, new GrizzlyHttpContainer(config, parentContext), false, null, start);
+    }
+
+    /**
+     * Create new {@link HttpServer} instance.
+     *
      * @param uri                   uri on which the {@link ApplicationHandler} will be deployed. Only first path
      *                              segment will be used as context path, the rest will be ignored.
      * @param handler               {@link HttpHandler} instance.
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/model/ResourceMethodInvoker.java b/core-server/src/main/java/org/glassfish/jersey/server/model/ResourceMethodInvoker.java
index 94599f2..8780e32 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/model/ResourceMethodInvoker.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/model/ResourceMethodInvoker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2022 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
@@ -85,6 +85,7 @@
     private final Type invocableResponseType;
     private final boolean canUseInvocableResponseType;
     private final boolean isCompletionStageResponseType;
+    private final boolean isCompletionStageResponseResponseType; // CompletionStage<Response>
     private final Type completionStageResponseType;
     private final ResourceMethodDispatcher dispatcher;
     private final Method resourceMethod;
@@ -313,6 +314,8 @@
                 && CompletionStage.class.isAssignableFrom((Class<?>) ((ParameterizedType) invocableResponseType).getRawType());
         this.completionStageResponseType =
                 isCompletionStageResponseType ? ((ParameterizedType) invocableResponseType).getActualTypeArguments()[0] : null;
+        this.isCompletionStageResponseResponseType = Class.class.isInstance(completionStageResponseType)
+                && Response.class.isAssignableFrom((Class<?>) completionStageResponseType);
     }
 
     private <T> void addNameBoundProviders(
@@ -465,7 +468,7 @@
             if (canUseInvocableResponseType
                     && response.hasEntity()
                     && !(response.getEntityType() instanceof ParameterizedType)) {
-                response.setEntityType(unwrapInvocableResponseType(context.request()));
+                response.setEntityType(unwrapInvocableResponseType(context.request(), response.getEntityType()));
             }
 
             return response;
@@ -484,10 +487,10 @@
         return jaxrsResponse;
     }
 
-    private Type unwrapInvocableResponseType(ContainerRequest request) {
+    private Type unwrapInvocableResponseType(ContainerRequest request, Type entityType) {
         if (isCompletionStageResponseType
-                && request.resolveProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE)) {
-            return completionStageResponseType;
+                && request.resolveProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.FALSE)) {
+            return isCompletionStageResponseResponseType ? entityType : completionStageResponseType;
         }
         return invocableResponseType;
     }
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index 51408e2..3500e13 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -96,6 +96,11 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-binding</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-json-gson</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
index 50d4255..5e536e6 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2022 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
@@ -65,7 +65,8 @@
 
     @Override
     protected Application configure() {
-        return new ResourceConfig(CompletionStageResource.class, DataBeanWriter.class);
+        return new ResourceConfig(CompletionStageResource.class, DataBeanWriter.class)
+                .property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
     }
 
     @Test
@@ -106,6 +107,14 @@
     }
 
     @Test
+    public void testGetCompletedAsyncResponse() {
+        Response response = target("cs/completedAsyncResponse").request().get();
+
+        assertThat(response.getStatus(), is(200));
+        assertThat(response.readEntity(List.class).get(0), is(ENTITY));
+    }
+
+    @Test
     public void testGetException400Async() {
         Response response = target("cs/exception400Async").request().get();
 
@@ -215,6 +224,14 @@
         }
 
         @GET
+        @Path("/completedAsyncResponse")
+        public CompletionStage<Response> getCompletedAsyncResponse() {
+            CompletableFuture<Response> cs = new CompletableFuture<>();
+            delaySubmit(() -> cs.complete(Response.ok().entity(Collections.singletonList(ENTITY)).build()));
+            return cs;
+        }
+
+        @GET
         @Path("/exception400Async")
         public CompletionStage<String> getException400Async() {
             CompletableFuture<String> cs = new CompletableFuture<>();