Merge pull request #5646 from senivam/31_merge

merge of the actual 3.0 into the 3.1
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f42b9db..9dcb3de 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-[//]: # " Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. "

+[//]: # " Copyright (c) 2018, 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,13 +18,14 @@
 

 ## Project description

 

-Eclipse Jersey is a REST framework that provides a JAX-RS (JSR-370) implementation and more. 

+Eclipse Jersey is a REST framework that provides a <a href="https://jcp.org/en/jsr/detail?id=370">JAX-RS (JSR-370)</a>, 

+now mainly <a href="https://projects.eclipse.org/projects/ee4j.rest">Jakarta REST</a>, implementation and more. 

 Jersey provides its own APIs that extend the JAX-RS toolkit with additional features and utilities 

 to further simplify RESTful service and client development. Jersey also exposes numerous extension 

 SPIs so that developers may extend Jersey to best suit their needs.

  

 Goals of Jersey project can be summarized in the following points:

-* Track the JAX-RS API and provide regular releases of production quality implementations that ships with GlassFish;

+* Track the JAX-RS/Jakarta REST API and provide regular releases of production quality implementations that ships with GlassFish;

 

 * Provide APIs to extend Jersey & Build a community of users and developers; and finally

 

@@ -41,6 +42,21 @@
 

 * https://github.com/eclipse-ee4j/jersey

 

+## Eclipse Development Process

+

+This Eclipse Foundation open project is governed by the Eclipse Foundation

+Development Process and operates under the terms of the Eclipse IP Policy.

+

+## Specifications

+

+This specification project operates under the terms of the Eclipse Foundation

+Specification process.

+

+* https://eclipse.org/projects/dev_process

+* https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf

+* https://www.eclipse.org/projects/efsp/

+* https://www.eclipse.org/legal/efsp_non_assert.php

+

 ## Eclipse Contributor Agreement

 

 Before your contribution can be accepted by the project team contributors must

diff --git a/bom/pom.xml b/bom/pom.xml
index 80b1556..1ca327c 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.eclipse.ee4j</groupId>
         <artifactId>project</artifactId>
-        <version>1.0.8</version>
+        <version>1.0.9</version>
         <relativePath/>
     </parent>
 
@@ -420,6 +420,11 @@
                 <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>
+            <dependency>
                 <groupId>org.glassfish.jersey.test-framework</groupId>
                 <artifactId>jersey-test-framework-util</artifactId>
                 <version>${project.version}</version>
@@ -435,11 +440,6 @@
                 <version>2.4</version>
                 <inherited>true</inherited>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-site-plugin</artifactId>
-                <version>3.9.1</version>
-            </plugin>
         </plugins>
     </build>
 
diff --git a/bundles/apidocs/pom.xml b/bundles/apidocs/pom.xml
index c55b813..c65e6a1 100644
--- a/bundles/apidocs/pom.xml
+++ b/bundles/apidocs/pom.xml
@@ -128,10 +128,6 @@
             <version>3.1</version>
         </dependency>
         <dependency>
-            <groupId>jakarta.persistence</groupId>
-            <artifactId>jakarta.persistence-api</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.glassfish.jersey.containers</groupId>
             <artifactId>jersey-container-simple-http</artifactId>
             <version>${project.version}</version>
@@ -300,7 +296,7 @@
                             <dependencySourceIncludes>
                                 <dependencySourceInclude>org.glassfish.jersey.*:*</dependencySourceInclude>
                             </dependencySourceIncludes>
-                            <excludePackageNames>*.internal:*.internal.*:*.innate:*.innate.*</excludePackageNames>
+                            <excludePackageNames>*.innate:*.innate.*</excludePackageNames>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/bundles/jaxrs-ri/pom.xml b/bundles/jaxrs-ri/pom.xml
index 2d93a58..0161445 100644
--- a/bundles/jaxrs-ri/pom.xml
+++ b/bundles/jaxrs-ri/pom.xml
@@ -217,7 +217,9 @@
                     <showWarnings>false</showWarnings>
                     <fork>false</fork>
                     <excludes>
-                        <exclude>module-info.java</exclude><exclude>META-INF/versions/11/**</exclude>
+                        <exclude>module-info.java</exclude>
+                        <exclude>META-INF/versions/11/**</exclude>
+                        <exclude>META-INF/versions/21/**</exclude>
                     </excludes>
                 </configuration>
             </plugin>
@@ -314,6 +316,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
+                <version>${shade.mvn.plugin.version}</version>
                 <executions>
                     <execution>
                         <phase>package</phase>
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 1247447..11f2091 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2023 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
@@ -883,7 +883,8 @@
                 Object objectRequest = context.getAttribute(JERSEY_REQUEST_ATTR_NAME);
                 if (objectRequest != null) {
                     ClientRequest clientRequest = (ClientRequest) objectRequest;
-                    SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest).build();
+                    SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest)
+                            .setSNIHostName(clientRequest.getConfiguration()).build();
                     sniConfig.setSNIServerName(socket);
                 }
             }
@@ -937,12 +938,12 @@
         }
 
         @Override
-        public synchronized void mark(int readlimit) {
+        public void mark(int readlimit) {
             in.mark(readlimit);
         }
 
         @Override
-        public synchronized void reset() throws IOException {
+        public void reset() throws IOException {
             checkAborted();
             in.reset();
         }
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 6169a16..4eecc17 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -882,7 +882,8 @@
                 Object objectRequest = context.getAttribute(JERSEY_REQUEST_ATTR_NAME);
                 if (objectRequest != null) {
                     ClientRequest clientRequest = (ClientRequest) objectRequest;
-                    SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest).build();
+                    SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest)
+                            .setSNIHostName(clientRequest.getConfiguration()).build();
                     sniConfig.setSNIServerName(socket);
 
                     final int socketTimeout = ((ClientRequest) objectRequest).resolveProperty(ClientProperties.READ_TIMEOUT, -1);
@@ -941,12 +942,12 @@
         }
 
         @Override
-        public synchronized void mark(int readlimit) {
+        public void mark(int readlimit) {
             in.mark(readlimit);
         }
 
         @Override
-        public synchronized void reset() throws IOException {
+        public void reset() throws IOException {
             checkAborted();
             in.reset();
         }
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
index 422d919..9b92517 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -60,8 +60,10 @@
     private final int connectTimeout;
     private final ProxyConfiguration proxyConfiguration;
     private final AtomicReference<SSLParamConfigurator> sniConfigs = new AtomicReference<>(null);
+    private final Configuration configuration;
 
     ConnectorConfiguration(Client client, Configuration config) {
+        configuration = config;
         final Map<String, Object> properties = config.getProperties();
 
         int proposedChunkSize = JdkConnectorProperties.getValue(properties, ClientProperties.CHUNKED_ENCODING_SIZE,
@@ -181,6 +183,10 @@
         return sniConfigs.get();
     }
 
+    Configuration getConfiguration() {
+        return configuration;
+    }
+
     @Override
     public String toString() {
         return "ConnectorConfiguration{"
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
index b20f00c..7413caf 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -51,7 +51,8 @@
     void send(HttpRequest httpRequest, CompletionHandler<HttpResponse> completionHandler) {
         final Map<String, List<Object>> headers = new HashMap<>();
         httpRequest.getHeaders().forEach((k, v) -> headers.put(k, (List) v));
-        final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().uri(httpRequest.getUri()).headers(headers).build();
+        final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().uri(httpRequest.getUri())
+                .headers(headers).setSNIHostName(connectorConfiguration.getConfiguration()).build();
         connectorConfiguration.setSniConfig(sniConfig);
 
         final DestinationConnectionPool.DestinationKey destinationKey = new DestinationConnectionPool.DestinationKey(
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java
index 15725e7..4070300 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -496,7 +496,7 @@
 
         if (contentLengths != null) {
             try {
-                int bodyLength = Integer.parseInt(contentLengths.get(0));
+                long bodyLength = Long.parseLong(contentLengths.get(0));
                 if (bodyLength == 0) {
                     expectContent = false;
                     return;
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java
index 0a3ede0..7dccd87 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -31,7 +31,7 @@
 
     abstract boolean parse(ByteBuffer input) throws ParseException;
 
-    static TransferEncodingParser createFixedLengthParser(AsynchronousBodyInputStream responseBody, int expectedLength) {
+    static TransferEncodingParser createFixedLengthParser(AsynchronousBodyInputStream responseBody, long expectedLength) {
         return new FixedLengthEncodingParser(responseBody, expectedLength);
     }
 
@@ -42,11 +42,11 @@
 
     private static class FixedLengthEncodingParser extends TransferEncodingParser {
 
-        private final int expectedLength;
+        private final long expectedLength;
         private final AsynchronousBodyInputStream responseBody;
-        private volatile int consumedLength = 0;
+        private volatile long consumedLength = 0;
 
-        FixedLengthEncodingParser(AsynchronousBodyInputStream responseBody, int expectedLength) {
+        FixedLengthEncodingParser(AsynchronousBodyInputStream responseBody, long expectedLength) {
             this.expectedLength = expectedLength;
             this.responseBody = responseBody;
         }
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
index ab71e1f..e6aad83 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -208,7 +208,7 @@
 
         try {
             final SSLParamConfigurator sslConfig = SSLParamConfigurator.builder()
-                    .request(jerseyRequest).setSNIAlways(true).build();
+                    .request(jerseyRequest).setSNIAlways(true).setSNIHostName(jerseyRequest.getConfiguration()).build();
 
             String key = requestUri.getScheme() + "://" + sslConfig.getSNIHostName() + ":" + port;
             ArrayList<Channel> conns;
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 aa0676b..c5a920c 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
@@ -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
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java
index e0446d2..90d138d 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2023 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
@@ -94,7 +94,7 @@
     /**
      * A value of {@code true} declares that the client will try to set
      * unsupported HTTP method to {@link java.net.HttpURLConnection} via
-     * reflection.
+     * reflection as a workaround for a missing HTTP method.
      * <p>
      * NOTE: Enabling this property may cause security related warnings/errors
      * and it may break when other JDK implementation is used. <b>Use only
@@ -103,6 +103,10 @@
      * <p>The value MUST be an instance of {@link java.lang.Boolean}.</p>
      * <p>The default value is {@code false}.</p>
      * <p>The name of the configuration property is <tt>{@value}</tt>.</p>
+     * <p>Since JDK 16 the JDK internal classes are not opened for reflection and the workaround method does not work,
+     * unless {@code --add-opens java.base/java.net=ALL-UNNAMED} for HTTP requests and additional
+     * {@code --add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED} for HTTPS (HttpsUrlConnection) options are set.
+     * </p>
      */
     public static final String SET_METHOD_WORKAROUND =
             "jersey.config.client.httpUrlConnection.setMethodWorkaround";
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 cb32a5c..a92adf5 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
@@ -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
@@ -16,14 +16,15 @@
 
 package org.glassfish.jersey.client.innate.http;
 
-import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.HttpHeaders;
 import org.glassfish.jersey.client.ClientProperties;
 import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.internal.PropertiesResolver;
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSocket;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.UriBuilder;
 import org.glassfish.jersey.internal.PropertiesResolver;
 import org.glassfish.jersey.internal.util.PropertiesHelper;
@@ -52,6 +53,7 @@
         private String sniHostNameHeader = null;
         private String sniHostNameProperty = null;
         private boolean setAlways = false;
+        private String sniHostPrecedence = null;
 
         /**
          * Sets the SNIHostName and {@link URI} from the {@link ClientRequest} instance.
@@ -107,6 +109,62 @@
         }
 
         /**
+         * <p>
+         *     Sets the {@code hostName} to be used for calculating the  {@link javax.net.ssl.SNIHostName}.
+         *     Takes precedence over the HTTP HOST header, if set.
+         * </p>
+         * <p>
+         *     By default, the {@code SNIHostName} is set when the HOST HTTP header differs from the HTTP request host.
+         *     When the {@code hostName} matches the HTTP request host, the {@code SNIHostName} is not set,
+         *     and the HTTP HOST header is not used for setting the {@code SNIHostName}. This allows Domain Fronting.
+         * </p>
+         * @param hostName the host the {@code SNIHostName} should be set for.
+         * @return the builder instance.
+         */
+        public Builder setSNIHostName(String hostName) {
+            sniHostPrecedence = trimSniHostName(hostName);
+            return this;
+        }
+
+        /**
+         * <p>
+         *     Sets the {@code hostName} to be used for calculating the  {@link javax.net.ssl.SNIHostName}.
+         *     The {@code hostName} value is taken from the {@link Configuration} if the property
+         *     {@link ClientProperties#SNI_HOST_NAME} is set.
+         *     Takes precedence over the HTTP HOST header, if set.
+         * </p>
+         * <p>
+         *     By default, the {@code SNIHostName} is set when the HOST HTTP header differs from the HTTP request host.
+         *     When the {@code hostName} matches the HTTP 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>
+         * @param configuration the host the {@code SNIHostName} should be set for.
+         * @return the builder instance.
+         */
+        public Builder setSNIHostName(Configuration configuration) {
+            return setSNIHostName((String) configuration.getProperty(ClientProperties.SNI_HOST_NAME));
+        }
+
+        /**
+         * <p>
+         *     Sets the {@code hostName} to be used for calculating the  {@link javax.net.ssl.SNIHostName}.
+         *     The {@code hostName} value is taken from the {@link PropertiesResolver} if the property
+         *     {@link ClientProperties#SNI_HOST_NAME} is set.
+         *     Takes precedence over the HTTP HOST header, if set.
+         * </p>
+         * <p>
+         *     By default, the {@code SNIHostName} is set when the HOST HTTP header differs from the HTTP request host.
+         *     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>
+         * @param resolver the host the {@code SNIHostName} should be set for.
+         * @return the builder instance.
+         */
+        public Builder setSNIHostName(PropertiesResolver resolver) {
+            return setSNIHostName(resolver.resolveProperty(ClientProperties.SNI_HOST_NAME, String.class));
+        }
+
+        /**
          * Builds the {@link SSLParamConfigurator} instance.
          * @return the configured {@link SSLParamConfigurator} instance.
          */
@@ -121,11 +179,15 @@
             }
 
             final String hostHeader = hostHeaders.get(0).toString();
+            return trimSniHostName(hostHeader);
+        }
+
+        private static String trimSniHostName(String sniHostName) {
             final String trimmedHeader;
-            if (hostHeader != null) {
-                int index = hostHeader.indexOf(':'); // RFC 7230  Host = uri-host [ ":" port ] ;
-                final String trimmedHeader0 = index != -1 ? hostHeader.substring(0, index).trim() : hostHeader.trim();
-                trimmedHeader = trimmedHeader0.isEmpty() ? hostHeader : trimmedHeader0;
+            if (sniHostName != null) {
+                int index = sniHostName.indexOf(':'); // RFC 7230  Host = uri-host [ ":" port ] ;
+                final String trimmedHeader0 = index != -1 ? sniHostName.substring(0, index).trim() : sniHostName.trim();
+                trimmedHeader = trimmedHeader0.isEmpty() ? sniHostName : trimmedHeader0;
             } else {
                 trimmedHeader = null;
             }
@@ -137,7 +199,9 @@
     private SSLParamConfigurator(SSLParamConfigurator.Builder builder) {
         String sniHostName = builder.sniHostNameHeader == null ? builder.sniHostNameProperty : builder.sniHostNameHeader;
         uri = builder.uri;
-        sniConfigurator = SniConfigurator.createWhenHostHeader(uri, sniHostName, builder.setAlways);
+        sniConfigurator = SniConfigurator.createWhenHostHeader(uri,
+                builder.sniHostPrecedence != null ? builder.sniHostPrecedence : sniHostName,
+                builder.setAlways);
     }
 
     /**
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 9e766f5..d5d916d 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
@@ -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
@@ -50,12 +50,13 @@
     }
 
     /**
-     * Create ClientSNI when {@link HttpHeaders#HOST} is set different from the request URI host (or {@code whenDiffer}.is false).
+     * Create {@link SniConfigurator} when {@link HttpHeaders#HOST} is set different from the request URI host
+     * (or {@code whenDiffer}.is false).
      * @param hostUri the Uri of the HTTP request
      * @param sniHostName the SniHostName either from HttpHeaders or the
      *      {@link org.glassfish.jersey.client.ClientProperties#SNI_HOST_NAME} property from Configuration object.
      * @param whenDiffer create {@SniConfigurator only when different from the request URI host}
-     * @return ClientSNI or empty when {@link HttpHeaders#HOST}
+     * @return Optional {@link SniConfigurator} or empty when {@link HttpHeaders#HOST} is equal to the requestHost
      */
     static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, String sniHostName, boolean whenDiffer) {
         if (sniHostName == null) {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
index c89cf19..f19b109 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
@@ -357,7 +357,8 @@
     private ClientResponse _apply(final ClientRequest request) throws IOException {
         final HttpURLConnection uc;
         final Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(request);
-        final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(request).build();
+        final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(request)
+                .setSNIHostName(request.getConfiguration()).build();
         final URI sniUri;
         if (sniConfig.isSNIRequired()) {
             sniUri = sniConfig.toIPRequestUri();
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 1f7de34..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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2023 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
@@ -46,8 +46,8 @@
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.same;
 
 /**
  * {@code ClientRequest} unit tests.
diff --git a/core-common/pom.xml b/core-common/pom.xml
index a83931f..13ab2a5 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -254,9 +254,161 @@
 
     <profiles>
         <profile>
+            <id>build.jdk20-</id>
+            <activation>
+                <jdk>[11,21)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>add.java20-</id>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>src/main/java20-</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>build.jdk21</id>
+            <activation>
+                <jdk>[21,)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>add.java20-</id>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>src/main/java21</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-compile</id>
+                                <configuration>
+                                    <!-- compile everything to ensure module-info contains right entries -->
+                                    <release>21</release>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <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 21+</echo>
+                                    </target>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>compile-java21</id>
+                                <phase>process-resources</phase>
+                                <configuration>
+                                    <target>
+                                        <mkdir dir="${java21.build.outputDirectory}" />
+                                        <javac srcdir="${java21.sourceDirectory}" destdir="${java21.build.outputDirectory}"
+                                               classpath="${project.build.outputDirectory}" includeantruntime="false" release="21"/>
+                                    </target>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>copyJDK21FilesToMultiReleaseJar</id>
+            <activation>
+                <file>
+                    <!-- ${java21.build.outputDirectory} does not work here -->
+                    <exists>target/classes-java21/org/glassfish/jersey/innate/VirtualThreadSupport.class</exists>
+                </file>
+                <jdk>[11,21)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-resources-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>copy-jdk21-sources</id>
+                                <phase>prepare-package</phase>
+                                <goals>
+                                    <goal>copy-resources</goal>
+                                </goals>
+                                <configuration>
+                                    <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/21/org/glassfish/jersey/innate</outputDirectory>
+                                    <resources>
+                                        <resource>
+                                            <directory>${java21.sourceDirectory}/org/glassfish/jersey/innate</directory>
+                                        </resource>
+                                    </resources>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>copy-jdk21-classes-to-meta-inf</id>
+                                <phase>prepare-package</phase>
+                                <goals>
+                                    <goal>copy-resources</goal>
+                                </goals>
+                                <configuration>
+                                    <outputDirectory>${project.build.outputDirectory}/META-INF/versions/21</outputDirectory>
+                                    <resources>
+                                        <resource>
+                                            <directory>${java21.build.outputDirectory}</directory>
+                                        </resource>
+                                    </resources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
             <id>securityOff</id>
             <properties>
-               <surefire.security.argline />
+                <surefire.security.argline />
             </properties>
             <build>
                 <plugins>
@@ -293,6 +445,13 @@
 
     <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>
 
 </project>
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.java
new file mode 100644
index 0000000..b276f3c
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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
+ */
+
+/**
+ * Jersey innate injection related packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
+ */
+package org.glassfish.jersey.innate.inject;
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/ExternalRegistrables.java b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/ExternalRegistrables.java
new file mode 100644
index 0000000..f5c5f8f
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/ExternalRegistrables.java
@@ -0,0 +1,53 @@
+/*
+ * 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.inject.spi;
+
+import jakarta.ws.rs.RuntimeType;
+import java.util.List;
+
+/**
+ * Provide a list of classes or interfaces the InjectionManager can support.
+ */
+public interface ExternalRegistrables {
+
+    /**
+     * Contract - RuntimeType pair. For a contract applicable on both client and server, use {@code null} as RuntimeType.
+     */
+    public static final class ClassRuntimeTypePair {
+        private final Class<?> contract;
+        private final RuntimeType runtimeType;
+
+        public ClassRuntimeTypePair(Class<?> contract, RuntimeType runtimeType) {
+            this.contract = contract;
+            this.runtimeType = runtimeType;
+        }
+
+        public Class<?> getContract() {
+            return contract;
+        }
+
+        public RuntimeType getRuntimeType() {
+            return runtimeType;
+        }
+    }
+
+    /**
+     * List of contracts that can be registered into Jersey to be passed by the external injection framework.
+     * @return list of contracts allowed to be registered in Jersey.
+     */
+    List<ClassRuntimeTypePair> registrableContracts();
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.java
new file mode 100644
index 0000000..5ad36dd
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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
+ */
+
+/**
+ * Jersey innate injection related packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
+ */
+package org.glassfish.jersey.innate.inject.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java
index b0648e7..a1835bb 100644
--- a/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 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
@@ -16,5 +16,6 @@
 
 /**
  * Jersey innate packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
  */
 package org.glassfish.jersey.innate;
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Providers.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Providers.java
index 4bbab3e..f5c467a 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Providers.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Providers.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
@@ -43,7 +43,9 @@
 import jakarta.annotation.Priority;
 
 import org.glassfish.jersey.JerseyPriorities;
+import org.glassfish.jersey.innate.inject.spi.ExternalRegistrables;
 import org.glassfish.jersey.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.ServiceFinder;
 import org.glassfish.jersey.model.ContractProvider;
 import org.glassfish.jersey.model.internal.RankedComparator;
 import org.glassfish.jersey.model.internal.RankedProvider;
@@ -103,6 +105,14 @@
         interfaces.putAll(JAX_RS_PROVIDER_INTERFACE_WHITELIST);
         interfaces.put(jakarta.ws.rs.core.Feature.class, ProviderRuntime.BOTH);
         interfaces.put(Binder.class, ProviderRuntime.BOTH);
+
+        try {
+            ServiceFinder<ExternalRegistrables> registerables = ServiceFinder.find(ExternalRegistrables.class, true);
+            registerables.forEach(regs -> regs.registrableContracts()
+                    .forEach(pair -> interfaces.put(pair.getContract(), ProviderRuntime.fromRuntimeType(pair.getRuntimeType()))));
+        } catch (Throwable t) {
+            LOGGER.warning(LocalizationMessages.ERROR_EXTERNAL_REGISTERABLES_IGNORED(t.getMessage()));
+        }
         return interfaces;
     }
 
@@ -119,6 +129,10 @@
         public RuntimeType getRuntime() {
             return runtime;
         }
+
+        private static ProviderRuntime fromRuntimeType(RuntimeType type) {
+            return type == null ? BOTH : (type == RuntimeType.SERVER ? SERVER : CLIENT);
+        }
     }
 
     /**
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 29be49f..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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2023 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,7 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.glassfish.jersey.innate.VirtualThreadSupport;
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.internal.guava.Preconditions;
 
@@ -58,6 +59,8 @@
 public final class CommittingOutputStream extends OutputStream {
 
     private static final Logger LOGGER = Logger.getLogger(CommittingOutputStream.class.getName());
+    private final boolean isVirtualThread = VirtualThreadSupport.isVirtualThread();
+
     /**
      * Null stream provider.
      */
@@ -275,7 +278,13 @@
 
             commitStream(currentSize);
             if (buffer != null) {
-                buffer.writeTo(adaptedOutput);
+                if (isVirtualThread && adaptedOutput != null) {
+                    adaptedOutput.write(buffer.toByteArray());
+                } else {
+                    // Virtual thread in JDK 21 are blocked by synchronized writeTo
+                    // but about 10% faster than ^ without virtual threads.
+                    buffer.writeTo(adaptedOutput);
+                }
             }
         }
     }
diff --git a/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java b/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java
new file mode 100644
index 0000000..90cafba
--- /dev/null
+++ b/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+    /**
+     * Do not instantiate.
+     */
+    private VirtualThreadSupport() {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Informs whether the given {@link Thread} is virtual.
+     * @return true when the current thread is virtual.
+     */
+    public static boolean isVirtualThread() {
+        return false;
+    }
+}
diff --git a/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java b/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java
new file mode 100644
index 0000000..74f58ba
--- /dev/null
+++ b/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+    /**
+     * Do not instantiate.
+     */
+    private VirtualThreadSupport() {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Informs whether the given {@link Thread} is virtual.
+     * @return true when the current thread is virtual.
+     */
+    public static boolean isVirtualThread() {
+        return Thread.currentThread().isVirtual();
+    }
+}
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 b60bf25..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
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2024 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
@@ -39,6 +39,7 @@
 error.entity.provider.basictypes.character.morechars=A single character expected in the entity input stream.
 error.entity.provider.basictypes.constructor=Error converting entity to {0} type by single String constructor.
 error.entity.provider.basictypes.unkwnown=Unsupported basic type {0}.
+error.external.registerables.ignored=Error reading external registrable contracts: {0}.
 error.finding.exception.mapper.type=Could not find exception type for given ExceptionMapper class: {0}.
 error.interceptor.reader.proceed=Last reader interceptor in the chain called the method proceed.
 error.interceptor.writer.proceed=Last writer interceptor in the chain called the method proceed.
diff --git a/core-common/src/test/java/org/glassfish/jersey/logging/LoggingInterceptorTest.java b/core-common/src/test/java/org/glassfish/jersey/logging/LoggingInterceptorTest.java
index ed4d5dc..a138afb 100644
--- a/core-common/src/test/java/org/glassfish/jersey/logging/LoggingInterceptorTest.java
+++ b/core-common/src/test/java/org/glassfish/jersey/logging/LoggingInterceptorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -32,8 +32,8 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
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 b671e68..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
@@ -53,7 +53,7 @@
 public class ChunkedOutput<T> extends GenericType<T> implements Closeable {
     private static final byte[] ZERO_LENGTH_DELIMITER = new byte[0];
 
-    private final BlockingDeque<T> queue = new LinkedBlockingDeque<>();
+    private final BlockingDeque<T> queue;
     private final byte[] chunkDelimiter;
     private final AtomicBoolean resumed = new AtomicBoolean(false);
     private final Lock lock = new ReentrantLock();
@@ -72,12 +72,59 @@
     private volatile ContainerResponse responseContext;
     private volatile ConnectionCallback connectionCallback;
 
-
     /**
      * Create new {@code ChunkedOutput}.
      */
     protected ChunkedOutput() {
         this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
+        queue = new LinkedBlockingDeque<>();
+    }
+
+    /**
+     * Create new {@code ChunkedOutput} based on builder.
+     *
+     * @param builder the builder to use
+     */
+    protected ChunkedOutput(Builder<T> builder) {
+        super();
+        if (builder.queueCapacity > 0) {
+            queue = new LinkedBlockingDeque<>(builder.queueCapacity);
+        } else {
+            queue = new LinkedBlockingDeque<>();
+        }
+        if (builder.chunkDelimiter != null) {
+            this.chunkDelimiter = new byte[builder.chunkDelimiter.length];
+            System.arraycopy(builder.chunkDelimiter, 0, this.chunkDelimiter, 0, builder.chunkDelimiter.length);
+        } else {
+            this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
+        }
+        if (builder.asyncContextProvider != null) {
+            this.asyncContext = builder.asyncContextProvider.get();
+        }
+    }
+
+    /**
+     * Create new {@code ChunkedOutput} based on builder.
+     *
+     * @param builder the builder to use
+     */
+    private ChunkedOutput(TypedBuilder<T> builder) {
+        super(builder.chunkType);
+
+        if (builder.queueCapacity > 0) {
+            queue = new LinkedBlockingDeque<>(builder.queueCapacity);
+        } else {
+            queue = new LinkedBlockingDeque<>();
+        }
+        if (builder.chunkDelimiter != null) {
+            this.chunkDelimiter = new byte[builder.chunkDelimiter.length];
+            System.arraycopy(builder.chunkDelimiter, 0, this.chunkDelimiter, 0, builder.chunkDelimiter.length);
+        } else {
+            this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
+        }
+        if (builder.asyncContextProvider != null) {
+            this.asyncContext = builder.asyncContextProvider.get();
+        }
     }
 
     /**
@@ -88,6 +135,7 @@
     public ChunkedOutput(final Type chunkType) {
         super(chunkType);
         this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
+        queue = new LinkedBlockingDeque<>();
     }
 
     /**
@@ -103,6 +151,7 @@
         } else {
             this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
         }
+        queue = new LinkedBlockingDeque<>();
     }
 
     /**
@@ -120,6 +169,7 @@
         }
 
         this.asyncContext = asyncContextProvider == null ? null : asyncContextProvider.get();
+        queue = new LinkedBlockingDeque<>();
     }
 
     /**
@@ -137,6 +187,7 @@
         } else {
             this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
         }
+        queue = new LinkedBlockingDeque<>();
     }
 
     /**
@@ -151,6 +202,7 @@
         } else {
             this.chunkDelimiter = chunkDelimiter.getBytes();
         }
+        queue = new LinkedBlockingDeque<>();
     }
 
     /**
@@ -167,6 +219,26 @@
         } else {
             this.chunkDelimiter = chunkDelimiter.getBytes();
         }
+        queue = new LinkedBlockingDeque<>();
+    }
+
+    /**
+     * Returns a builder to create a ChunkedOutput with custom configuration.
+     *
+     * @return builder
+     */
+    public static <T> Builder<T> builder() {
+        return new Builder<>();
+    }
+
+    /**
+     * Returns a builder to create a ChunkedOutput with custom configuration.
+     *
+     * @param chunkType      chunk type. Must not be {code null}.
+     * @return builder
+     */
+    public static <T> TypedBuilder<T> builder(Type chunkType) {
+        return new TypedBuilder<>(chunkType);
     }
 
     /**
@@ -181,7 +253,12 @@
         }
 
         if (chunk != null) {
-            queue.add(chunk);
+            try {
+                queue.put(chunk);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                throw new IOException(e);
+            }
         }
 
         flushQueue();
@@ -351,7 +428,6 @@
 
     /**
      * Get state information.
-     *
      * Please note that {@code ChunkedOutput} can be closed by the client side - client can close connection
      * from its side.
      *
@@ -363,10 +439,12 @@
 
     /**
      * Executed only in case of close being triggered by client.
+     *
      * @param e Exception causing the close
      */
-    protected void onClose(Exception e){
-
+    protected void onClose(Exception e) {
+        // drain queue when an exception occurs to prevent deadlocks
+        queue.clear();
     }
 
     @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
@@ -409,4 +487,78 @@
         this.connectionCallback = connectionCallbackRunner;
         flushQueue();
     }
+
+    /**
+     * Builder that allows to create a new ChunkedOutput based on the given configuration options.
+     *
+     * @param <Y>
+     */
+    public static class Builder<Y> {
+        byte[] chunkDelimiter;
+        int queueCapacity = -1;
+        Provider<AsyncContext> asyncContextProvider;
+
+        private Builder() {
+            // hide constructor
+        }
+
+        /**
+         * Set the chunk delimiter, in bytes.
+         * @param chunkDelimiter the chunk delimiter in bytes
+         * @return builder
+         */
+        public Builder<Y> chunkDelimiter(byte[] chunkDelimiter) {
+            this.chunkDelimiter = chunkDelimiter;
+            return this;
+        }
+
+        /**
+         * Set the queue capacity. If greater than 0, the queue is bounded and will block when full.
+         * @param queueCapacity the queue capacity
+         * @return builder
+         */
+        public Builder<Y> queueCapacity(int queueCapacity) {
+            this.queueCapacity = queueCapacity;
+            return this;
+        }
+
+        /**
+         * Set the async context provider.
+         * @param asyncContextProvider the async context provider
+         * @return builder
+         */
+        public Builder<Y> asyncContextProvider(Provider<AsyncContext> asyncContextProvider) {
+            this.asyncContextProvider = asyncContextProvider;
+            return this;
+        }
+
+        /**
+         * Build the ChunkedOutput based on the given configuration.
+         * @return the ChunkedOutput
+         */
+        public ChunkedOutput<Y> build() {
+            return new ChunkedOutput<>(this);
+        }
+    }
+
+    /**
+     * Builder that allows to create a new ChunkedOutput based on the given configuration options.
+     *
+     * @param <Y>
+     */
+    public static class TypedBuilder<Y> extends Builder<Y> {
+        private Type chunkType;
+
+        private TypedBuilder(Type chunkType) {
+            this.chunkType = chunkType;
+        }
+
+        /**
+         * Build the ChunkedOutput based on the given configuration.
+         * @return the ChunkedOutput
+         */
+        public ChunkedOutput<Y> build() {
+            return new ChunkedOutput<>(this);
+        }
+    }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
index 40faecc..d936c51 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -34,6 +34,9 @@
 import jakarta.ws.rs.core.UriBuilder;
 
 import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
+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.TracingLogger;
 import org.glassfish.jersey.server.ContainerRequest;
 import org.glassfish.jersey.server.internal.ServerTraceEvent;
@@ -66,7 +69,7 @@
     private final LinkedList<ResourceMethod> matchedLocators = new LinkedList<>();
     private final LinkedList<Resource> locatorSubResources = new LinkedList<>();
 
-    private final TracingLogger tracingLogger;
+    private final LazyValue<TracingLogger> tracingLogger;
 
     private volatile ResourceMethod matchedResourceMethod = null;
     private volatile Throwable mappedThrowable = null;
@@ -86,7 +89,8 @@
      */
     public UriRoutingContext(final ContainerRequest requestContext) {
         this.requestContext = requestContext;
-        this.tracingLogger = TracingLogger.getInstance(requestContext);
+        // Tracing Logger is initialized after UriContext before pushMatchedResource
+        this.tracingLogger = Values.lazy((Value<TracingLogger>) () -> TracingLogger.getInstance(requestContext));
     }
 
     // RoutingContext
@@ -97,7 +101,7 @@
 
     @Override
     public void pushMatchedResource(final Object resource) {
-        tracingLogger.log(ServerTraceEvent.MATCH_RESOURCE, resource);
+        tracingLogger.get().log(ServerTraceEvent.MATCH_RESOURCE, resource);
         matchedResources.push(resource);
     }
 
@@ -108,7 +112,7 @@
 
     @Override
     public void pushMatchedLocator(final ResourceMethod resourceLocator) {
-        tracingLogger.log(ServerTraceEvent.MATCH_LOCATOR, resourceLocator.getInvocable().getHandlingMethod());
+        tracingLogger.get().log(ServerTraceEvent.MATCH_LOCATOR, resourceLocator.getInvocable().getHandlingMethod());
         matchedLocators.push(resourceLocator);
     }
 
@@ -189,14 +193,14 @@
 
     @Override
     public void setMatchedResourceMethod(final ResourceMethod resourceMethod) {
-        tracingLogger.log(ServerTraceEvent.MATCH_RESOURCE_METHOD, resourceMethod.getInvocable().getHandlingMethod());
+        tracingLogger.get().log(ServerTraceEvent.MATCH_RESOURCE_METHOD, resourceMethod.getInvocable().getHandlingMethod());
         this.matchedResourceMethod = resourceMethod;
     }
 
     @Override
     public void pushMatchedRuntimeResource(final RuntimeResource runtimeResource) {
-        if (tracingLogger.isLogEnabled(ServerTraceEvent.MATCH_RUNTIME_RESOURCE)) {
-            tracingLogger.log(ServerTraceEvent.MATCH_RUNTIME_RESOURCE,
+        if (tracingLogger.get().isLogEnabled(ServerTraceEvent.MATCH_RUNTIME_RESOURCE)) {
+            tracingLogger.get().log(ServerTraceEvent.MATCH_RUNTIME_RESOURCE,
                     runtimeResource.getResources().get(0).getPath(),
                     runtimeResource.getResources().get(0).getPathPattern().getRegex(),
                     matchResults.peek().group()
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml
index aa4aee9..9a1b29d 100644
--- a/docs/src/main/docbook/appendix-properties.xml
+++ b/docs/src/main/docbook/appendix-properties.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2013, 2023 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
@@ -1170,7 +1170,22 @@
                             </para>
                         </entry>
                     </row>
-
+                    <row>
+                        <entry>&jersey.client.ClientProperties.SNI_HOST_NAME; (Jersey 2.43 or later)</entry>
+                        <entry><literal>jersey.config.client.snihostname</literal></entry>
+                        <entry>
+                            <para>
+                                Sets the host name to be used for calculating the <literal>javax.net.ssl.SNIHostName</literal>
+                                during the HTTPS request. Takes precedence over the HTTP HOST header, if set.
+                            </para>
+                            <para>
+                                By default, the <literal>SNIHostName</literal> is set when the HOST HTTP header differs from
+                                the HTTP request host. When the property value host name matches the HTTPS request host,
+                                the <literal>SNIHostName</literal> is not set, and the HTTP HOST header is not used for
+                                setting the <literal>SNIHostName</literal>. This allows for Domain Fronting.
+                            </para>
+                        </entry>
+                    </row>
                     <row>
                         <entry>&jersey.client.ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION;
                             (Jersey 2.2 or later)</entry>
@@ -1352,7 +1367,7 @@
                         <entry>
                             <para>
                                 If set to &lit.true; then XML root element tag name for collections will
-                                be derived from <literal>javax.xml.bind.annotation.XmlRootElement</literal>
+                                be derived from <literal>jakarta.xml.bind.annotation.XmlRootElement</literal>
                                 annotation value and won't be de-capitalized.
                             </para>
                             <para>
@@ -1412,6 +1427,88 @@
 
 
     </section>
+    <section xml:id="appendix-properties-client-default">
+        <title>The default HttpUrlConnector properties</title>
+        <para>
+            List of properties defined in &jersey.client.HttpUrlConnectorProvider; class.
+        </para>
+
+        <table>
+            <title>List of the default &jersey.client.HttpUrlConnectorProvider; properites</title>
+            <tgroup cols="3">
+                <thead>
+                    <row>
+                        <entry>Constant</entry>
+                        <entry>Value</entry>
+                        <entry>Description</entry>
+                    </row>
+                </thead>
+                <tbody>
+                    <row>
+                        <entry>&jersey.client.HttpUrlConnectorProvider.SET_METHOD_WORKAROUND;</entry>
+                        <entry><literal>jersey.config.client.httpUrlConnection.setMethodWorkaround</literal></entry>
+                        <entry>
+                            <para>
+                                A value of &lit.true; declares that the client will try to set
+                                unsupported HTTP method to <literal>java.net.HttpURLConnection</literal> via
+                                reflection as a workaround for a missing HTTP method.
+                            </para>
+                            <para>
+                                NOTE: Enabling this property may cause security related warnings/errors
+                                and it may break when other JDK implementation is used. <emphasis>Use only
+                                when you know what you are doing.</emphasis>
+                            </para>
+                            <para>
+                                The value MUST be an instance of &lit.jdk6.Boolean;. The default value is &lit.false;.
+                            </para>
+                            <para>Since JDK 16 the JDK internal classes are not opened for reflection and the workaround method
+                                does not work, unless <literal>--add-opens java.base/java.net=ALL-UNNAMED</literal> for HTTP
+                                requests and additional <literal>--add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED</literal>
+                                for HTTPS (<literal>javax.net.ssl.HttpsUrlConnection</literal>) options are set.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.client.HttpUrlConnectorProvider.USE_FIXED_LENGTH_STREAMING;</entry>
+                        <entry><literal>jersey.config.client.httpUrlConnector.useFixedLengthStreaming</literal></entry>
+                        <entry>
+                            <para>
+                                If &lit.true;, the &lit.jersey.client.HttpUrlConnector; (if used) will assume the content length
+                                from the value of <literal>jakarta.ws.rs.core.HttpHeaders#CONTENT_LENGTH</literal> request
+                                header (if present).
+                            </para>
+                            <para>
+                                When this property is enabled and the request has a valid non-zero content length
+                                value specified in its <literal>jakarta.ws.rs.core.HttpHeaders#CONTENT_LENGTH</literal> request
+                                header, that this value will be used as an input to the
+                                <literal>java.net.HttpURLConnection#setFixedLengthStreamingMode(int)</literal> method call
+                                invoked on the underlying <literal>java.net.HttpURLConnection</literal>.
+                                This will also suppress the entity buffering in the <literal>HttpURLConnection</literal>,
+                                which is undesirable in certain scenarios, e.g. when streaming large entities.
+                            </para>
+                            <para>
+                                Note that the content length value defined in the request header must exactly match
+                                the real size of the entity. If the <literal>jakarta.ws.rs.core.HttpHeaders#CONTENT_LENGTH</literal>
+                                header is explicitly specified in a request, this property will be ignored and the
+                                request entity will be still buffered by the underlying <literal>HttpURLConnection</literal> infrastructure.
+                            </para>
+                            <para>
+                                This property also overrides the behaviour enabled by the &jersey.client.ClientProperties.CHUNKED_ENCODING_SIZE;
+                                property. Chunked encoding will only be used, if the size is not specified in the header of the request.
+                            </para>
+                            <para>
+                                Note that this property only applies to client run-times that are configured to use the default
+                                &lit.jersey.client.HttpUrlConnector; as the client connector. The property is ignored by other connectors.
+                            </para>
+                            <para>
+                                The default value is &lit.false;.
+                            </para>
+                        </entry>
+                    </row>
+                </tbody>
+            </tgroup>
+        </table>
+    </section>
     <section xml:id="appendix-properties-client-apache">
         <title>Apache HTTP client configuration properties</title>
 
@@ -2307,4 +2404,80 @@
             </tgroup>
         </table>
     </section>
+    <section xml:id="appendix-properties-multipart">
+        <title>Multipart configuration properties</title>
+
+        <para>
+            List of multipart configuration properties that can be found in &jersey.media.multipart.MultiPartProperties; class.
+        </para>
+
+        <table>
+            <title>
+                List of multipart configuration properties settable in the
+                &jersey.media.multipart.MultiPartProperties.MULTI_PART_CONFIG_RESOURCE; configuration file.
+            </title>
+            <tgroup cols="3">
+                <thead>
+                    <row>
+                        <entry>Constant</entry>
+                        <entry>Value</entry>
+                        <entry>Description</entry>
+                    </row>
+                </thead>
+                <tbody>
+                    <row>
+                        <entry>&jersey.media.multipart.MultiPartProperties.BUFFER_THRESHOLD;</entry>
+                        <entry><literal>jersey.config.multipart.bufferThreshold</literal></entry>
+                        <entry>
+                            <para>
+                                Name of the resource property for the threshold size (in bytes) above which a
+                                body part entity will be buffered to disk instead of being held in memory.
+                            </para>
+                            <para>
+                                The default value is &jersey.message.MessageProperties.IO_DEFAULT_BUFFER_SIZE;
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.media.multipart.MultiPartProperties.MAX_PARTS;</entry>
+                        <entry><literal>jersey.config.multipart.maxParts</literal></entry>
+                        <entry>
+                            <para>
+                                Limit the maximum number of parts the multipart entity can have. If the limit is over,
+                                the error response status <literal>413 - REQUEST_ENTITY_TOO_LARGE</literal>
+                                is returned.
+                            </para>
+                            <para>
+                                By default, the number is unlimited.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.media.multipart.MultiPartProperties.MULTI_PART_CONFIG_RESOURCE;</entry>
+                        <entry><literal>jersey-multipart-config.properties</literal></entry>
+                        <entry>
+                            <para>
+                                Name of a properties resource that (if found in the classpath
+                                for this application) will be used to configure the settings returned
+                                by our getter methods.
+                            </para>
+                        </entry>
+                    </row>
+                    <row>
+                        <entry>&jersey.media.multipart.MultiPartProperties.TEMP_DIRECTORY;</entry>
+                        <entry><literal>jersey.config.multipart.tempDir</literal></entry>
+                        <entry>
+                            <para>
+                                Name of the resource property for the directory to store temporary files containing body parts
+                                of multipart message that extends allowed memory threshold.
+                            </para>
+                            <para>
+                                The default value is not set (will be taken from <literal>java.io.tmpdir</literal> system property).
+                            </para>
+                        </entry>
+                    </row>
+                </tbody>
+            </tgroup>
+        </table>
+    </section>
 </appendix>
\ No newline at end of file
diff --git a/docs/src/main/docbook/async.xml b/docs/src/main/docbook/async.xml
index f496bab..f39b76b 100644
--- a/docs/src/main/docbook/async.xml
+++ b/docs/src/main/docbook/async.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2012, 2021 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
@@ -270,6 +270,9 @@
     public ChunkedOutput<String> getChunkedResponse() {
         final ChunkedOutput<String> output = new ChunkedOutput<String>(String.class);
 
+        // Or use the builder pattern instead, which also allows to configure the queue capacity
+        // final ChunkedOutput<String> output = ChunkedOutput.<String>builder(String.class).queueCapacity(10).build();
+
         new Thread() {
             public void run() {
                 try {
diff --git a/docs/src/main/docbook/client.xml b/docs/src/main/docbook/client.xml
index 998e32b..bfda0f5 100644
--- a/docs/src/main/docbook/client.xml
+++ b/docs/src/main/docbook/client.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 
-    Copyright (c) 2010, 2023 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
@@ -688,71 +688,6 @@
                     </tbody>
                 </tgroup>
             </table>
-
-            <warning xml:id="connectors.warning" xreflabel="Header modification issue">
-                <para>
-                    Be aware of using other than default &lit.jersey.client.Connector; implementation.
-                    There is an issue handling HTTP headers in
-                    &lit.jaxrs.WriterInterceptor; or &lit.jaxrs.ext.MessageBodyWriter;.
-                    If you need to change header fields do not use nor
-                    &lit.jersey.apache.ApacheConnectorProvider; nor &lit.jersey.grizzly.GrizzlyConnectorProvider;
-                    nor &lit.jersey.jetty.JettyConnectorProvider; neither &lit.jersey.netty.NettyConnectorProvider;.
-                    The issue for example applies to Jersey <xref linkend="multipart" endterm="multipart.short"/>
-                    feature that also modifies HTTP headers.
-                </para>
-                <para>
-                    On the other hand, in the default transport connector, there are some restrictions on the headers, that
-                    can be sent in the default configuration.
-                    <literal>HttpUrlConnectorProvider</literal> uses &lit.jdk6.HttpUrlConnection; as an underlying connection
-                    implementation. This JDK class by default restricts the use of following headers:
-                    <itemizedlist>
-                        <listitem>&lit.http.header.AccessControlRequestHeaders;</listitem>
-                        <listitem>&lit.http.header.AccessControlRequestMethod;</listitem>
-                        <listitem>&lit.http.header.Connection; (with one exception - &lit.http.header.Connection; header with
-                            value <literal>Closed</literal> is allowed by default)</listitem>
-                        <listitem>&lit.http.header.ContentLength;</listitem>
-                        <listitem>&lit.http.header.ContentTransferEncoding;</listitem>
-                        <listitem>&lit.http.header.Host;</listitem>
-                        <listitem>&lit.http.header.Keep-Alive;</listitem>
-                        <listitem>&lit.http.header.Origin;</listitem>
-                        <listitem>&lit.http.header.Trailer;</listitem>
-                        <listitem>&lit.http.header.Transfer-Encoding;</listitem>
-                        <listitem>&lit.http.header.Upgrade;</listitem>
-                        <listitem>&lit.http.header.Via;</listitem>
-                        <listitem>all the headers starting with &lit.http.header.Sec.prefix;</listitem>
-                    </itemizedlist>
-                    The underlying connection can be configured to permit all headers to be sent,
-                    however this behaviour can be changed only by setting the system property
-                    <literal>sun.net.http.allowRestrictedHeaders</literal>.
-                    <example>
-                        <title>Sending restricted headers with <literal>HttpUrlConnector</literal></title>
-                        <programlisting language="java" linenumbering="numbered">
-                            Client client = ClientBuilder.newClient();
-                            System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
-
-                            Response response = client.target(yourUri).path(yourPath).request().
-                            header("Origin", "http://example.com").
-                            header("Access-Control-Request-Method", "POST").
-                            get();
-                        </programlisting>
-                    </example>
-                </para>
-                <para>
-                    Note, that internally the &lit.jdk6.HttpUrlConnection; instances are pooled, so (un)setting the
-                    property after already creating a target typically does not have any effect.
-                    The property influences all the connections <emphasis>created</emphasis> after the property has been
-                    (un)set, but there is no guarantee, that your request will use a connection
-                    created after the property change.
-                </para>
-                <para>
-                    In a simple environment, setting the property before creating the first target is sufficient, but in complex
-                    environments (such as application servers), where some poolable connections might exist before your
-                    application even bootstraps, this approach is not 100% reliable and we recommend using a different client
-                    transport connector, such as Apache Connector.
-                    These limitations have to be considered especially when invoking <emphasis>CORS</emphasis> (Cross Origin
-                    Resource Sharing) requests.
-                </para>
-            </warning>
         </para>
         <para>
             As indicated earlier, &jersey.client.Connector; and &jersey.client.ConnectorProvider; contracts are Jersey-specific
@@ -761,8 +696,8 @@
             instance:
 
             <programlisting language="java" linenumbering="numbered">ClientConfig clientConfig = new ClientConfig();
-clientConfig.connectorProvider(new GrizzlyConnectorProvider());
-Client client = ClientBuilder.newClient(clientConfig);</programlisting>
+                clientConfig.connectorProvider(new GrizzlyConnectorProvider());
+                Client client = ClientBuilder.newClient(clientConfig);</programlisting>
 
             &lit.jaxrs.client.Client; accepts as a constructor argument a &lit.jaxrs.core.Configurable; instance. Jersey
             implementation of the &lit.jaxrs.core.Configurable; provider for the client is &lit.jersey.client.ClientConfig;.
@@ -781,11 +716,96 @@
             Jersey 2.40. The following example shows how to setup the custom Grizzly Asynchronous HTTP Client based
             &lit.jersey.client.ConnectorProvider; in a Jersey client instance:
             <programlisting language="java" linenumbering="numbered">Client client = ClientBuilder.newBuilder()
-    .property(ClientProperties.CONNECTOR_PROVIDER, "org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider")
-    .build();</programlisting>
+                .property(ClientProperties.CONNECTOR_PROVIDER, "org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider")
+                .build();</programlisting>
 
             For more information about the property see <xref linkend="appendix-properties"/>.
         </para>
+        <para>
+            <warning xml:id="connectors.warning" xreflabel="Header modification issue">
+                <para>
+                    Be aware of using other than default &lit.jersey.client.Connector; implementation.
+                    There is an issue handling HTTP headers in
+                    &lit.jaxrs.WriterInterceptor; or &lit.jaxrs.ext.MessageBodyWriter;.
+                    If you need to change header fields do not use neither
+                    &lit.jersey.apache.ApacheConnectorProvider; nor &lit.jersey.grizzly.GrizzlyConnectorProvider;
+                    nor &lit.jersey.jetty.JettyConnectorProvider; (for asynchronous requests).
+                    Other older version connectors can be affected by this issue as well.
+                    The issue for example applies to Jersey <xref linkend="multipart" endterm="multipart.short"/>
+                    feature that also modifies HTTP headers.
+                </para>
+            </warning>
+        </para>
+        <section>
+            <title>The default &lit.jersey.client.HttpUrlConnector;</title>
+
+            <para>The default connector is the most advanced connector, and it supports the most features Jersey has to offer.
+                However, there are a few limitations coming from the &lit.jdk6.HttpUrlConnection;</para>.
+            <para>
+                One limitation is in the variety of HTTP methods supported by the &lit.jdk6.HttpUrlConnection;, since only the
+                original HTTP/1.1 methods are supported. For instance, HTTP Patch method is not supported. See
+                property &jersey.client.HttpUrlConnectorProvider.SET_METHOD_WORKAROUND; in the Appendix
+                <xref linkend="appendix-properties-client-default"/> for a possible workaround.
+            </para>
+            <para>
+                Also, in the default transport connector, there are some restrictions on the headers, that
+                can be sent in the default configuration.
+                <literal>HttpUrlConnectorProvider</literal> uses &lit.jdk6.HttpUrlConnection; as an underlying connection
+                implementation. This JDK class by default restricts the use of following headers:
+                <itemizedlist>
+                    <listitem>&lit.http.header.AccessControlRequestHeaders;</listitem>
+                    <listitem>&lit.http.header.AccessControlRequestMethod;</listitem>
+                    <listitem>&lit.http.header.Connection; (with one exception - &lit.http.header.Connection; header with
+                        value <literal>Closed</literal> is allowed by default)</listitem>
+                    <listitem>&lit.http.header.ContentLength;</listitem>
+                    <listitem>&lit.http.header.ContentTransferEncoding;</listitem>
+                    <listitem>&lit.http.header.Host;</listitem>
+                    <listitem>&lit.http.header.Keep-Alive;</listitem>
+                    <listitem>&lit.http.header.Origin;</listitem>
+                    <listitem>&lit.http.header.Trailer;</listitem>
+                    <listitem>&lit.http.header.Transfer-Encoding;</listitem>
+                    <listitem>&lit.http.header.Upgrade;</listitem>
+                    <listitem>&lit.http.header.Via;</listitem>
+                    <listitem>all the headers starting with &lit.http.header.Sec.prefix;</listitem>
+                </itemizedlist>
+                The underlying connection can be configured to permit all headers to be sent,
+                however this behaviour can be changed only by setting the system property
+                <literal>sun.net.http.allowRestrictedHeaders</literal>.
+                <example>
+                    <title>Sending restricted headers with <literal>HttpUrlConnector</literal></title>
+                    <programlisting language="java" linenumbering="numbered">
+                        Client client = ClientBuilder.newClient();
+                        System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+
+                        Response response = client.target(yourUri).path(yourPath).request().
+                        header("Origin", "http://example.com").
+                        header("Access-Control-Request-Method", "POST").
+                        get();
+                    </programlisting>
+                </example>
+                <warning>
+                    <para>
+                        Internally, the &lit.jdk6.HttpUrlConnection; instances are pooled, so (un)setting the
+                        property after already creating a target typically does not have any effect.
+                        The property influences all the connections <emphasis>created</emphasis> after the property has been
+                        (un)set, but there is no guarantee, that your request will use a connection
+                        created after the property change.
+                    </para>
+                    <para>
+                        In a simple environment, setting the property before creating the first target is sufficient, but in complex
+                        environments (such as application servers), where some poolable connections might exist before your
+                        application even bootstraps, this approach is not 100% reliable and we recommend using a different client
+                        transport connector, such as Apache Connector.
+                        These limitations have to be considered especially when invoking <emphasis>CORS</emphasis> (Cross Origin
+                        Resource Sharing) requests.
+                    </para>
+                </warning>
+            </para>
+            <para>
+                The limited configurability of the &lit.jdk6.HttpUrlConnection; is another aspect to consider. For details, see
+                <literal>Java Networking Properties</literal>, for instance property <literal>http.maxConnections</literal>.
+            </para>
+        </section>
         <section>
             <title>Client Connectors Properties</title>
             <para>
@@ -956,7 +976,7 @@
         <para>
             To solve injection of a custom type into a client provider instance
             use &jersey.client.InjectionManagerClientProvider; to
-            extract &hk2.ServiceLocator; which can return the required injection. The following example shows how to utilize
+            extract &lit.jersey.common.internal.inject.InjectionManager; which can return the required injection. The following example shows how to utilize
             &lit.jersey.client.InjectionManagerClientProvider;:
         </para>
         <example>
@@ -981,7 +1001,7 @@
         </example>
         <para>
             For more information see javadoc of &jersey.client.InjectionManagerClientProvider;
-            (and javadoc of &lit.jersey.common.InjectionManagerProvider; which supports common JAX-RS components).
+            (and javadoc of &lit.jersey.common.InjectionManagerProvider; which supports common Jakarta REST components).
         </para>
     </section>
 
@@ -1142,6 +1162,19 @@
                 Note that only <literal>Apache Connector, JDK Connector, Netty connector</literal>, and the default
                 <literal>HttpUrlConnector</literal> do support this feature.
             </para>
+            <para>
+                Sometimes, it may be required the <literal>SNIHostName</literal> is not set, or it differs from the
+                HTTP <literal>Host</literal> header. In that case, the &jersey.client.ClientProperties.SNI_HOST_NAME;
+                property can be utilized. The property sets the host name to be used for calculating the
+                <literal>javax.net.ssl.SNIHostName</literal>. The property takes precedence over the HTTP
+                <literal>Host</literal> header.
+            </para>
+            <para>
+                When the host name in the the &jersey.client.ClientProperties.SNI_HOST_NAME; property matches the HTTP request
+                host, the <literal>SNIHostName</literal> is not set, and the HTTP <literal>Host</literal> header is not used
+                for setting the <literal>SNIHostName</literal>.
+                Turning the SNI off allows for Domain Fronting.
+            </para>
         </section>
 
     </section>
diff --git a/docs/src/main/docbook/custom-di.xml b/docs/src/main/docbook/custom-di.xml
index 6e83b52..407cc2e 100644
--- a/docs/src/main/docbook/custom-di.xml
+++ b/docs/src/main/docbook/custom-di.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    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
@@ -60,6 +60,35 @@
     </para>
 
     <para>
+        Since Jersey 2.26, the injection has been abstracted, so that &hk2.link; can be eventually replaced by the CDI or
+        any other injection framework. In the next chapters, we document possibilities provided directly by &hk2.link; and
+        by Jersey abstraction components.
+    </para>
+
+    <section xml:id="injection.manager">
+        <title>InjectionManager</title>
+
+        <para>
+            Since Jersey 2.26, Jersey comes with the main abstraction interface to communicate with the DI container, the
+            &jersey.common.internal.inject.InjectionManager;. What is <literal>ServiceLocator</literal> for &hk2.link;, or
+            <literal>BeanManager</literal> for CDI, that's &jersey.common.internal.inject.InjectionManager; for Jersey.
+        </para>
+        <para>
+            &jersey.common.internal.inject.InjectionManager; can be injected into the user provided classes instantiated
+            by Jersey. It can also be obtained programmatically by &jersey.client.InjectionManagerClientProvider;
+            and &lit.jersey.common.InjectionManagerProvider; from Jakarta REST components, such as
+            &jaxrs.core.FeatureContext;, or &jaxrs.ext.MessageBodyReader; and &jaxrs.ext.MessageBodyReader;.
+        </para>
+        <para>
+            Customers used to the &hk2.ServiceLocator; can still use it directly; the &hk2.ServiceLocator; can be obtained
+            either directly by injection, or programmatically as <literal>InjectionManager.getInstance(ServiceLocator.class)</literal>.
+        </para>
+    </section>
+
+    <section>
+        <title>Implementing Custom Injection Provider</title>
+
+      <para>
         Relying on Servlet HTTP session concept is not very RESTful. It turns the originally state-less HTTP
         communication schema into a state-full manner. However, it could serve
         as a good example that will help me demonstrate implementation of the use cases described above.
@@ -68,10 +97,7 @@
         Below we will show how to make actual Servlet &jee9.servlet.HttpSession; injectable into JAX-RS components
         and how to make this injection work with a custom inject annotation type. Finally, we will demonstrate
         how you can write &lit.jee9.servlet.HttpSession;-scoped JAX-RS resources.
-    </para>
-
-    <section>
-        <title>Implementing Custom Injection Provider</title>
+      </para>
 
         <para>
             Jersey implementation allows you to directly inject &jee9.servlet.HttpServletRequest; instance into
@@ -89,7 +115,11 @@
     ...
 
 }</programlisting>
+        </para>
+        <section>
+            <title>Using HK2 classes</title>
 
+            <para>
             To make the above injection work, you will need to define an additional HK2 binding in your
             application &jersey.server.ResourceConfig;.
             Let's start with a custom HK2 &hk2.Factory; implementation that knows how to extract
@@ -145,48 +175,122 @@
             @Override
             protected void configure() {
                 bindFactory(HttpSessionFactory.class).to(HttpSession.class)
-                .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+                   .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
             }
         });
     }
 }</programlisting>
 
-            Note that we did not define any explicit injection scope for the new injection binding.
-            By default, HK2 factories are bound in a HK2 &hk2.PerLookup; scope, which is in most
-            cases a good choice and it is suitable also in our example.
-        </para>
+                Note that if we did not define any explicit injection scope for the new injection binding,
+                By default, HK2 factories are bound in a HK2 &hk2.PerLookup; scope, which is in most
+                cases a good choice, and it is suitable also in our example.
+            </para>
 
-        <para>
-            To summarize the approach described above, here is a list of steps to follow
-            when implementing custom injection provider in your Jersey application :
+            <para>
+                To summarize the approach described above, here is a list of steps to follow
+                when implementing custom injection provider in your Jersey application :
 
-            <itemizedlist>
-                <listitem><simpara>Implement your own HK2 &lit.hk2.Factory; to provide the
-                    injectable instances.</simpara></listitem>
-                <listitem><simpara>Use the HK2 &lit.hk2.Factory; to define an injection
-                    binding for the injected instance via custom HK2 &lit.hk2.Binder;.</simpara></listitem>
-                <listitem><simpara>Register the custom HK2 &lit.hk2.Binder; in your application
-                    &lit.jersey.server.ResourceConfig;.</simpara></listitem>
-            </itemizedlist>
-        </para>
+                <itemizedlist>
+                    <listitem><simpara>Implement your own HK2 &lit.hk2.Factory; to provide the
+                        injectable instances.</simpara></listitem>
+                    <listitem><simpara>Use the HK2 &lit.hk2.Factory; to define an injection
+                        binding for the injected instance via custom HK2 &lit.hk2.Binder;.</simpara></listitem>
+                    <listitem><simpara>Register the custom HK2 &lit.hk2.Binder; in your application
+                        &lit.jersey.server.ResourceConfig;.</simpara></listitem>
+                </itemizedlist>
+            </para>
 
-        <para>
-            While the &lit.hk2.Factory;-based approach is quite straight-forward and should help you to
-            quickly prototype or even implement final solutions, you should bear in mind, that your
-            implementation does not need to be based on factories. You can for instance bind your own
-            types directly, while still taking advantage of HK2 provided dependency injection.
-            Also, in your implementation you may want to pay more attention to defining or managing
-            injection binding scopes for the sake of performance or correctness of your custom injection
-            extension.
+            <para>
+                While the &lit.hk2.Factory;-based approach is quite straight-forward and should help you to
+                quickly prototype or even implement final solutions, you should bear in mind, that your
+                implementation does not need to be based on factories. You can for instance bind your own
+                types directly, while still taking advantage of HK2 provided dependency injection.
+                Also, in your implementation you may want to pay more attention to defining or managing
+                injection binding scopes for the sake of performance or correctness of your custom injection
+                extension.
 
-            <important>
-                <para>
-                    While the individual injection binding implementations vary and depend on your use case,
-                    to enable your custom injection extension in Jersey, you must register your custom HK2 &hk2.Binder;
-                    implementation in your application &jersey.server.ResourceConfig;!
-                </para>
-            </important>
-        </para>
+                <important>
+                    <para>
+                        While the individual injection binding implementations vary and depend on your use case,
+                        to enable your custom injection extension in Jersey, you must register your custom HK2 &hk2.Binder;
+                        implementation in your application &jersey.server.ResourceConfig;!
+                    </para>
+                </important>
+            </para>
+        </section>
+        <section>
+            <title>Injection Provider Using Jersey API</title>
+            <para>
+                To make the <literal>HttpSession</literal> injection work without using HK2 API,
+                we will need to create a custom supplier that knows how to extract
+                &lit.jee9.servlet.HttpSession; out of given &lit.jee9.servlet.HttpServletRequest;.
+
+                <programlisting language="java">import java.util.function.Supplier
+    ...
+
+public class HttpSessionSupplier implements Supplier&lt;HttpSession&gt; {
+
+    private final HttpServletRequest request;
+
+    @Inject
+    public HttpSessionSupplier(HttpServletRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    public HttpSession get() {
+        return request.getSession();
+    }
+
+}</programlisting>
+
+                Once implemented, the supplier can be used in a custom Jersey &jersey.common.internal.inject.AbstractBinder;
+                to define the new injection binding for &lit.jee9.servlet.HttpSession;. Finally, the implemented binder
+                can be registered in your &jersey.server.ResourceConfig;:
+
+                <programlisting language="java">import org.glassfish.jersey.internal.inject.AbstractBinder;
+    ...
+public class MyApplication extends ResourceConfig {
+
+    public MyApplication() {
+
+        ...
+
+        register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bindFactory(HttpSessionSupplier.class).to(HttpSession.class)
+                    .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+            }
+        });
+    }
+}</programlisting>
+                   The default scope for Jersey binder is similarly as for the HK2, the
+                &jersey.common.internal.inject.PerLookup;.
+            </para>
+            <para>
+                To summarize the approach described above, here is a list of steps to follow
+                when implementing custom injection provider in your Jersey application :
+
+                <itemizedlist>
+                    <listitem><simpara>Implement your own Supplier to provide the
+                        injectable instances.</simpara></listitem>
+                    <listitem><simpara>Use the Supplier to define an injection
+                        binding for the injected instance via custom &jersey.common.internal.inject.AbstractBinder;.
+                    </simpara></listitem>
+                    <listitem><simpara>Register the custom &jersey.common.internal.inject.AbstractBinder; in your application
+                        &lit.jersey.server.ResourceConfig;.</simpara></listitem>
+                </itemizedlist>
+
+                <important>
+                    <para>
+                        Similarly to the HK2, to enable your custom injection extension in Jersey,
+                        you must register your custom &jersey.common.internal.inject.AbstractBinder;
+                        implementation in your application &jersey.server.ResourceConfig;!
+                    </para>
+                </important>
+            </para>
+        </section>
     </section>
 
     <section>
@@ -231,6 +335,8 @@
             use case will help us to avoid use case specific distractions and allow us better focus on
             the important aspects of the job of defining a custom injection annotation.
         </para>
+        <section>
+            <title>Custom Injection Annotation using HK2</title>
 
         <para>
             If you remember from the previous section, to make the injection in the code snippet above work,
@@ -317,6 +423,104 @@
     }
 }</programlisting>
         </para>
+        </section>
+        <section>
+            <title>Custom Injection Annotation using Jersey InjectionResolver</title>
+
+            <para>
+                Jersey also comes with its &jersey.common.internal.inject.InjectionResolver; used to translate into
+                the HK2 &hk2.InjectionResolver; during runtime. The abstraction is important for allowing to support
+                the custom injection annotation in various DI containers. For instance, the abstraction is used when
+                supporting injection using &jaxrs.core.Context; in the CDI container (<literal>jersey-cdi2-se</literal> module).
+            </para>
+            <para>
+                The SessionInjectResolver then looks as follows:
+<programlisting language="java">import jakarta.inject.Inject;
+
+import jakarta.servlet.http.HttpSession;
+
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+...
+
+public class SessionInjectResolver implements InjectionResolver&lt;SessionInject&gt; {
+
+    private final InjectionManger injectionManager;
+
+    public SessionInjectResolver(InjectionManager) {
+        this.injectionManager = injectionManager;
+    }
+
+    @Override
+    public Object resolve(Injectee injectee) {
+        if (HttpSession.class == injectee.getRequiredType()) {
+            return injectionManager.getInstance(HttpServletRequest.class).getSession();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isConstructorParameterIndicator() {
+        return false;
+    }
+
+    @Override
+    public boolean isMethodParameterIndicator() {
+        return false;
+    }
+
+    @Override
+    public Class&lt;SessionInject&gt; getAnnotation() {
+        return SessionInject.class;
+    }
+}</programlisting>
+
+                The SessionInjectResolver uses &jersey.common.internal.inject.InjectionManager; described in
+                <xref linkend="injection.manager"/>.
+            </para>
+            <para>
+                Unlike with &hk2.link;, Jersey &jersey.common.internal.inject.InjectionResolver; can only be bound
+                as instance in the &jersey.common.internal.inject.AbstractBinder;. That is why the
+                &jersey.common.internal.inject.InjectionManager; is used in the <literal>InjectionResolver</literal>
+                to resolve the <literal>HttpSession</literal> instance.
+            </para>
+            <para>
+                The &jersey.common.internal.inject.InjectionResolver; can be registered in the with Jersey application
+                &lit.jersey.server.ResourceConfig; as follows:
+
+<programlisting language="java">import jakarta.ws.rs.core.Feature;
+
+import org.glassfish.jersey.InjectionManagerProvider;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+
+import jakarta.inject.Singleton;
+
+...
+
+public class MyApplication extends ResourceConfig {
+
+public MyApplication() {
+
+    ...
+
+    register(new Feature() {
+        @Override
+        public boolean configure(FeatureContext context) {
+            final InjectionManager injectionManager = InjectionManagerProvider.getInjectionManager(context);
+            context.register(new AbstractBinder() {
+                @Override
+                protected void configure() {
+                    bind(new SessionInjectResolver(injectionManager)).to(HttpSession.class).in(Singleton.class);
+                }
+            });
+            return true;
+        }
+    });
+}</programlisting>
+            </para>
+        </section>
     </section>
 
     <section>
diff --git a/docs/src/main/docbook/dependencies.xml b/docs/src/main/docbook/dependencies.xml
index 176fe08..889ecea 100644
--- a/docs/src/main/docbook/dependencies.xml
+++ b/docs/src/main/docbook/dependencies.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2010, 2023 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,18 +33,10 @@
         <title>Java SE Compatibility</title>
 
         <para>
-            <emphasis>3.x branch: </emphasis>
+            <emphasis>3.1 branch: </emphasis>
             <itemizedlist>
                 <listitem>
-                    <para>This user guide refers only to version 3 and above of Jersey, its compatibility is described below</para>
-                </listitem>
-                <listitem>
-                    <para>Since version 3.0.0 all Jersey 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.
-                    Some modules, however, are fully compatible with JDK 11 and above (Jetty modules based on Jetty 11).
-                    Some modules (Helidon Connector, Spring 6) require JDK 17.
-                    </para>
+                    <para>This user guide refers only to version 3.1.x of Jersey, its compatibility is described below.</para>
                 </listitem>
                 <listitem>
                     <para>Since version 3.1.0 all Jersey components are compiled with Java SE 11 target.
@@ -60,6 +52,30 @@
                     </para>
                 </listitem>
             </itemizedlist>
+            <table pgwide="1" frame='all' xml:id="jersey-jdk-compatibility">
+                <title>Jersey 3.1.x JDK compatibility</title>
+                <tgroup cols='3' align='center' colsep='1' rowsep='1'>
+                    <colspec colname='c1'/>
+                    <colspec colname='c2'/>
+                    <colspec colname='c3'/>
+                    <thead>
+                        <row>
+                            <entry>Jersey version</entry>
+                            <entry>JDK min version</entry>
+                            <entry>JDK max version</entry>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <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>21</entry></row>
+                        <row><entry>3.1.5</entry><entry>11</entry><entry>21</entry></row>
+                        <row><entry>3.1.6</entry><entry>11</entry><entry>21</entry></row>
+                    </tbody>
+                </tgroup>
+            </table>
         </para>
     </section>
     <section>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent
index be67534..10d0b15 100644
--- a/docs/src/main/docbook/jersey.ent
+++ b/docs/src/main/docbook/jersey.ent
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <!--
 
-    Copyright (c) 2010, 2023 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
@@ -54,7 +54,7 @@
 <!ENTITY heroku.uri "https://www.heroku.com">
 <!ENTITY heroku.link "<link xlink:href='&heroku.uri;'>Heroku</link>">
 <!ENTITY hk2.javadoc.uri "https://javaee.github.io/hk2/apidocs/">
-<!ENTITY hk2.link "<link xlink:href='https://github.com/eclipse-ee4j/glassfish-hk2'>Glassfish-HK2</link>">
+<!ENTITY hk2.link "<link xlink:href='https://eclipse-ee4j.github.io/glassfish-hk2/'>Glassfish-HK2</link>">
 <!ENTITY hk2.spring-bridge.link "<link xlink:href='https://javaee.github.io/hk2/spring-bridge/'>The Spring/HK2 Bridge</link>">
 <!ENTITY jaxb.release.uri "https://eclipse-ee4j.github.io/jaxb-ri">
 <!ENTITY jaxb.javadoc.uri "&jaxb.release.uri;/docs/api/jakarta.xml.bind">
@@ -62,7 +62,7 @@
 <!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://javaee.github.io/javaee-spec/javadocs/javax/json/bind">
+<!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">
 
 <!ENTITY jersey.ext.bean-validation.deps.link "<link xlink:href='&jersey.project-info.uri.prefix;/jersey-bean-validation/dependencies.html'>jersey-bean-validation</link>" >
@@ -220,6 +220,7 @@
 <!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>">
 <!ENTITY jaxrs.core.Form "<link xlink:href='&jaxrs.javadoc.uri;/core/Form.html'>Form</link>">
 <!ENTITY jaxrs.core.GenericEntity "<link xlink:href='&jaxrs.javadoc.uri;/core/GenericEntity.html'>GenericEntity&lt;T&gt;</link>">
 <!ENTITY jaxrs.core.GenericType "<link xlink:href='&jaxrs.javadoc.uri;/core/GenericType.html'>GenericType&lt;T&gt;</link>">
@@ -359,6 +360,7 @@
 <!ENTITY jersey.client.ClientProperties.PROXY_USERNAME "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#PROXY_USERNAME'>ClientProperties.PROXY_USERNAME</link>" >
 <!ENTITY jersey.client.ClientProperties.READ_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#READ_TIMEOUT'>ClientProperties.READ_TIMEOUT</link>" >
 <!ENTITY jersey.client.ClientProperties.REQUEST_ENTITY_PROCESSING "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#REQUEST_ENTITY_PROCESSING'>ClientProperties.REQUEST_ENTITY_PROCESSING</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.ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#SUPPRESS_HTTP_COMPLIANCE_VALIDATION'>ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION</link>" >
 <!ENTITY jersey.client.ClientProperties.SSL_CONTEXT_SUPPLIER "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#SSL_CONTEXT_SUPPLIER'>ClientProperties.SSL_CONTEXT_SUPPLIER</link>" >
 <!ENTITY jersey.client.ClientProperties.USE_ENCODING "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#USE_ENCODING'>ClientProperties.USE_ENCODING</link>" >
@@ -416,7 +418,9 @@
 <!ENTITY jersey.common.CommonProperties.PARAM_CONVERTERS_THROW_IAE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#PARAM_CONVERTERS_THROW_IAE'>CommonProperties.PARAM_CONVERTERS_THROW_IAE</link>" >
 <!ENTITY jersey.common.internal.inject.DisposableSupplier "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/DisposableSupplier.html'>DisposableSupplier</link>">
 <!ENTITY jersey.common.internal.inject.InjectionManager "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/InjectionManager.html'>InjectionManager</link>">
+<!ENTITY jersey.common.internal.inject.InjectionResolver "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/InjectionResolver.html'>InjectionResolver</link>">
 <!ENTITY jersey.common.internal.inject.AbstractBinder "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/AbstractBinder.html'>AbstractBinder</link>">
+<!ENTITY jersey.common.internal.inject.PerLookup "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/PerLookup.html'>PerLookup</link>">
 <!ENTITY jersey.common.internal.inject.Binder "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/Binder.html'>Binder</link>">
 <!ENTITY jersey.common.InjectionManagerProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/InjectionManagerProvider.html'>InjectionManagerProvider</link>">
 <!ENTITY jersey.common.SslConfigurator "<link xlink:href='&jersey.javadoc.uri.prefix;/SslConfigurator.html'>SslConfigurator</link>">
@@ -553,7 +557,12 @@
 <!ENTITY jersey.media.multipart.FormDataParam "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/FormDataParam.html'>@FormDataParam</link>" >
 <!ENTITY jersey.media.multipart.MultiPart "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPart.html'>MultiPart</link>" >
 <!ENTITY jersey.media.multipart.MultiPartFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartFeature.html'>MultiPartFeature</link>" >
-<!ENTITY jersey.media.multipart.StreamDataBodyPart "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/file/StreamDataBodyPart.html'>StreamDataBodyPart</link>" >
+<!ENTITY jersey.media.multipart.MultiPartProperties "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartProperties.html'>MultiPartProperties</link>" >
+<!ENTITY jersey.media.multipart.MultiPartProperties.BUFFER_THRESHOLD "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartProperties.html#BUFFER_THRESHOLD'>MultiPartProperties.BUFFER_THRESHOLD</link>">
+<!ENTITY jersey.media.multipart.MultiPartProperties.MAX_PARTS "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartProperties.html#MAX_PARTS'>MultiPartProperties.MAX_PARTS</link>">
+<!ENTITY jersey.media.multipart.MultiPartProperties.MULTI_PART_CONFIG_RESOURCE "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartProperties.html#MULTI_PART_CONFIG_RESOURCE'>MultiPartProperties.MULTI_PART_CONFIG_RESOURCE</link>">
+<!ENTITY jersey.media.multipart.MultiPartProperties.TEMP_DIRECTORY "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/MultiPartProperties.html#TEMP_DIRECTORY'>MultiPartProperties.TEMP_DIRECTORY</link>">
+<!ENTITY jersey.media.multipart.StreamDataBodyPart "<link xlink:href='&jersey.javadoc.uri.prefix;/media/multipart/file/StreamDataBodyPart.html'>StreamDataBodyPart</link>">
 <!ENTITY jersey.message.MessageBodyWorkers "<link xlink:href='&jersey.javadoc.uri.prefix;/message/MessageBodyWorkers.html'>MessageBodyWorkers</link>">
 <!ENTITY jersey.message.MessageProperties "<link xlink:href='&jersey.javadoc.uri.prefix;/message/MessageProperties.html'>MessageProperties</link>">
 <!ENTITY jersey.message.MessageProperties.DEFLATE_WITHOUT_ZLIB "<link xlink:href='&jersey.javadoc.uri.prefix;/message/MessageProperties.html#DEFLATE_WITHOUT_ZLIB'>MessageProperties.DEFLATE_WITHOUT_ZLIB</link>">
@@ -971,6 +980,7 @@
 <!ENTITY lit.jersey.client.EncodingFeature "<literal>EncodingFeature</literal>">
 <!ENTITY lit.jersey.client.HttpAuthenticationFeature "<literal>HttpAuthenticationFeature</literal>">
 <!ENTITY lit.jersey.client.HttpUrlConnectorProvider "<literal>HttpUrlConnectorProvider</literal>">
+<!ENTITY lit.jersey.client.HttpUrlConnector "<literal>HttpUrlConnector</literal>">
 <!ENTITY lit.jersey.client.InjectionManagerClientProvider "<literal>InjectionManagerClientProvider</literal>">
 <!ENTITY lit.jersey.client.oauth1.AccessToken "<literal>AccessToken</literal>">
 <!ENTITY lit.jersey.client.oauth1.ConsumerCredentials "<literal>ConsumerCredentials</literal>">
diff --git a/docs/src/main/docbook/media.xml b/docs/src/main/docbook/media.xml
index 517b163..34d2a7d 100644
--- a/docs/src/main/docbook/media.xml
+++ b/docs/src/main/docbook/media.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" standalone="no"?>
 <!--
 
-    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
@@ -1935,6 +1935,25 @@
                 </tip>
             </section>
         </section>
+        <section xml:id="multipart.configuration">
+            <title>Properties for configuring the Multipart</title>
+            <para>
+                There are multiple options that can be used when configuring
+                the multipart. See &jersey.media.multipart.MultiPartProperties; or <xref linkend="appendix-properties-multipart"/>
+                for the possibilities.
+            </para>
+            <para>
+                The options can set in a configuration file specified by the
+                &jersey.media.multipart.MultiPartProperties.MULTI_PART_CONFIG_RESOURCE; property.
+                That is the standard Java properties file.
+            </para>
+            <para>
+                Or the options can be set programmatically,
+                by registering <literal>ContextResolver&lt;MultiPartProperties&gt;</literal>. For instance:
+            </para>
+            <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>
diff --git a/docs/src/main/docbook/modules.xml b/docs/src/main/docbook/modules.xml
index fb54949..8ce80ef 100644
--- a/docs/src/main/docbook/modules.xml
+++ b/docs/src/main/docbook/modules.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2023 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
@@ -479,6 +479,14 @@
 <entry>Jersey extension module providing support for Mustache templates.</entry>
 </row>
 <row>
+    <entry>
+        <link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-mvc-thymeleaf/dependencies.html">
+            jersey-mvc-thymeleaf
+        </link>
+    </entry>
+    <entry>Jersey extension module providing support for Thymeleaf templates.</entry>
+</row>
+<row>
 <entry>
 <link xlink:href="https://eclipse-ee4j.github.io/jersey.github.io/project-info/&version;/jersey/project/jersey-proxy-client/dependencies.html">
     jersey-proxy-client
diff --git a/etc/scripts/TCK/EE10/jakarta-ee10-tck.sh b/etc/scripts/TCK/EE10/jakarta-ee10-tck.sh
deleted file mode 100644
index 75dd07c..0000000
--- a/etc/scripts/TCK/EE10/jakarta-ee10-tck.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for listing staging from the staging repo.
-#
-# Input Parameters:
-#     JERSEY_VERSION     - type: String
-#                        - example: 3.1.5
-#                        - description: version of Jersey (EE10) to be tested
-#     GLASSFISH_VERSION  - type: String
-#                        - example: 7.0.6
-#                        - description: version of GF (EE10) to be used within tests
-#     TCK_VERSION        - type: String
-#                        - example: 3.1.3
-#                        - description: version of a TCK bundle which will be downloaded from the staging/central
-# Configuration:
-#
-# JDK:
-#       openjdk-jdk11-latest
-# Git:
-#     https://github.com/eclipse-ee4j/jersey
-#  Branch:
-#     */3.1
-#
-#
-
-#
-# The first sh invocation
-#
-#!/bin/bash -xe
-
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-mvn -f tests/jersey-tck/pom.xml clean install \
-    -Dtck.version=${TCK_VERSION} \
-    -Dglassfish.container.version=${GLASSFISH_VERSION} \
-    -Djersey.version=${JERSEY_VERSION} | tee tck.log
-
-
-#
-# The second sh invocation
-#
-#!/bin/bash -xe
-
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-mvn -f tests/jersey-tck/pom.xml dependency:copy -Dartifact=jakarta.ws.rs:jakarta-restful-ws-tck:${TCK_VERSION} -Dtck.version=${TCK_VERSION} -Dtransitive=false
-export DOWNLOAD_PATH='tests/jersey-tck/target/dependency/'
-export NAME=`ls ${DOWNLOAD_PATH}`
-
-echo '***********************************************************************************' >> SUMMARY.TXT
-echo '***                        TCK bundle information                               ***' >> SUMMARY.TXT
-echo "*** Name:         ${NAME}                            ***" >> SUMMARY.TXT
-echo '*** Artifact ID:	   jakarta.ws.rs:jakarta-restful-ws-tck:'${TCK_VERSION}'         ***' >> SUMMARY.TXT
-echo '*** Date and size: '`stat -c "date: %y, size(b): %s" ${DOWNLOAD_PATH}/${NAME}`'  ***' >> SUMMARY.TXT
-echo '*** SHA256SUM: '`sha256sum ${DOWNLOAD_PATH}/${NAME} | awk '{print $1}'`' ***' >> SUMMARY.TXT
-echo '***                                                                             ***' >> SUMMARY.TXT
-echo '***********************************************************************************' >> SUMMARY.TXT
-echo '***                        TCK results summary                                  ***' >> SUMMARY.TXT
-export TESTS_RUN=`grep 'Skipped: [0-9]*$' tck.log | grep -o 'Tests run: [0-9]*' | awk '{  SUM += $3 } END { print SUM }'`
-export FAILURES=`grep 'Skipped: [0-9]*$' tck.log | grep -o 'Failures: [0-9]*' | awk '{  SUM += $2 } END { print SUM }'`
-export ERRORS=`grep 'Skipped: [0-9]*$' tck.log | grep -o 'Errors: [0-9]*' | awk '{  SUM += $2 } END { print SUM }'`
-export SKIPPED=`grep 'Skipped: [0-9]*$' tck.log | grep -o 'Skipped: [0-9]*' | awk '{  SUM += $2 } END { print SUM }'`
-echo '[INFO] Number of Tests Passed      = '${TESTS_RUN} >> SUMMARY.TXT
-echo '[INFO] Number of Tests Failed      = '${FAILURES} >> SUMMARY.TXT
-echo '[INFO] Number of Tests with Errors = '${ERRORS} >> SUMMARY.TXT
-echo '[INFO] Number of Skipped Tests     = '${SKIPPED} >> SUMMARY.TXT
-echo '[INFO] ****************************************************************************' >> SUMMARY.TXT
-grep 'Tests run:' tck.log | grep --invert-match 'Skipped: [0-9]*$' >> SUMMARY.TXT
-
-
-#
-# Archive the artifacts:
-#    tck.log,tests/jersey-tck/target/glassfish7/glassfish/domains/domain1/logs/server.log,tests/jersey-tck/pom.xml,SUMMARY.TXT
-#
\ No newline at end of file
diff --git a/etc/scripts/TCK/EE8/jersey-staging-GF-integration.sh b/etc/scripts/TCK/EE8/jersey-staging-GF-integration.sh
deleted file mode 100644
index 92c43c0..0000000
--- a/etc/scripts/TCK/EE8/jersey-staging-GF-integration.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/bin/bash -ex
-#
-# 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
-#
-
-#
-# script for Jersey EE8 integration into Glassfish 5.
-#
-# Input Parameters:
-#   GF_URL           - type: String
-#                    - value: http://central.maven.org/maven2/org/glassfish/main/distributions/glassfish/5.1.0/glassfish-5.1.0.zip
-#                    - description: actual URL of the Glassfish 5
-#   MAVEN_REPO_URL   - type: String
-#                    - value: https://jakarta.oss.sonatype.org/content/groups/staging/org/glassfish/jersey
-#                    - description: Jersey binaries location
-#   JERSEY_VERSION   - type: String
-#                    - value: 2.42
-#                    - description: the version of Jersey to be integrated into the GF
-#   JERSEY_JARS      - type: Multi-line String
-#                    - value: containers/glassfish/jersey-gf-ejb/${JERSEY_VERSION}/jersey-gf-ejb
-#                              containers/jersey-container-grizzly2-http/${JERSEY_VERSION}/jersey-container-grizzly2-http
-#                              containers/jersey-container-servlet/${JERSEY_VERSION}/jersey-container-servlet
-#                              containers/jersey-container-servlet-core/${JERSEY_VERSION}/jersey-container-servlet-core
-#                              core/jersey-client/${JERSEY_VERSION}/jersey-client
-#                              core/jersey-common/${JERSEY_VERSION}/jersey-common
-#                              core/jersey-server/${JERSEY_VERSION}/jersey-server
-#                              ext/jersey-bean-validation/${JERSEY_VERSION}/jersey-bean-validation
-#                              ext/cdi/jersey-cdi1x/${JERSEY_VERSION}/jersey-cdi1x
-#                              ext/cdi/jersey-cdi1x-servlet/${JERSEY_VERSION}/jersey-cdi1x-servlet
-#                              ext/cdi/jersey-cdi1x-transaction/${JERSEY_VERSION}/jersey-cdi1x-transaction
-#                              ext/jersey-entity-filtering/${JERSEY_VERSION}/jersey-entity-filtering
-#                              ext/jersey-mvc/${JERSEY_VERSION}/jersey-mvc
-#                              ext/jersey-mvc-jsp/${JERSEY_VERSION}/jersey-mvc-jsp
-#                              inject/jersey-hk2/${JERSEY_VERSION}/jersey-hk2
-#                              media/jersey-media-jaxb/${JERSEY_VERSION}/jersey-media-jaxb
-#                              media/jersey-media-json-binding/${JERSEY_VERSION}/jersey-media-json-binding
-#                              media/jersey-media-json-jackson/${JERSEY_VERSION}/jersey-media-json-jackson
-#                              media/jersey-media-json-jettison/${JERSEY_VERSION}/jersey-media-json-jettison
-#                              media/jersey-media-json-processing/${JERSEY_VERSION}/jersey-media-json-processing
-#                              media/jersey-media-moxy/${JERSEY_VERSION}/jersey-media-moxy
-#                              media/jersey-media-multipart/${JERSEY_VERSION}/jersey-media-multipart
-#                              media/jersey-media-sse/${JERSEY_VERSION}/jersey-media-sse
-#                    - description: List of binaries to be integrated into the GF 5
-#
-#
-# Configuration:
-#
-# JDK:
-#       (System)
-# Git:
-#     ------none------
-#
-#  Copy artifacts from another project:
-#       JAXRS_build
-#    Latest successful build
-#    Artifacts to copy:
-#       **/*.jar
-#    Target directory:
-#       download
-#    [X] Flatten directories [X] Fingerprint Artifacts
-#
-#
-#
-ls
-cd download
-wget -q ${GF_URL} -O glassfish.zip
-#wget -q ${JAX_RS_JAR} -O jakarta.ws.rs-api.jar
-
-while IFS= read -r line ; do wget -q ${MAVEN_REPO_URL}/$line-${JERSEY_VERSION}.jar; done <<< "${JERSEY_JARS}"
-
-echo Listing grabbed jars
-ls *.jar
-
-#unzip
-unzip -q glassfish.zip -d ${WORKSPACE}
-cd ${WORKSPACE}/glassfish5/glassfish/modules
-
-#replace API jar
-#cp -v ${WORKSPACE}/download/jakarta.ws.rs-api.jar .
-
-#replace Jersey Jar
-for jarfile in ${WORKSPACE}/download/*.jar; do
-   echo $(basename $jarfile) | sed -e 's/-RC[0-9][0-9]*//' | sed -e 's/-SNAPSHOT//' | sed -e 's/\.[0-9][0-9]*//' | sed -e 's/\.[0-9][0-9]*//' | sed -e 's/-[0-9][0-9]*//' | while IFS= read -r gfnamejar ; do if [ -f $gfnamejar ]; then rm -v $gfnamejar; cp -v $jarfile $gfnamejar; fi; done;
-done
-
-cd ${WORKSPACE}
-zip -r glassfish.zip glassfish5
-
-
-#
-#  Archive the artifacts:
-#    glassfish.zip
-#
-#
diff --git a/etc/scripts/TCK/EE8/tck-build.sh b/etc/scripts/TCK/EE8/tck-build.sh
deleted file mode 100644
index 40a9cb1..0000000
--- a/etc/scripts/TCK/EE8/tck-build.sh
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/bin/bash -ex
-#
-# 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
-#
-
-#
-# script for building EE8 TCK bundle for Jersey.
-#
-# Input Parameters:
-#   GF_URL     - type: String
-#              - value: https://search.maven.org/remotecontent?filepath=org/glassfish/main/distributions/glassfish/5.1.0/glassfish-5.1.0.zip
-#              - description: actual URL of the Glassfish 5
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk8-latest
-# Git:
-#     https://github.com/eclipse-ee4j/jakartaee-tck.git
-#  Branch:
-#     */master
-#  Check out to a sub-directory:
-#     CTS
-#
-#  [X] With Ant:
-#       apache-ant-latest
-#     JDK:
-#       oracle-jdk8-latest
-#
-#  Copy artifacts from another project:
-#       ts_jte_alter
-#    Latest successful build
-#    Artifacts to copy:
-#       ts.jte
-#    Target directory:
-#       download
-#    [X] Flatten directories [X] Fingerprint Artifacts
-#
-#
-#
-
-mkdir ${WORKSPACE}/CTS/tools
-mkdir ${WORKSPACE}/CTS/tools/ant
-
-#create zip command
-#mkdir batch
-#touch ${WORKSPACE}/batch/zip.sh
-#chmod +x ${WORKSPACE}/batch/zip.sh
-#touch ${WORKSPACE}/batch/zip
-#chmod +x ${WORKSPACE}/batch/zip
-#alias zip='${WORKSPACE}/batch/zip.sh'
-
-#echo "echo ARG1=\$1">batch/zip.sh
-#echo "echo ARG2=\$2">>batch/zip.sh
-#echo "echo ARG3=\$3">>batch/zip.sh
-#echo "if [ \$1='-T' ]; then">>batch/zip.sh
-#echo "	exit">>batch/zip.sh
-#echo "fi">>batch/zip.sh
-#echo "filename=\`echo \$2 | cut -d'.' -f 1,2\`">>batch/zip.sh
-#echo "echo filename=\$filename">>batch/zip.sh
-#echo "tar -zcvf '\${filename}'.tar.gz \$3">>batch/zip.sh
-#echo "mv \${filename}.tar.gz \${filename}.zip">>batch/zip.sh
-#echo "echo created \${filename}.zip">>batch/zip.sh
-
-#echo "${WORKSPACE}/batch/zip.sh \$*">batch/zip
-
-#cat batch/zip.sh
-#cat batch/zip
-
-
-#Set variables
-export ANT_OPTS=-Djavax.xml.accessExternalSchema=all
-
-cd download
-#wget -4 https://jenkins.eclipse.org/jersey/view/TCK/job/ts_jte_alter/lastSuccessfulBuild/artifact/ts.jte
-
-#wget -q https://ci.adoptopenjdk.net/view/Build%20Monitor/job/jtharness/lastSuccessfulBuild/artifact/jtharness.tar.gz -O jtharness.tar.gz
-#wget -q https://ci.adoptopenjdk.net/view/Build%20Monitor/job/sigtest/lastSuccessfulBuild/artifact/sigtest.tar.gz -O sigtest.tar.gz
-#wget -q http://central.maven.org/maven2/com/sun/xml/bind/jaxb-xjc/2.2.7/jaxb-xjc-2.2.7.jar -O jaxb-xjc.jar
-#wget -q http://central.maven.org/maven2/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3.jar -O ant-contrib.jar
-#wget -q http://central.maven.org/maven2/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar
-#wget -q http://central.maven.org/maven2/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar
-#wget -q http://central.maven.org/maven2/commons-codec/commons-codec/1.3/commons-codec-1.3.jar
-#tar xfz jtharness.tar.gz
-#tar xvfz sigtest.tar.gz
-#unzip -q sigtest-4.0
-#cp -av ${WORKSPACE}/download/sigtest-4.0/lib/. ${WORKSPACE}/CTS/lib/
-#cp -v ${WORKSPACE}/download/jtharness/lib/javatest.jar ${WORKSPACE}/CTS/lib/javatest.jar
-#cp -v ${WORKSPACE}/download/jaxb-xjc.jar ${WORKSPACE}/CTS/lib/
-#cp -v ${WORKSPACE}/download/ant-contrib.jar ${WORKSPACE}/CTS/lib/
-#cp -v ${WORKSPACE}/download/ant-contrib.jar ${WORKSPACE}/CTS/lib/ant-contrib-1.0b3.jar
-#cp -v ${WORKSPACE}/download/commons-httpclient-3.1.jar ${WORKSPACE}/CTS/lib/
-#cp -v ${WORKSPACE}/download/commons-logging-1.1.1.jar ${WORKSPACE}/CTS/lib/
-#cp -v ${WORKSPACE}/download/commons-codec-1.3.jar ${WORKSPACE}/CTS/lib/
-
-
-ls
-
-yes | cp -vr ${WORKSPACE}/download/ts.jte ${WORKSPACE}/CTS/install/jaxrs/bin/
-#cp -v ${WORKSPACE}/download/ts.jte ${WORKSPACE}/CTS/bin/ts.jte
-
-wget -q ${GF_URL} -O glassfish.zip
-unzip -q glassfish.zip -d ${WORKSPACE}
-
-#COMPILE TCK
-
-export TS_HOME=${WORKSPACE}/CTS
-export deliverabledir=jaxrs
-export javaee_home=${WORKSPACE}/glassfish5
-
-#touch ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/api = servlet >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/api/rs/ext/interceptor = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/ee = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/jaxrs21 = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/jaxrs21/api = servlet >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/spec = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/servlet3 = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-#echo com/sun/ts/tests/jaxrs/platform  = standalone >> ${WORKSPACE}/CTS/vehicle.properties
-
-#cat ${WORKSPACE}/CTS/vehicle.properties
-
-#fix the test
-cd ${WORKSPACE}/CTS/src/com/sun/ts/tests/jaxrs/jaxrs21/ee/sse/sseeventsink
-sed -i '314s/open()/register(holder::add)/' JAXRSClient.java
-sed -i '315s/register(holder::add)/open()/' JAXRSClient.java
-#end of fix
-
-cd ${WORKSPACE}/CTS/install/${deliverabledir}/bin
-ant build.all
-ant update.jaxrs.wars
-
-# BUNDLE TCK
-
-cd ${WORKSPACE}/CTS/release/tools/
-ant jakartaee-jaxrs
-#ls ${WORKSPACE}/CTS/release/JAXRS_BUILD/
-cd ${WORKSPACE}/CTS/release/JAXRS_BUILD/latest
-for fn in `ls *.zip`; do cp -v "${fn}" `echo ${fn} | cut -d'_' -f 1`_latest.zip; done
-
-#zip -s 10m jaxrstck_split_latest.zip jaxrstck-2.1_latest.zip
-#ls
-
-
-
-#
-#  Archive the artifacts:
-#    CTS/release/JAXRS_BUILD/latest/*.z*
-#
-#
-
diff --git a/etc/scripts/TCK/EE8/tck-run-pipeline.groovy b/etc/scripts/TCK/EE8/tck-run-pipeline.groovy
deleted file mode 100644
index 95936f1..0000000
--- a/etc/scripts/TCK/EE8/tck-run-pipeline.groovy
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env groovy
-
-/*
- * 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
- */
-
-/**
- * Runs TCK for Jersey EE8 on GlassFish 5
- *
- * Input Parameters:
- *
- *   GF_INTEGRATION_JOB_NAME    - type: String
- *                              - value: Jersey_Staging_GF_Integration
- *                              - description: name of a job from which the prepared archive of the Glassfish 5 is taken
- *                              - possible values: Jersey_binaries_GF_integration
- *                                                 Jersey_Staging_GF_Integration
- *                                                 GF5_Jersey2_Archive_Integration
- *   TS_JTE_JOB_NAME            - type: String
- *                              - value: ts_jte_alter
- *                              - description: name of a job from which prepared ts.jte is taken
- *  TCK_BUNDLE_JOB_OR_URL       - type: String
- *                              - value: tck_build
- *                              - description: name of a job from which prepared TCK bundle is taken
- */
-
-node {
-
-    // Job that created the API artifact
-    def GF_BUILD_JOB = "${env.GF_INTEGRATION_JOB_NAME}"
-    def TS_JTE_BUILD_JOB = "${env.TS_JTE_JOB_NAME}"
-    def TCK_BUNDLE_URL = "${env.TCK_BUNDLE_JOB_OR_URL}"
-    def API_JAR_NAME="jakarta.ws.rs-api.jar"
-
-    echo "GF_BUILD_JOB=${GF_BUILD_JOB}"
-    echo "TS_JTE_BUILD_JOB=${TS_JTE_BUILD_JOB}"
-    echo "TCK_BUNDLE_URL=${TCK_BUNDLE_URL}"
-
-    //TCK properties
-    env.deliverabledir="jaxrs"
-    env.tck_root="restful-ws-tck"
-    env.TS_HOME="${env.WORKSPACE}/${env.tck_root}"
-    env.javaee_home="${env.WORKSPACE}/glassfish5"
-
-    env.JAVA_HOME= tool name: 'oracle-jdk8-latest', type: 'jdk'
-    env.ANT_HOME= tool name: 'apache-ant-latest', type: 'ant'
-    env.PATH="${ANT_HOME}/bin:${JAVA_HOME}/bin:${PATH}"
-    env.ANT_OPTS="-Djavax.xml.accessExternalSchema=all"
-
-    stage("Grab GF and ts.jte artifacts") {
-        //https://go.cloudbees.com/docs/cloudbees-documentation/cjoc-user-guide/index.html#cluster-copy-artifacts
-        dir ("download") {
-            copyArtifacts(projectName: "${GF_BUILD_JOB}")
-            copyArtifacts(projectName: "${TS_JTE_BUILD_JOB}")
-        }
-    }
-
-    stage("Grab TCK bundle") {
-        env.TCK_BUNDLE_URL = "${TCK_BUNDLE_URL}"
-        if (!(env.TCK_BUNDLE_URL).startsWith("http")) {
-            dir ("download") {
-                copyArtifacts(projectName: "${TCK_BUNDLE_URL}", filter: "**/*_latest.zip")
-                //flatten - could be done by copyRemoteArtifacts but mapper arg expects java class
-                sh "find . -mindepth 2 -type f -print -exec mv {} . \\;"
-
-                //sh "rm *doc*.zip"
-                sh "mv ${deliverabledir}-tck*.zip ${deliverabledir}-tck.zip"
-            }
-        } else {
-            sh '''#!/bin/bash -ex
-                cd ${WORKSPACE}/download 
-                wget -q ${TCK_BUNDLE_URL} -O ${deliverabledir}-tck.zip
-               '''
-        }
-    }
-
-    stage("Unzip TCK and GF") {
-        sh '''#!/bin/bash -ex
-            cd ${WORKSPACE}
-            unzip ${WORKSPACE}/download/glassfish.zip
-            unzip -q ${WORKSPACE}/download/${deliverabledir}-tck.zip
-            ls
-            ls ${tck_root}
-            
-            cd ${WORKSPACE}/glassfish5/glassfish/modules
-            jar xf jersey-common.jar META-INF/MANIFEST.MF
-            cat  META-INF/MANIFEST.MF | grep Bundle-Version
-           '''
-    }
-
-    stage ("Replace ts.jte") {
-        sh '''#!/bin/bash -ex
-            ls ${TS_HOME}
-            ls ${TS_HOME}/bin
-            yes | cp -rfv ${WORKSPACE}/download/ts.jte ${TS_HOME}/bin/ts.jte
-           '''
-    }
-
-    stage("Configure TCK") {
-        sh '''#!/bin/bash -ex
-            cd ${TS_HOME}/bin
-            ant config.vi
-           '''
-    }
-
-    stage ("Deploy TCK tests") {
-         sh '''#!/bin/bash -ex
-            cd ${TS_HOME}/bin
-            ant deploy.all
-           '''
-    }
-
-    stage ("Run TCK tests") {
-         sh '''#!/bin/bash -ex
-            cd ${TS_HOME}/bin
-            ant run.all | tee run.log
-           '''
-    }
-
-    stage ("Create summary.txt, API, and run.log artifacts") {
-        sh '''#!/bin/bash -ex
-            cd ${TS_HOME}/bin
-            cat run.log | sed -e '1,/Completed running/d' > summary.txt
-            PASSED_COUNT=`head -1 summary.txt | tail -1 | sed 's/.*=\\s\\(.*\\)/\\1/'`
-            FAILED_COUNT=`head -2 summary.txt | tail -1 | sed 's/.*=\\s\\(.*\\)/\\1/'`
-            ERROR_COUNT=`head -3 summary.txt | tail -1 | sed 's/.*=\\s\\(.*\\)/\\1/'`
-            
-            echo ERROR_COUNT=${ERROR_COUNT}
-            echo FAILED_COUNT=${FAILED_COUNT}
-            echo PASSED_COUNT=${PASSED_COUNT}            
-           '''
-
-        archiveArtifacts artifacts: "${env.tck_root}/bin/summary.txt", fingerprint: true
-        archiveArtifacts artifacts: "${env.tck_root}/bin/run.log", fingerprint: true
-        archiveArtifacts artifacts: "glassfish5/glassfish/modules/${API_JAR_NAME}", fingerprint: true
-        archiveArtifacts artifacts: "glassfish5/glassfish/modules/META-INF/MANIFEST.MF", fingerprint: true
-        archiveArtifacts artifacts: "glassfish5/glassfish/domains/domain1/logs/server.log", fingerprint: true
-    }
-}
\ No newline at end of file
diff --git a/etc/scripts/TCK/EE8/ts-jte-alter.sh b/etc/scripts/TCK/EE8/ts-jte-alter.sh
deleted file mode 100644
index 27d908a..0000000
--- a/etc/scripts/TCK/EE8/ts-jte-alter.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for generating ts.jte for EE8 Jersey TCK.
-#
-# Input Parameters:
-#
-#   SERVER_HOME         - type: String
-#                       - value: ${ts.home}/../glassfish5/glassfish
-#  JAXRS_API_JAR_NAME   - type: String
-#                       - value: jakarta.ws.rs-api.jar
-#  HARNESS_REPORT_DIR   - type: String
-#                       - value: ${ts.home}/../JTreport
-#  HARNESS_WORK_DIR     - type: String
-#                       - value: ${ts.home}/../JTwork
-#
-# Configuration:
-#
-# JDK:
-#       (System)
-# Git:
-#     ----none----
-#
-#
-
-wget https://raw.githubusercontent.com/eclipse-ee4j/jakartaee-tck/master/install/jaxrs/bin/ts.jte
-
-JARS_ON_CP="\
-\${web.home}/modules/jersey-client.jar:\
-\${web.home}/modules/jersey-common.jar:\
-\${web.home}/modules/jersey-container-servlet.jar:\
-\${web.home}/modules/jersey-container-servlet-core.jar:\
-\${web.home}/modules/jersey-hk2.jar:\
-\${web.home}/modules/jersey-media-jaxb.jar:\
-\${web.home}/modules/jersey-media-json-binding.jar:\
-\${web.home}/modules/jersey-media-json-processing.jar:\
-\${web.home}/modules/jersey-media-sse.jar:\
-\${web.home}/modules/jersey-server.jar:\
-\${web.home}/modules/jsonp-jaxrs.jar:\
-\${web.home}/modules/asm-all-repackaged.jar:\
-\${web.home}/modules/bean-validator.jar:\
-\${web.home}/modules/endorsed/jakarta.annotation-api.jar:\
-\${web.home}/modules/cdi-api.jar:\
-\${web.home}/modules/cglib.jar:\
-\${web.home}/modules/hk2-api.jar:\
-\${web.home}/modules/hk2-locator.jar:\
-\${web.home}/modules/hk2-utils.jar:\
-\${web.home}/modules/javassist.jar:\
-\${web.home}/modules/jakarta.ejb-api.jar:\
-\${web.home}/modules/jakarta.inject.jar:\
-\${web.home}/modules/jakarta.json.jar:\
-\${web.home}/modules/jakarta.json-api.jar:\
-\${web.home}/modules/jakarta.json.bind-api.jar:\
-\${web.home}/modules/jakarta.interceptor-api.jar:\
-\${web.home}/modules/jakarta.servlet-api.jar:\
-\${web.home}/modules/osgi-resource-locator.jar:\
-\${web.home}/modules/weld-osgi-bundle.jar:\
-\${web.home}/modules/yasson.jar"
-
-sed -i 's/^impl\.vi=/impl\.vi=glassfish/g' ts.jte
-sed -i "s/^web\.home=/$(echo web\.home=${SERVER_HOME} | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^impl\.vi\.deploy\.dir=/$(echo impl\.vi\.deploy\.dir=\${web.home}/domains/domain1/autodeploy | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i 's/^jaxrs_impl_name=/jaxrs_impl_name=jersey/g' ts.jte
-sed -i 's/^harness\.log\.traceflag=/harness\.log\.traceflag=true/g' ts.jte
-sed -i 's/^webServerHost=/webServerHost=localhost/g' ts.jte
-sed -i 's/^webServerPort=/webServerPort=8080/g' ts.jte
-sed -i "s/^work\.dir=\/tmp\/JTwork/$(echo work\.dir=${HARNESS_WORK_DIR} | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^report\.dir=\/tmp\/JTreport/$(echo report\.dir=${HARNESS_REPORT_DIR} | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^jaxrs_impl\.classes=/$(echo jaxrs_impl\.classes=${JARS_ON_CP} | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^jaxrs\.classes=/$(echo jaxrs\.classes=\${web.home}/modules/${JAXRS_API_JAR_NAME} | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^jaxrs_impl_lib=/$(echo jaxrs_impl_lib=\${web.home}/modules/jersey-container-servlet-core.jar | sed -e 's/\\/\\\\/g; s/\//\\\//g;')/g" ts.jte
-sed -i "s/^servlet_adaptor=/servlet_adaptor=org\/glassfish\/jersey\/servlet\/ServletContainer.class/g" ts.jte
-
-sed -i "s/-Dcts.tmp=\.*/-Djavax.xml.accessExternalSchema=all -Dcts.tmp=/g" ts.jte
-
-
-#
-# Archive the artifacts:
-#     ts.jte
\ No newline at end of file
diff --git a/etc/scripts/release/EE10/bundle-apidocs.sh b/etc/scripts/release/EE10/bundle-apidocs.sh
deleted file mode 100644
index 089a1a9..0000000
--- a/etc/scripts/release/EE10/bundle-apidocs.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing api docs bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 3.1.6
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk17-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Branches to build:
-#          tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
-#!/bin/bash -xe
-
-# Execution environment
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-echo '-[ Run maven release plugin ]---------------------------------------------------'
-
-mvn -q -V -C -DstagingDescription="org.glassfish.jersey.bundles.apidocs:${VERSION}" \
-    -Pstaging,oss-release,pre-release -DskipTests -pl :apidocs \
-    -Djersey.version=${VERSION} -Dsource.mvn.plugin.version=3.2.0 install javadoc:jar gpg:sign deploy
\ No newline at end of file
diff --git a/etc/scripts/release/EE10/bundle-examples.sh b/etc/scripts/release/EE10/bundle-examples.sh
deleted file mode 100644
index c49fa1c..0000000
--- a/etc/scripts/release/EE10/bundle-examples.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing examples bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 3.1.6
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk11-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Branches to build:
-#          tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
-
- # Execution environment
- MVN_HOME="/opt/tools/apache-maven/latest/"
- PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
- mvn clean install -C -B -Djersey.version=${VERSION} -DskipTests -Ppre-release,staging -pl org.glassfish.jersey.examples:project -amd
-
- mvn -C -B -DstagingDescription="org.glassfish.jersey.examples:${VERSION}" \
-     -Pstaging,oss-release,pre-release \
-     -Djersey.version=${VERSION} -DskipTests -pl :jersey-examples \
-     deploy
\ No newline at end of file
diff --git a/etc/scripts/release/EE10/bundle-user-guide.sh b/etc/scripts/release/EE10/bundle-user-guide.sh
deleted file mode 100644
index 8890a79..0000000
--- a/etc/scripts/release/EE10/bundle-user-guide.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing User Guide bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 3.1.6
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk11-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Credentials:
-#          GitHub bot SSH
-#    Branches to build:
-#          refs/tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
-#!/bin/bash -xe
-
-# Execution environment
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-cd docs
-
-echo '-[ Run maven release plugin ]---------------------------------------------------'
-
-mvn -q -C -DstagingDescription="org.glassfish.jersey.jersey-documentation:${VERSION}" \
-    -Pstaging,oss-release,pre-release \
-    -DskipTests \
-    install javadoc:jar gpg:sign deploy
\ No newline at end of file
diff --git a/etc/scripts/release/EE10/release.groovy b/etc/scripts/release/EE10/release.groovy
deleted file mode 100644
index ad2f167..0000000
--- a/etc/scripts/release/EE10/release.groovy
+++ /dev/null
@@ -1,333 +0,0 @@
-#!/usr/bin/env groovy
-
-/*
- * 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
- */
-
-/**
- * Release script for Jakarta EE10 Jersey versions
- * Release branch is 3.1
- *
- * Input Parameters:
- * RELEASE_VERSION - type: String
- *                 - example:  3.1.6
- *                 - Description: mandatory release version. Later is being published to staging/central.
- * NEXT_VERSION    - type: String
- *                 - example:  3.1.99-SNAPSHOT
- *                 - Description: mandatory next developing version will be committed in to the release branch and later
- *                               merged into the original release branch for further developing.
- * BRANCH          - type: Choice Parameter
- *                 - values: 3.1
- *                 - Description: Original release branch from which the codebase is being checked out
- * DRY_RUN         - type: Boolean
- *                 - Description: if checked nothing is really committed to Git nor published to the staging
- * OVERWRITE       - type: Boolean
- *                 - Description: if checked allows replacing of the previously published RELEASE_VERSION of Jersey
- *
- */
-
-#!/usr/bin/env groovy
-
-node {
-
-    def MVN_HOME = tool name: 'apache-maven-latest', type: 'maven'
-    def HELP_PLUGIN = 'org.apache.maven.plugins:maven-help-plugin:2.1.1'
-    def TARGET = 'package javadoc:jar gpg:sign install:install'
-    def DEPLOY_TARGET = ''
-    def RELEASE_VERSION = RELEASE_VERSION
-    def NEXT_VERSION = NEXT_VERSION
-    def RELEASE_TAG = ''
-    def NEW_RELEASE_BRANCH = ''
-    def OVERWRITE = OVERWRITE
-    def PROJECT_NAME = 'Jersey'
-    def LOGIN = 'jersey-bot'
-    def EMAIL = 'jersey-bot@eclipse.org'
-    def REPO = 'git@github.com:eclipse-ee4j/jersey.git'
-    def SECRET_FILE_ID = 'secret-subkeys.asc'
-    def CREDENTIALS_ID = 'github-bot-ssh'
-    def GIT_ORIGIN = 'origin'
-    def RELEASE_FOLDER = env.WORKSPACE
-    def RELEASE_BRANCH = BRANCH
-
-    def STAGING_NAME_PATTERN = 'orgglassfishjersey-[0-9]+'
-    def STAGING_NAME = ''
-    def STAGING_PREV_NAME = ''
-    def STAGING_OPEN_NAME = ''
-    def STAGING_DESC = 'org.glassfish.jersey:' + RELEASE_VERSION
-    def STAGING_BOM_DESC = 'org.glassfish.jersey.bom:' + RELEASE_VERSION
-    def STAGING_PROFILE_ID = '70fa3a107a8918'
-
-    def MULTIRELEASE_MODULES = ':jersey-wadl-doclet,:jersey-spring6,:jersey-helidon-connector,:jersey-jetty-connector,:jersey-jetty-http2-connector,:jersey-container-jetty-http,:jersey-container-jetty-http2,:jersey-test-framework-provider-jetty,:jersey-test-framework-provider-jetty-http2'
-
-    def JDK_11_HOME = tool name: 'openjdk-jdk11-latest', type: 'jdk'
-    //def JDK_12_HOME = tool name: 'openjdk-jdk12-latest', type: 'jdk'
-    def JDK_21_HOME = tool name: 'openjdk-jdk21-latest', type: 'jdk'
-    //def JDK_8_HOME = tool name: 'oracle-jdk8-latest', type: 'jdk'
-
-    env.JAVA_HOME = JDK_11_HOME
-    env.PATH = "${env.JAVA_HOME}/bin:${env.PATH}:${MVN_HOME}/bin"
-
-    sh 'java -version'
-
-    stage('Fetch from git') {
-        git(branch: RELEASE_BRANCH, credentialsId: CREDENTIALS_ID, url: REPO)
-    }
-    stage('Prepare environment') {
-
-        dir(RELEASE_FOLDER) {
-            //# Check whether top level pom.xml contains SNAPSHOT version
-            if (!sh(returnStdout: true, script: "grep '<version>' pom.xml | grep 'SNAPSHOT'")?.trim()) {
-                error('-[ Missing SNAPSHOT version in POM! ]-------------------------------------------')
-            }
-
-            //# Compute release versions
-            def SNAPSHOT_VERSION = sh(returnStdout: true, script: 'mvn -q -Dexec.executable="echo" -Dexec.args=\'${project.version}\' --non-recursive exec:exec -Pstaging').trim()
-
-            if (!RELEASE_VERSION?.trim()) {
-                if (!SNAPSHOT_VERSION?.trim()) {
-                    error('-[ Missing required snapshot version number! ]----------------------------------')
-                } else {
-                    def versionTokens = SNAPSHOT_VERSION.split('-')
-                    RELEASE_VERSION = versionTokens[0]
-                }
-            }
-
-            if (!NEXT_VERSION?.trim()) {
-                def (MAJOR_VERSION, MINOR_VERSION) = RELEASE_VERSION.tokenize('.')
-                def NEXT_MINOR_VERSION = (MINOR_VERSION as Integer) + 1
-                NEXT_VERSION = MAJOR_VERSION + '.' + NEXT_MINOR_VERSION + '-SNAPSHOT'
-            }
-
-            RELEASE_TAG = RELEASE_VERSION
-            NEW_RELEASE_BRANCH = RELEASE_VERSION+'-BRANCH'
-
-            echo "Current version: ${SNAPSHOT_VERSION}"
-            echo "Release version: ${RELEASE_VERSION}"
-            echo "Next version:    ${NEXT_VERSION}"
-            echo "Release tag:     ${RELEASE_TAG}"
-            echo "Release branch:  ${NEW_RELEASE_BRANCH}"
-
-            if (!SNAPSHOT_VERSION?.trim() || !RELEASE_VERSION?.trim() || !NEXT_VERSION?.trim()) {
-                error '-[ Missing required version numbers! ]------------------------------------------'
-            }
-
-            if (DRY_RUN == 'true') {
-                echo '-[ Dry run turned on ]----------------------------------------------------------'
-                //TARGET = 'install'
-            } else {
-                DEPLOY_TARGET = ' deploy:deploy'
-            }
-            echo '-[ Configure git user ]--------------------------------------------------------'
-            sh "git config --local user.email \"${EMAIL}\""
-            sh "git config --local user.name \"$LOGIN\""
-
-        }
-
-    }
-    stage('Prepare GPG') {
-        withCredentials([file(credentialsId: SECRET_FILE_ID, variable: 'KEYRING')]) {
-            //# Workaround: GPG initialization
-            sh("gpg --batch --import ${KEYRING}")
-            sh '''
-                for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
-                do
-                    echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
-                done
-                '''
-        }
-    }
-    stage('Prepare branch') {
-        echo '-[ Prepare branch ]-------------------------------------------------------------'
-
-        echo '-[ Switching to release branch ]-------------------------------------------------'
-        sh """
-        git checkout ${GIT_ORIGIN}/${RELEASE_BRANCH} && true
-        git reset --hard ${GIT_ORIGIN}/${RELEASE_BRANCH} && true
-        git checkout -B ${NEW_RELEASE_BRANCH}
-        """
-        echo '-[ Release tag cleanup ]--------------------------------------------------------'
-        def TAG_NAME = sh(returnStdout: true, script: "git tag | grep ${RELEASE_TAG}\$ || true").trim()
-        if (RELEASE_TAG == TAG_NAME) {
-            if (OVERWRITE == 'true') {
-                echo "${RELEASE_TAG} tag already exists, deleting"
-                sshagent([CREDENTIALS_ID]) {
-                    sh "git push --delete origin ${RELEASE_TAG} && true"
-                }
-            } else {
-                error "${RELEASE_TAG} tag already exists"
-            }
-            //# Always delete local tag if exists
-            sh """
-            git tag --delete ${RELEASE_TAG} && true
-            """
-        }
-        sh '''
-        sed -i 's|<suppress files="generated" checks=".*"/>|<suppress files="generated" checks=".*"/><suppress files="unpacked-src" checks=".*"/>|g' etc/config/checkstyle-suppressions.xml
-        '''
-    }
-    stage('Check previous stagings') {
-        if (DRY_RUN == 'true') {
-            echo DRY_RUN + ' ------'
-        } else {
-            if (OVERWRITE == 'true') {
-                STAGING_PREV_NAME = sh(returnStdout: true,
-                        script: "mvn -B --non-recursive -Pstaging nexus-staging:rc-list | awk '/\\[INFO] $STAGING_NAME_PATTERN[ ]+CLOSED[ ]+$STAGING_DESC[ ]*\$/ {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'").trim()
-                echo 'Previously closed staging name: ' + STAGING_PREV_NAME
-            }
-
-            STAGING_OPEN_NAME = sh(returnStdout: true,
-                    script: "mvn -B --non-recursive -Pstaging nexus-staging:rc-list | awk  '/$STAGING_NAME_PATTERN OPEN / {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'").trim()
-
-            if (!STAGING_OPEN_NAME?.trim()) {
-                echo 'No currently open stagings'
-            } else {
-                echo 'Currently open redundand staging: ' + STAGING_OPEN_NAME + ', immediately closing'
-                sh """
-                    OPEN_STAGINGS=${STAGING_OPEN_NAME}
-                    mvn -B -q -Pstaging nexus-staging:rc-drop -DstagingRepositoryId=\${OPEN_STAGINGS}  
-                """
-            }
-        }
-    }
-    /*
-    stage('Open new staging') {
-        if (DRY_RUN == 'true') {
-            echo DRY_RUN + ' ------'
-        } else {
-            STAGING_NAME = sh(returnStdout: true,
-                script: "mvn -B --non-recursive -Pstaging -DstagingProfileId=${STAGING_PROFILE_ID} -DstagingDescription=${STAGING_DESC} nexus-staging:rc-open | awk  '/\\[INFO] Opened / {print \$3}'").trim()
-            echo 'New staging name: '+STAGING_NAME
-        }
-    }*/
-    stage("Build ${PROJECT_NAME}") {
-        echo env.JAVA_HOME
-        echo '-[ Run maven release ]---------------------------------------------------------'
-        echo '-[ Set Release version ]-------------------------------------------------------'
-        sh """
-        cd ${RELEASE_FOLDER}
-        mvn -q -B -V -Pstaging versions:set -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false
-        mvn -q -B -V -Pstaging versions:set -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false -f bom/pom.xml
-        """
-        echo '-[ Update Copyright years ]----------------------------------------------------'
-        sh '''#!/bin/bash -e
-        
-            export CURRENT_YEAR=`date '+%Y'`
-            export SED_CMD_LINE='sed -i "s#, 20.. Oracle and/or its affiliates#, ${CURRENT_YEAR} Oracle and/or its affiliates#g"'
-
-            git status --porcelain --untracked-files=no > modified_pom.log
-            cp modified_pom.log list_of_poms.txt
-            sed -i "s| M |$SED_CMD_LINE |g" modified_pom.log
-            sed -i "s| M ||g" list_of_poms.txt
-
-            bash modified_pom.log
-
-            echo ${CURRENT_YEAR} current year
-
-            while IFS= read -r path_to_pom
-            do
-              export CP_YEAR=`grep -o 'Copyright (c) 20.. Oracle and/or its affiliates' ${path_to_pom} | awk '{print $3}'`
-              [[ -z ${CP_YEAR} ]] && CP_YEAR=${CURRENT_YEAR} || echo ${CP_YEAR}
-              [[ ${CP_YEAR} == ${CURRENT_YEAR} ]] || ( sed -i "s#Copyright (c) ${CP_YEAR} Oracle and/or its affiliates#Copyright (c) ${CP_YEAR}, ${CURRENT_YEAR} Oracle and/or its affiliates#g" ${path_to_pom} ; echo ${path_to_pom} )
-              unset CP_YEAR
-            done < "list_of_poms.txt"
-        '''
-        echo '-[ Run release build ]---------------------------------------------------------'
-        dir(RELEASE_FOLDER) {
-            //env.JAVA_HOME = JDK_12_HOME
-            //sh 'mvn clean install -am -Pstaging -pl :jersey-wadl-doclet -DskipTests -B -q -V -Djersey.version=${RELEASE_VERSION}'
-            env.JAVA_HOME = JDK_21_HOME
-            sh "mvn clean install -B -q -V -DskipTests -am -Pstaging -Djersey.version=${RELEASE_VERSION} --projects ${MULTIRELEASE_MODULES}"
-            env.JAVA_HOME = JDK_11_HOME
-            //
-            sh "mvn -q -B -V -Djersey.version=${RELEASE_VERSION} -DskipTests -Ddoclint=none -Dadditionalparam='-Xdoclint:none' " +
-                    " -Poss-release,staging -U -C ${TARGET} ${DEPLOY_TARGET}"
-            //sh "mvn -Poss-release,staging -pl :jersey-wadl-doclet -am install gpg:sign ${DEPLOY_TARGET} -B -q -V -DskipTests -Djersey.version=${RELEASE_VERSION}"
-
-        }
-    }
-    stage('Prepare release') {
-        sh '''
-        git checkout -- etc/config/checkstyle-suppressions.xml
-        '''
-        echo '-[ Perform release commit to git ]---------------------------------------------'
-        sh "git commit -a -m ${RELEASE_VERSION}"
-        sh "git tag -m ${RELEASE_TAG} -a ${RELEASE_TAG}"
-        echo '-[ Set next snapshot version ]-------------------------------------------------'
-        dir(RELEASE_FOLDER) {
-            sh """
-                mvn -q -B -Pstaging -Djersey.version=${RELEASE_VERSION} versions:set -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false 
-                mvn -q -B -Pstaging -Djersey.version=${RELEASE_VERSION} versions:set -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false -f bom/pom.xml
-            """
-        }
-        echo '-[ Perform commit to git ]-----------------------------------------------------'
-        sh "git commit -a -m ${NEXT_VERSION}"
-    }
-    stage('Publish release') {
-        if (DRY_RUN == 'true') {
-            echo '-[ Prepared branch ]----------------------------------------------------------'
-            sh "git branch --list ${NEW_RELEASE_BRANCH}"
-            echo '-[ Prepared tag ]-------------------------------------------------------------'
-            sh "git tag --list ${NEW_RELEASE_BRANCH}"
-            echo '-[ Prepared commits ]---------------------------------------------------------'
-            sh 'git log -n 5'
-            sshagent([CREDENTIALS_ID]) {
-                sh "git push ${GIT_ORIGIN} ${NEW_RELEASE_BRANCH} --dry-run"
-            }
-            return
-        } else {
-            sshagent([CREDENTIALS_ID]) {
-                sh "git push -f ${GIT_ORIGIN} ${NEW_RELEASE_BRANCH} --follow-tags"
-            }
-        }
-    }
-    stage('Find related staging') {
-        if (DRY_RUN != 'true') {
-            if (!STAGING_NAME?.trim()) {
-                try {
-                    STAGING_NAME =
-                            sh(returnStdout: true,
-                                    script: "mvn -Djersey.version=${RELEASE_VERSION} -B --non-recursive -Pstaging nexus-staging:rc-list | awk  '/$STAGING_NAME_PATTERN OPEN / {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'"
-                            ).trim()
-                } catch (Error err) {
-                    currentBuild.result = 'UNSTABLE'
-                }
-            }
-            echo 'Staging name: ' + STAGING_NAME
-        } else {
-            echo 'DRY_RUN'
-        }
-    }
-    stage('Close released staging') {
-        if (!STAGING_NAME?.trim()) {
-            echo 'Nothing to be closed'
-        } else {
-            sh("mvn -B -q -Pstaging -Djersey.version=${RELEASE_VERSION} nexus-staging:rc-close -DstagingRepositoryId=${STAGING_NAME} -DstagingDescription='${STAGING_DESC}'")
-        }
-    }
-    stage('Drop redundant staging') {
-        if (!STAGING_PREV_NAME?.trim()) {
-            echo 'Nothing to be dropped'
-        } else {
-            try {
-                sh("""
-                OPEN_STAGINGS=${STAGING_PREV_NAME}
-                mvn -Djersey.version=${RELEASE_VERSION} -B -q -Pstaging nexus-staging:rc-drop -DstagingRepositoryId=\${OPEN_STAGINGS}
-                """)
-            } catch (Error err) {
-                currentBuild.result = 'UNSTABLE'
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/etc/scripts/release/EE8/bundle-apidocs.sh b/etc/scripts/release/EE8/bundle-apidocs.sh
deleted file mode 100644
index dc360cc..0000000
--- a/etc/scripts/release/EE8/bundle-apidocs.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing api docs bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 2.42
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk8-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Branches to build:
-#          tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
- # Execution environment
- MVN_HOME="/opt/tools/apache-maven/latest/"
- PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
- if [[ $VERSION == 2* ]] ;
- then
- 	export PROFILE_BUNDLE=',jetty2x'
- fi
-
- sed -i "s|org.glassfish.jersey.ext.micrometer|org.glassfish.jersey.ext|g" bundles/apidocs/pom.xml
-
- echo '-[ Run maven release plugin ]---------------------------------------------------'
-
- mvn -q -C -DstagingDescription="org.glassfish.jersey.bundles.apidocs:${VERSION}" \
-     -Pstaging,oss-release,pre-release${PROFILE_BUNDLE} -DskipTests -Denforcer.skip -pl bundles/apidocs \
-     install javadoc:jar gpg:sign deploy -Dsource.mvn.plugin.version=3.2.0
\ No newline at end of file
diff --git a/etc/scripts/release/EE8/bundle-examples.sh b/etc/scripts/release/EE8/bundle-examples.sh
deleted file mode 100644
index 61afc00..0000000
--- a/etc/scripts/release/EE8/bundle-examples.sh
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing examples bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 2.42
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk8-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Branches to build:
-#          tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
- # Execution environment
- MVN_HOME="/opt/tools/apache-maven/latest/"
- PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
- mvn clean install -C -B -DskipTests -Denforcer.skip -Ppre-release,staging -pl org.glassfish.jersey.examples:project -amd
-
- mvn -C -B -DstagingDescription="org.glassfish.jersey.examples:${VERSION}" \
-     -Pstaging,oss-release,pre-release -Denforcer.skip=true \
-     -DskipTests -pl :jersey-examples \
-     deploy
\ No newline at end of file
diff --git a/etc/scripts/release/EE8/bundle-user-guide.sh b/etc/scripts/release/EE8/bundle-user-guide.sh
deleted file mode 100644
index f6a121d..0000000
--- a/etc/scripts/release/EE8/bundle-user-guide.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for releasing User Guide bundle by release tag.
-#
-# Input Parameters:
-#
-# VERSION - type: String
-#         - example: 2.42
-#         - description: Name of the existing version tag in the Git repo.
-#
-# Configuration:
-#
-# JDK:
-#       oracle-jdk11-latest
-# Git:
-#          git@github.com:eclipse-ee4j/jersey.git
-#    Credentials:
-#          GitHub bot SSH
-#    Branches to build:
-#          refs/tags/${VERSION}
-#
-# Bindings:
-#    Secret file:
-#         Variable:
-#              KEYRING
-#         Credentials:
-#              secret-subkeys.asc
-#
-#
-
-
- gpg --batch --import ${KEYRING}
- for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
- do
-   echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
- done
-
- # Execution environment
- MVN_HOME="/opt/tools/apache-maven/latest/"
- PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
- echo '-[ Set version to ]-'${VERSION}
-
- mvn -q -Pstaging versions:set -DnewVersion=${VERSION} -DgenerateBackupPoms=false -Djersey.version=${VERSION}
-
- cd docs
-
- echo '-[ Run maven release plugin ]---------------------------------------------------'
-
- mvn -q -C -DstagingDescription="org.glassfish.jersey.jersey-documentation:${VERSION}" \
-     -Pstaging,oss-release,pre-release \
-     -DskipTests \
-     -Djersey.version=${VERSION} \
-     install javadoc:jar gpg:sign deploy
\ No newline at end of file
diff --git a/etc/scripts/release/EE8/release.groovy b/etc/scripts/release/EE8/release.groovy
deleted file mode 100644
index 3a88d31..0000000
--- a/etc/scripts/release/EE8/release.groovy
+++ /dev/null
@@ -1,347 +0,0 @@
-#!/usr/bin/env groovy
-
-/*
- * 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
- */
-
-/**
- * Release script for Jakarta EE8/9 Jersey versions
- * Release branches are 2.x or 3.0
- *
- * Input Parameters:
- * RELEASE_VERSION - type: String
- *                 - example:  2.42
- *                 - Description: mandatory release version. Later is being published to staging/central.
- * NEXT_VERSION    - type: String
- *                 - example:  2.43-SNAPSHOT
- *                 - Description: mandatory next developing version will be committed in to the release branch and later
- *                               merged into the original release branch for further developing.
- * BRANCH          - type: Choice Parameter
- *                 - values: 2.x
- *                           3.0
- *                 - Description: Original release branch from which the codebase is being checked out
- * DRY_RUN         - type: Boolean
- *                 - Description: if checked nothing is really committed to Git nor published to the staging
- * OVERWRITE       - type: Boolean
- *                 - Description: if checked allows replacing of the previously published RELEASE_VERSION of Jersey
- *
- */
-
-node {
-
-    def MVN_HOME = tool name: 'apache-maven-latest', type: 'maven'
-    def HELP_PLUGIN = 'org.apache.maven.plugins:maven-help-plugin:2.1.1'
-    def TARGET = 'package javadoc:jar gpg:sign install:install'
-    def DEPLOY_TARGET = ''
-    def RELEASE_VERSION = RELEASE_VERSION
-    def NEXT_VERSION = NEXT_VERSION
-    def RELEASE_TAG = ''
-    def NEW_RELEASE_BRANCH = ''
-    def OVERWRITE = OVERWRITE
-    def PROJECT_NAME = 'Jersey'
-    def LOGIN = 'jersey-bot'
-    def EMAIL = 'jersey-bot@eclipse.org'
-    def REPO = 'git@github.com:eclipse-ee4j/jersey.git'
-    def SECRET_FILE_ID = 'secret-subkeys.asc'
-    def CREDENTIALS_ID = 'github-bot-ssh'
-    def GIT_ORIGIN = 'origin'
-    def RELEASE_FOLDER = env.WORKSPACE
-    def RELEASE_BRANCH = BRANCH
-
-    def STAGING_NAME_PATTERN = 'orgglassfishjersey-[0-9]+'
-    def STAGING_NAME = ''
-    def STAGING_PREV_NAME = ''
-    def STAGING_OPEN_NAME = ''
-    def STAGING_DESC = 'org.glassfish.jersey:' + RELEASE_VERSION
-    def STAGING_BOM_DESC = 'org.glassfish.jersey.bom:' + RELEASE_VERSION
-    def STAGING_PROFILE_ID = '70fa3a107a8918'
-
-    def JDK_11_HOME = tool name: 'openjdk-jdk11-latest', type: 'jdk'
-    def JDK_12_HOME = tool name: 'openjdk-jdk12-latest', type: 'jdk'
-    def JDK_17_HOME = tool name: 'openjdk-jdk17-latest', type: 'jdk'
-    def JDK_8_HOME = tool name: 'oracle-jdk8-latest', type: 'jdk'
-
-    def ZX_BRANCH_MODULES = ',:jersey-jetty-connector,:jersey-container-jetty-http,:jersey-container-jetty-servlet,:jersey-test-framework-provider-jetty,:jersey-test-framework-core,:jersey-container-servlet-core'
-
-    env.JAVA_HOME = JDK_8_HOME
-    env.PATH = "${env.JAVA_HOME}/bin:${env.PATH}:${MVN_HOME}/bin"
-
-    if (RELEASE_BRANCH == '2.x') {
-        ZX_BRANCH_MODULES = ''
-    }
-
-    sh 'java -version'
-
-    stage('Fetch from git') {
-        git(branch: RELEASE_BRANCH, credentialsId: CREDENTIALS_ID, url: REPO)
-    }
-    stage('Prepare environment') {
-
-        dir(RELEASE_FOLDER) {
-            //# Check whether top level pom.xml contains SNAPSHOT version
-            if (!sh(returnStdout: true, script: "grep '<version>' pom.xml | grep 'SNAPSHOT'")?.trim()) {
-                error('-[ Missing SNAPSHOT version in POM! ]-------------------------------------------')
-            }
-
-            //# Compute release versions
-            def SNAPSHOT_VERSION = sh(returnStdout: true, script: 'mvn -q -Dexec.executable="echo" -Dexec.args=\'${project.version}\' --non-recursive exec:exec -Pstaging').trim()
-
-            if (!RELEASE_VERSION?.trim()) {
-                if (!SNAPSHOT_VERSION?.trim()) {
-                    error('-[ Missing required snapshot version number! ]----------------------------------')
-                } else {
-                    def versionTokens = SNAPSHOT_VERSION.split('-')
-                    RELEASE_VERSION = versionTokens[0]
-                }
-            }
-
-            if (!NEXT_VERSION?.trim()) {
-                def (MAJOR_VERSION, MINOR_VERSION) = RELEASE_VERSION.tokenize('.')
-                def NEXT_MINOR_VERSION = (MINOR_VERSION as Integer) + 1
-                NEXT_VERSION = MAJOR_VERSION + '.' + NEXT_MINOR_VERSION + '-SNAPSHOT'
-            }
-
-            RELEASE_TAG = RELEASE_VERSION
-            NEW_RELEASE_BRANCH = RELEASE_VERSION+'-BRANCH'
-
-            echo "Current version: ${SNAPSHOT_VERSION}"
-            echo "Release version: ${RELEASE_VERSION}"
-            echo "Next version:    ${NEXT_VERSION}"
-            echo "Release tag:     ${RELEASE_TAG}"
-            echo "Release branch:  ${NEW_RELEASE_BRANCH}"
-
-            if (!SNAPSHOT_VERSION?.trim() || !RELEASE_VERSION?.trim() || !NEXT_VERSION?.trim()) {
-                error '-[ Missing required version numbers! ]------------------------------------------'
-            }
-
-            if (DRY_RUN == 'true') {
-                echo '-[ Dry run turned on ]----------------------------------------------------------'
-                //TARGET = 'install'
-            } else {
-                DEPLOY_TARGET = ' deploy:deploy'
-            }
-            echo '-[ Configure git user ]--------------------------------------------------------'
-            sh "git config --local user.email \"${EMAIL}\""
-            sh "git config --local user.name \"$LOGIN\""
-
-        }
-
-    }
-    stage('Prepare GPG') {
-        withCredentials([file(credentialsId: SECRET_FILE_ID, variable: 'KEYRING')]) {
-            //# Workaround: GPG initialization
-            sh("gpg --batch --import ${KEYRING}")
-            sh '''
-                for fpr in $(gpg --list-keys --with-colons  | awk -F: '/fpr:/ {print $10}' | sort -u);
-                do
-                    echo -e "5\ny\n" |  gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
-                done
-                '''
-        }
-    }
-    stage('Prepare branch') {
-        echo '-[ Prepare branch ]-------------------------------------------------------------'
-
-        echo '-[ Switching to release branch ]-------------------------------------------------'
-        sh """
-        git checkout ${GIT_ORIGIN}/${RELEASE_BRANCH} && true
-        git reset --hard ${GIT_ORIGIN}/${RELEASE_BRANCH} && true
-        git checkout -B ${NEW_RELEASE_BRANCH}
-        """
-        echo '-[ Release tag cleanup ]--------------------------------------------------------'
-        def TAG_NAME = sh(returnStdout: true, script: "git tag | grep ${RELEASE_TAG} || true").trim()
-        if (RELEASE_TAG == TAG_NAME) {
-            if (OVERWRITE == 'true') {
-                echo "${RELEASE_TAG} tag already exists, deleting"
-                sshagent([CREDENTIALS_ID]) {
-                    sh "git push --delete origin ${RELEASE_TAG} && true"
-                }
-            } else {
-                error "${RELEASE_TAG} tag already exists"
-            }
-            //# Always delete local tag if exists
-            sh """
-            git tag --delete ${RELEASE_TAG} && true
-            """
-        }
-        sh '''
-        sed -i 's|<suppress files="generated" checks=".*"/>|<suppress files="generated" checks=".*"/><suppress files="unpacked-src" checks=".*"/>|g' etc/config/checkstyle-suppressions.xml
-        '''
-    }
-    stage('Check previous stagings') {
-        if (DRY_RUN == 'true') {
-            echo DRY_RUN + ' ------'
-        } else {
-            if (OVERWRITE == 'true') {
-                STAGING_PREV_NAME = sh(returnStdout: true,
-                        script: "mvn -B --non-recursive -Pstaging nexus-staging:rc-list | awk '/\\[INFO] $STAGING_NAME_PATTERN[ ]+CLOSED[ ]+$STAGING_DESC[ ]*\$/ {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'").trim()
-                echo 'Previously closed staging name: ' + STAGING_PREV_NAME
-            }
-
-            STAGING_OPEN_NAME = sh(returnStdout: true,
-                    script: "mvn -B --non-recursive -Pstaging nexus-staging:rc-list | awk  '/$STAGING_NAME_PATTERN OPEN / {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'").trim()
-
-            if (!STAGING_OPEN_NAME?.trim()) {
-                echo 'No currently open stagings'
-            } else {
-                echo 'Currently open redundand staging: ' + STAGING_OPEN_NAME + ', immediately closing'
-                sh """
-                    OPEN_STAGINGS=${STAGING_OPEN_NAME}
-                    mvn -B -q -Pstaging nexus-staging:rc-drop -DstagingRepositoryId=\${OPEN_STAGINGS}  
-                """
-            }
-        }
-    }
-    /*
-    stage('Open new staging') {
-        if (DRY_RUN == 'true') {
-            echo DRY_RUN + ' ------'
-        } else {
-            STAGING_NAME = sh(returnStdout: true,
-                script: "mvn -B --non-recursive -Pstaging -DstagingProfileId=${STAGING_PROFILE_ID} -DstagingDescription=${STAGING_DESC} nexus-staging:rc-open | awk  '/\\[INFO] Opened / {print \$3}'").trim()
-            echo 'New staging name: '+STAGING_NAME
-        }
-    }*/
-    stage("Build ${PROJECT_NAME}") {
-        echo env.JAVA_HOME
-        echo '-[ Run maven release ]---------------------------------------------------------'
-        echo '-[ Set Release version ]-------------------------------------------------------'
-        sh """
-        cd ${RELEASE_FOLDER}
-        mvn -B -V -Pstaging versions:set -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false
-        cd bom
-        mvn -B -V -Pstaging versions:set -DnewVersion=${RELEASE_VERSION} -DgenerateBackupPoms=false
-        cd ..
-        """
-        echo '-[ Update Copyright years ]----------------------------------------------------'
-        sh '''#!/bin/bash -e
-        
-            export CURRENT_YEAR=`date '+%Y'`
-            export SED_CMD_LINE='sed -i "s#, 20.. Oracle and/or its affiliates#, ${CURRENT_YEAR} Oracle and/or its affiliates#g"'
-
-            git status --porcelain --untracked-files=no > modified_pom.log
-            cp modified_pom.log list_of_poms.txt
-            sed -i "s| M |$SED_CMD_LINE |g" modified_pom.log
-            sed -i "s| M ||g" list_of_poms.txt
-
-            bash modified_pom.log
-
-            echo ${CURRENT_YEAR} current year
-
-            while IFS= read -r path_to_pom
-            do
-              export CP_YEAR=`grep -o 'Copyright (c) 20.. Oracle and/or its affiliates' ${path_to_pom} | awk '{print $3}'`
-              [[ -z ${CP_YEAR} ]] && CP_YEAR=${CURRENT_YEAR} || echo ${CP_YEAR}
-              [[ ${CP_YEAR} == ${CURRENT_YEAR} ]] || ( sed -i "s#Copyright (c) ${CP_YEAR} Oracle and/or its affiliates#Copyright (c) ${CP_YEAR}, ${CURRENT_YEAR} Oracle and/or its affiliates#g" ${path_to_pom} ; echo ${path_to_pom} )
-              unset CP_YEAR
-            done < "list_of_poms.txt"
-        '''
-        echo '-[ Run release build ]---------------------------------------------------------'
-        dir(RELEASE_FOLDER) {
-            env.JAVA_HOME = JDK_12_HOME
-            //
-            sh "mvn -am -Pstaging --projects  core-server,core-client,media/jaxb,inject/hk2,ext/wadl-doclet,core-common${ZX_BRANCH_MODULES} clean install -B -q -V -DskipTests"
-            if (RELEASE_BRANCH == '3.0') {
-                env.JAVA_HOME = JDK_17_HOME
-                sh "mvn clean install -B -q -V -DskipTests -am -Pstaging --projects :jersey-spring6,connectors/helidon-connector"
-            }
-            env.JAVA_HOME = JDK_8_HOME
-            sh "mvn -q -B -V -DskipTests -Ddoclint=none -Dadditionalparam='-Xdoclint:none' -Dcheckstyle.skip " +
-                    //" -DstagingDescription='${STAGING_DESC}' -DstagingRepositoryId='${STAGING_NAME}' "+
-                    " -Poss-release,staging -U -C ${TARGET} ${DEPLOY_TARGET}"
-
-            sh "mvn -Poss-release,staging --projects core-server,core-client,media/jaxb,inject/hk2,ext/wadl-doclet,core-common install gpg:sign ${DEPLOY_TARGET} -B -q -V -DskipTests"
-            if (RELEASE_BRANCH == '2.x') {
-                env.JAVA_HOME = JDK_11_HOME
-                sh "mvn -Poss-release,staging --projects connectors/helidon-connector install gpg:sign ${DEPLOY_TARGET} -B -q -V -DskipTests"
-            }
-        }
-    }
-    stage('Prepare release') {
-        sh '''
-        git checkout -- etc/config/checkstyle-suppressions.xml
-        '''
-        echo '-[ Perform release commit to git ]---------------------------------------------'
-        sh "git commit -a -m ${RELEASE_VERSION}"
-        sh "git tag -m ${RELEASE_TAG} -a ${RELEASE_TAG}"
-        echo '-[ Set next snapshot version ]-------------------------------------------------'
-        dir(RELEASE_FOLDER) {
-            sh """
-                mvn -B -Pstaging versions:set -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false 
-                cd bom
-                mvn -B -Pstaging versions:set -DnewVersion=${NEXT_VERSION} -DgenerateBackupPoms=false
-                cd ..
-            """
-        }
-        echo '-[ Perform commit to git ]-----------------------------------------------------'
-        sh "git commit -a -m ${NEXT_VERSION}"
-    }
-    stage('Publish release') {
-        if (DRY_RUN == 'true') {
-            echo '-[ Prepared branch ]----------------------------------------------------------'
-            sh "git branch --list ${NEW_RELEASE_BRANCH}"
-            echo '-[ Prepared tag ]-------------------------------------------------------------'
-            sh "git tag --list ${NEW_RELEASE_BRANCH}"
-            echo '-[ Prepared commits ]---------------------------------------------------------'
-            sh 'git log -n 5'
-            sshagent([CREDENTIALS_ID]) {
-                sh "git push ${GIT_ORIGIN} ${NEW_RELEASE_BRANCH} --dry-run"
-            }
-            return
-        } else {
-            sshagent([CREDENTIALS_ID]) {
-                sh "git push -f ${GIT_ORIGIN} ${NEW_RELEASE_BRANCH} --follow-tags"
-            }
-        }
-    }
-    stage('Find related staging') {
-        if (DRY_RUN != 'true') {
-            if (!STAGING_NAME?.trim()) {
-                try {
-                    STAGING_NAME =
-                            sh(returnStdout: true,
-                                    script: "mvn -B --non-recursive -Pstaging nexus-staging:rc-list | awk  '/$STAGING_NAME_PATTERN OPEN / {if(a){a = \$2\",\"a} else{a = \$2}}END{print a}'"
-                            ).trim()
-                } catch (Error err) {
-                    currentBuild.result = 'UNSTABLE'
-                }
-            }
-            echo 'Staging name: ' + STAGING_NAME
-        } else {
-            echo 'DRY_RUN'
-        }
-    }
-    stage('Close released staging') {
-        if (!STAGING_NAME?.trim()) {
-            echo 'Nothing to be closed'
-        } else {
-            sh("mvn -B -q -Pstaging nexus-staging:rc-close -DstagingRepositoryId=${STAGING_NAME} -DstagingDescription='${STAGING_DESC}'")
-        }
-    }
-    stage('Drop redundant staging') {
-        if (!STAGING_PREV_NAME?.trim()) {
-            echo 'Nothing to be dropped'
-        } else {
-            try {
-                sh("""
-                OPEN_STAGINGS=${STAGING_PREV_NAME}
-                mvn -B -q -Pstaging nexus-staging:rc-drop -DstagingRepositoryId=\${OPEN_STAGINGS}
-                """)
-            } catch (Error err) {
-                currentBuild.result = 'UNSTABLE'
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/etc/scripts/release/Release-After/list-closed-stagings.sh b/etc/scripts/release/Release-After/list-closed-stagings.sh
deleted file mode 100644
index d5f32ca..0000000
--- a/etc/scripts/release/Release-After/list-closed-stagings.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for listing staging from the staging repo.
-#
-# Input Parameters:
-#     ----none----
-# Configuration:
-#
-# JDK:
-#       (System)
-# Git:
-#     ----none----
-#
-#
-
-cat <<EOT >> pom.xml
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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
-
--->
-
-<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/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.eclipse.ee4j</groupId>
-        <artifactId>project</artifactId>
-        <version>1.0.9</version>
-        <relativePath/>
-    </parent>
-
-    <groupId>org.glassfish.jersey</groupId>
-    <artifactId>release-helper-util</artifactId>
-    <version>1.0.1-SNAPSHOT</version>
-    <packaging>pom</packaging>
-
-    <name>Jersey Release Helper</name>
-
-    <description>Generated POM for Jersey Release Helper utils</description>
-    <url>https://projects.eclipse.org/projects/ee4j.jersey</url>
-
-    <scm>
-      <connection>scm:git:git://github.com/eclipse-ee4j/jersey</connection>
-      <developerConnection>scm:git:git://github.com/eclipse-ee4j/jersey</developerConnection>
-      <url>https://github.com/eclipse-ee4j/jersey</url>
-    </scm>
-
-</project>
-EOT
-
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-export STAGING_PARAMS='-DnexusUrl=https://jakarta.oss.sonatype.org/ -DserverId=ossrh'
-export STAGING_PLUGIN='org.sonatype.plugins:nexus-staging-maven-plugin:1.6.7'
-
-
-mvn -B ${STAGING_PARAMS} ${STAGING_PLUGIN}:rc-list | grep orgglassfishjersey > closed_stagings.txt || true
-
-
-#
-#
-# Archive the artifacts:
-#      closed_stagings.txt
-#
diff --git a/etc/scripts/release/Release-After/populate-documentation.sh b/etc/scripts/release/Release-After/populate-documentation.sh
deleted file mode 100644
index 025e512..0000000
--- a/etc/scripts/release/Release-After/populate-documentation.sh
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/bin/bash -lex
-#
-# 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
-#
-
-#
-# script for api docs publishing. Publishes api docs from the bundle in the Maven Central to the project's site.
-#
-# Input Parameters:
-#   RELEASE_VERSION    - type: String
-#                      - example: 3.1.6
-#                      - description: version for which project info is being published
-#   DRY_RUN            - type: Boolean
-#                      - description: If checked nothing is being published/generated
-#   WEBSITE_URL        - type: String
-#                      - value: git@github.com:eclipse-ee4j/jersey.github.io.git
-#                      - description: GitHub url for the project info/apidocs repository.
-#                        Mandatory and changes only in exceptional cases
-#  BRANCH_SPECIFIER    - type: String
-#                      - example: 2.x
-#                      - description: Branch for which the api docs are being published. Used only in Git commit message
-#  UPDATE_LATEST       - type: Boolean
-#                      - description: If checked updates the latest api docs (distinguishes for EE8/EE9/EE10) along
-#                        with publication into the RELEASE_VERSION folder.
-# Configuration:
-#
-# JDK:
-#       oracle-jdk8-latest
-# Git:
-#       ----none----
-#
-# SSH agent:
-#    GitHub bot SSH
-#
-#
-#
-
-
-#
-# The first shell execution
-#
-
-
-TOOLS_PREFIX=/opt/tools
-#JAVA_PREFIX=/opt/tools/java/oracle
-MVN_HOME=/opt/tools/apache-maven/latest
-#JAVA_HOME=/opt/tools/java/oracle/jdk-8/latest
-PATH=/opt/tools/apache-maven/latest/bin:${JAVA_HOME}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-
-export CENTRAL_URL='https://repo1.maven.org/maven2'
-export STAGING_URL='https://jakarta.oss.sonatype.org/content/repositories/staging'
-
-# !!! if build docbook it's essentially important to turn the pre-release profile ON !!!
-#mvn clean install -Pstaging,pre-release -DskipTests  -V -q -e -U -B -f docs/pom.xml -Djersey.version=$RELEASE_VERSION
-# however we download already published docbook from staging/central:
-mkdir -p $WORKSPACE/docs/target/docbook/index
-cd $WORKSPACE/docs/target/docbook/index
-wget -nv ${STAGING_URL}/org/glassfish/jersey/jersey-documentation/${RELEASE_VERSION}/jersey-documentation-${RELEASE_VERSION}-docbook.zip
-unzip -o jersey-documentation-${RELEASE_VERSION}-docbook.zip
-rm jersey-documentation-${RELEASE_VERSION}-docbook.zip
-
-mkdir -p $WORKSPACE/target/site/apidocs
-cd $WORKSPACE/target/site/apidocs
-wget -nv ${STAGING_URL}/org/glassfish/jersey/bundles/apidocs/${RELEASE_VERSION}/apidocs-${RELEASE_VERSION}-javadoc.jar -O apidocs-javadoc.jar
-jar -xf apidocs-javadoc.jar
-rm apidocs-javadoc.jar
-rm -rf META-INF
-
-
-#
-# The second shell execution
-#
-
-
-#!/bin/bash -lex
-
-TOOLS_PREFIX=/opt/tools
-#JAVA_PREFIX=/opt/tools/java/oracle
-MVN_HOME=/opt/tools/apache-maven/latest
-#JAVA_HOME=/opt/tools/java/oracle/jdk-8/latest
-PATH=/opt/tools/apache-maven/latest/bin:${JAVA_HOME}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-
-DIRS="$RELEASE_VERSION"
-if $UPDATE_LATEST;
-then
-	if [[ $RELEASE_VERSION == 2* ]] ;
-    then
-    	export DIRS="latest $DIRS"
-    elif [[ $RELEASE_VERSION == 3.1* ]] ;
-    then
-    	export DIRS="latest31x $DIRS"
-    else
-    	export DIRS="latest30x $DIRS"
-    fi
-    echo ${DIRS} for ${RELEASE_VERSION} release
-fi
-
-#export PATH=/opt/csw/bin:$PATH
-WEB_DIR=$WORKSPACE/target/jersey-web
-
-
-function copyDocs {
-    APIDOCS_DIR=$WEB_DIR/apidocs/$1
-    DOCS_DIR=$WEB_DIR/documentation/$1
-
-    #
-    # API docs
-    #
-    if test ! -e $APIDOCS_DIR ; then
-        mkdir -p $APIDOCS_DIR
-    fi
-    cd $APIDOCS_DIR
-
-    rm -rf jersey || true
-    cp -R $WORKSPACE/target/site/apidocs ./jersey
-
-    #
-    # user guide
-    #
-    rm -rf $DOCS_DIR || true
-    mkdir -p $DOCS_DIR
-    cp -r $WORKSPACE/docs/target/docbook/index/* $DOCS_DIR
-    rm $DOCS_DIR/*.fo || true
-}
-
-if test -e $WEB_DIR ; then
-    rm -rf $WEB_DIR
-fi
-
-# would couse shallow reject: git clone --depth 1 $WEBSITE_URL $WEB_DIR
-git clone $WEBSITE_URL $WEB_DIR
-
-cd $WEB_DIR
-
-for dir in $DIRS; do
-    copyDocs $dir
-done
-
-cd $WEB_DIR
-
-git config --local user.email "jersey-bot@eclipse.org"
-git config --local user.name "jersey-bot"
-git add -A .
-git diff --cached --exit-code || git commit -m "[jenkins] automatic javadoc and documentation update [$RELEASE_VERSION @ $BRANCH_SPECIFIER]"
-
-if [ "$DRY_RUN" = "false" ]; then
-  echo "Pushing Web sources to $WEBSITE_URL"
-  git push origin master
-else
-  echo "Dry run .. not pushing to the master"
-  git push origin master --dry-run
-fi
-
-
diff --git a/etc/scripts/release/Release-After/publish-release-notes.sh b/etc/scripts/release/Release-After/publish-release-notes.sh
deleted file mode 100644
index d547134..0000000
--- a/etc/scripts/release/Release-After/publish-release-notes.sh
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for publishing listed stagings from the staging repo into the Maven Central.
-#
-# Input Parameters:
-#   VERSION            - type: String
-#                      - example: 3.1.6
-#                      - description: version for which release notes are being published
-#   DRY_RUN            - type: Boolean
-#                      - description: If checked nothing is being published/generated
-#   PUBLISH_TO_GITHUB  - type: Boolean
-#                      - description: If checked generated notes are propagated to GitHub
-# Configuration:
-#
-# JDK:
-#       oracle-jdk8-latest
-# Git:
-#     https://github.com/eclipse-ee4j/jersey
-#
-# Bindings:
-#    Username and password (separated):
-#       Username Variable:
-#          BOT_NAME
-#       Password Variable:
-#          BOT_PASSWORD
-#       Credentials:
-#          GitHub bot (username/token)
-#
-#
-#
-
-
-cat <<EOT >> pom.xml
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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
-
--->
-
-<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/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.eclipse.ee4j</groupId>
-        <artifactId>project</artifactId>
-        <version>1.0.9</version>
-        <relativePath/>
-    </parent>
-
-    <groupId>org.glassfish.jersey</groupId>
-    <artifactId>release-helper-util</artifactId>
-    <version>1.0.1-SNAPSHOT</version>
-    <packaging>pom</packaging>
-
-    <name>Jersey Release Helper</name>
-
-    <description>Generated POM for Jersey Release Helper utils</description>
-    <url>https://projects.eclipse.org/projects/ee4j.jersey</url>
-
-    <scm>
-      <connection>scm:git:git://github.com/eclipse-ee4j/jersey</connection>
-      <developerConnection>scm:git:git://github.com/eclipse-ee4j/jersey</developerConnection>
-      <url>https://github.com/eclipse-ee4j/jersey</url>
-    </scm>
-
-</project>
-EOT
-
-# Execution environment
-readonly MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-readonly RELEASE_DATE=`date -I`
-
-mkdir -p target
-
-mvn -B -V org.glassfish.jersey.tools.plugins:jersey-release-notes-maven-plugin:1.0.1:release-notes -DskipTests \
--DreleaseVersion=${VERSION} -DgithubLogin=${BOT_NAME} -DgithubPassword=${BOT_PASSWORD} \
--DtemplateFilePath=release-note.html -DreleaseDate=${RELEASE_DATE} \
--DdryRun=${DRY_RUN} -DpublishToGithub=${PUBLISH_TO_GITHUB}
-
-cp -a `pwd`/target/release-notes ${WORKSPACE}
\ No newline at end of file
diff --git a/etc/scripts/release/Release-After/release-note.html b/etc/scripts/release/Release-After/release-note.html
deleted file mode 100644
index f0e5996..0000000
--- a/etc/scripts/release/Release-After/release-note.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<html>
-<!--
-
-    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
-
--->
-<head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
-    <meta name="google-site-verification" content="OiKukTHVW4bdQqx8Fq0zA2EZ_hI6-yYL-MvkCxBxaFs" />
-    <title>Release Notes - Jersey @LATEST_VERSION@</title>
-</head>
-
-<body>
-
-<h1>Release Notes - <a href="/">Jersey</a> @LATEST_VERSION@</h1>
-
-Release date: <strong>@RELEASE_DATE@</strong>
-
-<h2>Previous releases</h2>
-
-<ul>
-    <li><a href="2.29.1.html">Jersey 2.29.1 Release Notes</a></li>
-    <li><a href="2.29.html">Jersey 2.29 Release Notes</a></li>
-    <li><a href="2.28.html">Jersey 2.28 Release Notes</a></li>
-    <li><a href="2.25.1.html">Jersey 2.25.1 Release Notes</a></li>
-    <li><a href="2.25.html">Jersey 2.25 Release Notes</a></li>
-    <li><a href="2.24.1.html">Jersey 2.24.1 Release Notes</a></li>
-    <li><a href="2.24.html">Jersey 2.24 Release Notes</a></li>
-    <li><a href="2.23.2.html">Jersey 2.23.2 Release Notes</a></li>
-    <li><a href="2.23.1.html">Jersey 2.23.1 Release Notes</a></li>
-    <li><a href="2.23.html">Jersey 2.23 Release Notes</a></li>
-    <li><a href="2.22.2.html">Jersey 2.22.2 Release Notes</a></li>
-    <li><a href="2.22.1.html">Jersey 2.22.1 Release Notes</a></li>
-    <li><a href="2.22.html">Jersey 2.22 Release Notes</a></li>
-    <li><a href="2.21.1.html">Jersey 2.21.1 Release Notes</a></li>
-    <li><a href="2.21.html">Jersey 2.21 Release Notes</a></li>
-    <li><a href="2.20.html">Jersey 2.20 Release Notes</a></li>
-    <li><a href="2.19.html">Jersey 2.19 Release Notes</a></li>
-    <li><a href="2.18.html">Jersey 2.18 Release Notes</a></li>
-    <li><a href="2.17.html">Jersey 2.17 Release Notes</a></li>
-    <li><a href="2.16.html">Jersey 2.16 Release Notes</a></li>
-    <li><a href="2.14.html">Jersey 2.14 Release Notes</a></li>
-    <li><a href="2.13.html">Jersey 2.13 Release Notes</a></li>
-    <li><a href="2.12.html">Jersey 2.12 Release Notes</a></li>
-    <li><a href="2.11.html">Jersey 2.11 Release Notes</a></li>
-    <li><a href="2.10.1.html">Jersey 2.10.1 Release Notes</a></li>
-    <li><a href="2.10.html">Jersey 2.10 Release Notes</a></li>
-    <li><a href="2.9.1.html">Jersey 2.9.1 Release Notes</a></li>
-    <li><a href="2.9.html">Jersey 2.9 Release Notes</a></li>
-    <li><a href="2.8.html">Jersey 2.8 Release Notes</a></li>
-    <li><a href="2.7.html">Jersey 2.7 Release Notes</a></li>
-    <li><a href="2.6.html">Jersey 2.6 Release Notes</a></li>
-    <li><a href="2.5.1.html">Jersey 2.5.1 Release Notes</a></li>
-    <li><a href="2.5.html">Jersey 2.5 Release Notes</a></li>
-    <li><a href="2.4.1.html">Jersey 2.4.1 Release Notes</a></li>
-    <li><a href="2.4.html">Jersey 2.4 Release Notes</a></li>
-    <li><a href="2.3.1.html">Jersey 2.3.1 Release Notes</a></li>
-    <li><a href="2.3.html">Jersey 2.3 Release Notes</a></li>
-    <li><a href="2.2.html">Jersey 2.2 Release Notes</a></li>
-    <li><a href="2.1.html">Jersey 2.1 Release Notes</a></li>
-    <li><a href="2.0.html">Jersey 2.0 Release Notes</a></li>
-</ul>
-
-</body>
-</html>
diff --git a/etc/scripts/release/Release-After/release-project-info.sh b/etc/scripts/release/Release-After/release-project-info.sh
deleted file mode 100644
index ebfe9b1..0000000
--- a/etc/scripts/release/Release-After/release-project-info.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/bash -lex
-#
-# 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
-#
-
-#
-# script for project info publishing. MUST BE RUN ONLY AFTER THE APIDOCS PUBLISHING.
-#
-# Input Parameters:
-#   RELEASE_VERSION    - type: String
-#                      - example: 3.1.6
-#                      - description: version for which project info is being published
-#   DRY_RUN            - type: Boolean
-#                      - description: If checked nothing is being published/generated
-#   WEBSITE_URL        - type: String
-#                      - value: git@github.com:eclipse-ee4j/jersey.github.io.git
-#                      - description: GitHub url for the project info/apidocs repository.
-#                        Mandatory and changes only in exceptional cases
-# Configuration:
-#
-# JDK:
-#       openjdk-jdk11-latest
-# Git:
-#       https://github.com/eclipse-ee4j/jersey
-#
-#   Branches to build:
-#       tags/${RELEASE_VERSION}
-#
-# SSH agent:
-#    GitHub bot SSH
-#
-#
-#
-
-
-#
-# The first shell execution
-#
-
-MVN_HOME=/opt/tools/apache-maven/latest
-PATH=${PATH}:${MVN_HOME}/bin:${JAVA_HOME}/bin
-
-mvn clean install -B -V -q -PtestsSkip,checkstyleSkip -Dtests.excluded -DskipTests '-Dmaven.test.skip=true'
-
-mvn -B -V -q -Pproject-info,checkstyleSkip,testsSkip,findbugsSkip,staging site site:stage \
-     -DgenerateProjectInfo=true -Dtests.excluded -Ddependency.locations.enabled=false \
-     -Dmaven.jxr.skip=true -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -DskipTests \
-     -Dfindbugs.skip=true
-
-#
-# The second shell execution
-#
-
-#!/bin/bash -lex
-
-export PATH=/opt/csw/bin:$PATH
-WEB_DIR=$WORKSPACE/target/jersey-web
-PROJECT_INFO_DIR=$WEB_DIR/project-info/$RELEASE_VERSION
-
-if test -e $WEB_DIR ; then
-    rm -rf $WEB_DIR
-fi
-
-# would couse shallow reject: git clone --depth 1 $WEBSITE_SOURCE_URL $WEB_DIR
-git clone $WEBSITE_URL $WEB_DIR
-cd $WEB_DIR
-
-if test ! -e $PROJECT_INFO_DIR ; then
-    mkdir -p $PROJECT_INFO_DIR
-fi
-
-cd $PROJECT_INFO_DIR
-
-rm -rf jersey || true
-cp -R $WORKSPACE/target/staging ./jersey
-
-cd $WEB_DIR
-
-git config --local user.email "jersey-bot@eclipse.org"
-git config --local user.name "jersey-bot"
-git add -A .
-#git diff --cached --exit-code ||
-git commit -m "[jenkins] automatic project-info update [$RELEASE_VERSION]"
-
-if [ "$DRY_RUN" = "false" ]; then
-  echo Pushing Web sources to $WEBSITE_URL
-  git push origin master
-else
-  echo "Dry run .. not pushing to the master"
-  git push origin master --dry-run
-fi
\ No newline at end of file
diff --git a/etc/scripts/release/Release-After/release-staging-to-central.sh b/etc/scripts/release/Release-After/release-staging-to-central.sh
deleted file mode 100644
index b470730..0000000
--- a/etc/scripts/release/Release-After/release-staging-to-central.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/bash
-#
-# 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
-#
-
-#
-# script for publishing listed stagings from the staging repo into the Maven Central.
-#
-# Input Parameters:
-#     STAGING_REPO_ID  - type: String
-#                      - example: orgglassfishjersey-1226,orgglassfishjersey-1227,orgglassfishjersey-1228,orgglassfishjersey-1229,orgglassfishjersey-1230
-#                      - description: list all staggings (comma separated) to be published to the Maven Central
-#     STAGING_DESC     - type: String
-#                      - example:org.glassfish.jersey:2.42
-#                      - description: description of what is published. Usually <group.id>:<version>
-# Configuration:
-#
-# JDK:
-#       (System)
-# Git:
-#     ----none----
-#
-#
-
-cat <<EOT >> pom.xml
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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
-
--->
-
-<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/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.eclipse.ee4j</groupId>
-        <artifactId>project</artifactId>
-        <version>1.0.9</version>
-        <relativePath/>
-    </parent>
-
-    <groupId>org.glassfish.jersey</groupId>
-    <artifactId>release-helper-util</artifactId>
-    <version>1.0.1-SNAPSHOT</version>
-    <packaging>pom</packaging>
-
-    <name>Jersey Release Helper</name>
-
-    <description>Generated POM for Jersey Release Helper utils</description>
-    <url>https://projects.eclipse.org/projects/ee4j.jersey</url>
-
-    <scm>
-      <connection>scm:git:git://github.com/eclipse-ee4j/jersey</connection>
-      <developerConnection>scm:git:git://github.com/eclipse-ee4j/jersey</developerConnection>
-      <url>https://github.com/eclipse-ee4j/jersey</url>
-    </scm>
-
-</project>
-EOT
-
-MVN_HOME="/opt/tools/apache-maven/latest/"
-PATH="${MVN_HOME}/bin:${JAVA_HOME}:/bin:${PATH}"
-
-export STAGING_PARAMS='-DnexusUrl=https://jakarta.oss.sonatype.org/ -DserverId=ossrh'
-export STAGING_PLUGIN='org.sonatype.plugins:nexus-staging-maven-plugin:1.6.7'
-
-
-mvn ${STAGING_PARAMS} -B -C -V ${STAGING_PLUGIN}:rc-release -DstagingRepositoryId="${STAGING_REPO_ID}" -DstagingDescription="${STAGING_DESC}"
-
diff --git a/etc/scripts/validation/dependency-convergence.sh b/etc/scripts/validation/dependency-convergence.sh
index 92ffeea..9bcf4fe 100755
--- a/etc/scripts/validation/dependency-convergence.sh
+++ b/etc/scripts/validation/dependency-convergence.sh
@@ -40,5 +40,11 @@
 #run validation
 mvn ${MVN_ARGS} ${MVN_CLI} -f ${CURRENT_LOCATION}/${VALIDATION_POM} -Djersey.version=${JERSEY_VERSION}
 
+#save exit status
+export MAVEN_BUILD_RESULT=$?
+
 #clean the mess
-rm ${CURRENT_LOCATION}/${TEMP_FILE}
\ No newline at end of file
+rm ${CURRENT_LOCATION}/${TEMP_FILE}
+
+#exit with saved exit stateus
+exit $MAVEN_BUILD_RESULT
diff --git a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyTags.java b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyTags.java
index d723c7c..29494f4 100644
--- a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyTags.java
+++ b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyTags.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
@@ -43,6 +43,8 @@
 
     private static final Tag URI_ROOT = Tag.of("uri", "root");
 
+    private static final Tag URI_UNKNOWN = Tag.of("uri", "UNKNOWN");
+
     private static final Tag EXCEPTION_NONE = Tag.of("exception", "None");
 
     private static final Tag STATUS_SERVER_ERROR = Tag.of("status", "500");
@@ -95,7 +97,10 @@
             }
         }
         String matchingPattern = getMatchingPattern(event);
-        if (matchingPattern.equals("/")) {
+        if (matchingPattern == null) {
+            return URI_UNKNOWN;
+        }
+        else if (matchingPattern.equals("/")) {
             return URI_ROOT;
         }
         return Tag.of("uri", matchingPattern);
@@ -108,7 +113,9 @@
     static String getMatchingPattern(RequestEvent event) {
         ExtendedUriInfo uriInfo = event.getUriInfo();
         List<UriTemplate> templates = uriInfo.getMatchedTemplates();
-
+        if (templates.isEmpty()) {
+            return null;
+        }
         StringBuilder sb = new StringBuilder();
         sb.append(uriInfo.getBaseUri().getPath());
         for (int i = templates.size() - 1; i >= 0; i--) {
diff --git a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListener.java b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListener.java
index cca1d13..0b05442 100644
--- a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListener.java
+++ b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListener.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
@@ -79,7 +79,7 @@
 
         switch (event.getType()) {
             case ON_EXCEPTION:
-                if (!isNotFoundException(event)) {
+                if (!isClientError(event)) {
                     break;
                 }
                 time(event, containerRequest);
@@ -122,13 +122,14 @@
         }
     }
 
-    private boolean isNotFoundException(RequestEvent event) {
+    private boolean isClientError(RequestEvent event) {
         Throwable t = event.getException();
         if (t == null) {
             return false;
         }
-        String className = t.getClass().getCanonicalName();
-        return className.equals("jakarta.ws.rs.NotFoundException") || className.equals("jakarta.ws.rs.NotFoundException");
+        String className = t.getClass().getSuperclass().getCanonicalName();
+        return className.equals("jakarta.ws.rs.ClientErrorException")
+                || className.equals("javax.ws.rs.ClientErrorException");
     }
 
     private Set<Timer> shortTimers(Set<Timed> timed, RequestEvent event) {
diff --git a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/DefaultJerseyTagsProviderTest.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/DefaultJerseyTagsProviderTest.java
index d0445f9..93a9e4d 100644
--- a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/DefaultJerseyTagsProviderTest.java
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/DefaultJerseyTagsProviderTest.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
@@ -51,7 +51,7 @@
 
     @Test
     void testRootPath() {
-        assertThat(tagsProvider.httpRequestTags(event(200, null, "/", (String[]) null)))
+        assertThat(tagsProvider.httpRequestTags(event(200, null, "/", "/")))
             .containsExactlyInAnyOrder(tagsFrom("root", 200, null, "SUCCESS"));
     }
 
@@ -86,21 +86,21 @@
     @Test
     @SuppressWarnings("serial")
     void exceptionsAreMappedCorrectly() {
-        assertThat(tagsProvider.httpRequestTags(event(500, new IllegalArgumentException(), "/app", (String[]) null)))
+        assertThat(tagsProvider.httpRequestTags(event(500, new IllegalArgumentException(), "/app", "/")))
             .containsExactlyInAnyOrder(tagsFrom("/app", 500, "IllegalArgumentException", "SERVER_ERROR"));
         assertThat(tagsProvider.httpRequestTags(
-                event(500, new IllegalArgumentException(new NullPointerException()), "/app", (String[]) null)))
+                event(500, new IllegalArgumentException(new NullPointerException()), "/app", "/")))
             .containsExactlyInAnyOrder(tagsFrom("/app", 500, "NullPointerException", "SERVER_ERROR"));
-        assertThat(tagsProvider.httpRequestTags(event(406, new NotAcceptableException(), "/app", (String[]) null)))
+        assertThat(tagsProvider.httpRequestTags(event(406, new NotAcceptableException(), "/app", "/")))
             .containsExactlyInAnyOrder(tagsFrom("/app", 406, "NotAcceptableException", "CLIENT_ERROR"));
         assertThat(tagsProvider.httpRequestTags(event(500, new Exception("anonymous") {
-        }, "/app", (String[]) null))).containsExactlyInAnyOrder(tagsFrom("/app", 500,
+        }, "/app", "/"))).containsExactlyInAnyOrder(tagsFrom("/app", 500,
                 "org.glassfish.jersey.micrometer.server.DefaultJerseyTagsProviderTest$1", "SERVER_ERROR"));
     }
 
     @Test
     void longRequestTags() {
-        assertThat(tagsProvider.httpLongRequestTags(event(0, null, "/app", (String[]) null)))
+        assertThat(tagsProvider.httpLongRequestTags(event(0, null, "/app", "/")))
             .containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/app"));
     }
 
diff --git a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListenerTest.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListenerTest.java
index 96324b2..ce2bc4a 100644
--- a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListenerTest.java
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/MetricsRequestEventListenerTest.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
@@ -20,6 +20,7 @@
 
 import jakarta.ws.rs.NotFoundException;
 import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
@@ -149,6 +150,11 @@
         }
         catch (Exception ignored) {
         }
+        try {
+            target("produces-text-plain").request(MediaType.APPLICATION_JSON).get();
+        }
+        catch (Exception ignored) {
+        }
 
         assertThat(registry.get(METRIC_NAME)
             .tags(tagsFrom("/throws-exception", "500", "SERVER_ERROR", "IllegalArgumentException"))
@@ -164,6 +170,11 @@
             .tags(tagsFrom("/throws-mappable-exception", "410", "CLIENT_ERROR", "ResourceGoneException"))
             .timer()
             .count()).isEqualTo(1);
+
+        assertThat(registry.get(METRIC_NAME)
+                       .tags(tagsFrom("UNKNOWN", "406", "CLIENT_ERROR", "NotAcceptableException"))
+                       .timer()
+                       .count()).isEqualTo(1);
     }
 
     private static Iterable<Tag> tagsFrom(String uri, String status, String outcome, String exception) {
diff --git a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/resources/TestResource.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/resources/TestResource.java
index 41e529d..36abeb2 100644
--- a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/resources/TestResource.java
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/resources/TestResource.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
@@ -90,6 +90,13 @@
     }
 
     @GET
+    @Path("produces-text-plain")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String producesTextPlain() {
+        return "hello";
+    }
+
+    @GET
     @Path("redirect/{status}")
     public Response redirect(@PathParam("status") int status) {
         if (status == 307) {
diff --git a/ext/mvc-thymeleaf/pom.xml b/ext/mvc-thymeleaf/pom.xml
new file mode 100644
index 0000000..181a53a
--- /dev/null
+++ b/ext/mvc-thymeleaf/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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
+
+-->
+
+<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.ext</groupId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-mvc-thymeleaf</artifactId>
+    <name>jersey-ext-mvc-thymeleaf</name>
+
+    <description>
+        Jersey extension module providing support for Thymeleaf templates.
+    </description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>org.glassfish.jersey.server.mvc.thymeleaf.*;version=${project.version}</Export-Package>
+                    </instructions>
+                    <unpackBundle>true</unpackBundle>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>${project.build.directory}/legal</directory>
+            </resource>
+        </resources>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <version>${servlet6.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.ext</groupId>
+            <artifactId>jersey-mvc</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.thymeleaf</groupId>
+            <artifactId>thymeleaf</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.javassist</groupId>
+                    <artifactId>javassist</artifactId>
+                </exclusion>
+            </exclusions>
+            <version>${thymeleaf.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.java
new file mode 100644
index 0000000..aba4aac
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.java
@@ -0,0 +1,23 @@
+/*
+ * 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.server.mvc.thymeleaf;
+
+import org.thymeleaf.TemplateEngine;
+
+public interface ThymeleafConfigurationFactory {
+    TemplateEngine getTemplateEngine();
+}
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafDefaultConfigurationFactory.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafDefaultConfigurationFactory.java
new file mode 100644
index 0000000..588c475
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafDefaultConfigurationFactory.java
@@ -0,0 +1,106 @@
+/*
+ * 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.server.mvc.thymeleaf;
+
+import jakarta.ws.rs.core.Configuration;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.messageresolver.IMessageResolver;
+import org.thymeleaf.messageresolver.StandardMessageResolver;
+import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+
+import java.util.Map;
+
+/**
+ * Handy {@link ThymeleafConfigurationFactory} that supplies a minimally
+ * configured {@link org.thymeleaf.TemplateEngine } able to
+ * render Thymeleaf templates.
+ * The recommended method to provide custom Thymeleaf engine settings is to
+ * sub-class this class, further customize the
+ * {@link org.thymeleaf.TemplateEngine settings} as desired in that
+ * class, and then register the sub-class with the {@link ThymeleafMvcFeature}
+ * TEMPLATE_OBJECT_FACTORY property.
+ *
+ * @author Dmytro Dovnar (dimonmc@gmail.com)
+ */
+public class ThymeleafDefaultConfigurationFactory implements ThymeleafConfigurationFactory {
+    private final Configuration config;
+    private final TemplateEngine templateEngine;
+
+    public ThymeleafDefaultConfigurationFactory(Configuration config) {
+        this.config = config;
+        this.templateEngine = initTemplateEngine();
+    }
+
+    @Override
+    public TemplateEngine getTemplateEngine() {
+        return templateEngine;
+    }
+
+    private ITemplateResolver getTemplateResolver() {
+        Map<String, Object> properties = config.getProperties();
+        String basePath = (String) PropertiesHelper.getValue(properties,
+                "jersey.config.server.mvc.templateBasePath" + ThymeleafMvcFeature.SUFFIX,
+                String.class, (Map) null);
+        if (basePath == null) {
+            basePath = (String) PropertiesHelper.getValue(properties,
+                    "jersey.config.server.mvc.templateBasePath", "", (Map) null);
+        }
+
+        if (basePath != null && !basePath.startsWith("/")) {
+            basePath = "/" + basePath;
+        }
+
+        String templateFileSuffix = (String) PropertiesHelper.getValue(properties,
+                "jersey.config.server.mvc.templateFileSuffix" + ThymeleafMvcFeature.SUFFIX,
+                ".html", (Map) null);
+
+        String templateFileMode = (String) PropertiesHelper.getValue(properties,
+                "jersey.config.server.mvc.templateMode" + ThymeleafMvcFeature.SUFFIX,
+                "HTML5", (Map) null);
+
+        Boolean cacheEnabled = (Boolean) PropertiesHelper.getValue(properties,
+                "jersey.config.server.mvc.caching" + ThymeleafMvcFeature.SUFFIX, Boolean.class, (Map) null);
+        if (cacheEnabled == null) {
+            cacheEnabled = (Boolean) PropertiesHelper.getValue(properties,
+                    "jersey.config.server.mvc.caching", false, (Map) null);
+        }
+
+        Long cacheLiveMs = (Long) PropertiesHelper.getValue(properties,
+                "jersey.config.server.mvc.cacheTTLMs" + ThymeleafMvcFeature.SUFFIX, 3600000L, (Map) null);
+
+        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
+        templateResolver.setPrefix(basePath);
+        templateResolver.setSuffix(templateFileSuffix);
+        templateResolver.setTemplateMode(templateFileMode);
+        templateResolver.setCacheTTLMs(cacheLiveMs);
+        templateResolver.setCacheable(cacheEnabled);
+        return templateResolver;
+    }
+
+    private TemplateEngine initTemplateEngine() {
+        TemplateEngine templateEngine = new TemplateEngine();
+        templateEngine.setTemplateResolver(getTemplateResolver());
+        return templateEngine;
+    }
+
+    private IMessageResolver getMessageResolver() {
+        StandardMessageResolver messageResolver = new StandardMessageResolver();
+        return messageResolver;
+    }
+}
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafMvcFeature.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafMvcFeature.java
new file mode 100644
index 0000000..b43b9a6
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafMvcFeature.java
@@ -0,0 +1,54 @@
+/*
+ * 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.server.mvc.thymeleaf;
+
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import org.glassfish.jersey.server.mvc.MvcFeature;
+
+@ConstrainedTo(RuntimeType.SERVER)
+public final class ThymeleafMvcFeature implements Feature {
+    public static final String SUFFIX = ".thymeleaf";
+    public static final String TEMPLATE_BASE_PATH = MvcFeature.TEMPLATE_BASE_PATH + SUFFIX;
+    public static final String CACHE_TEMPLATES = MvcFeature.CACHE_TEMPLATES + SUFFIX;
+    public static final String TEMPLATE_OBJECT_FACTORY = MvcFeature.TEMPLATE_OBJECT_FACTORY + SUFFIX;
+    public static final String ENCODING = MvcFeature.ENCODING + SUFFIX;
+
+    public static final String TEMPLATE_FILE_SUFFIX = "jersey.config.server.mvc.templateFileSuffix" + SUFFIX;
+    public static final String TEMPLATE_MODE = "jersey.config.server.mvc.templateMode" + SUFFIX;
+    public static final String CACHE_TTLMS = "jersey.config.server.mvc.cacheTTLMs" + SUFFIX;
+
+    @Override
+    public boolean configure(FeatureContext context) {
+        final Configuration config = context.getConfiguration();
+
+        if (!config.isRegistered(ThymeleafViewProcessor.class)) {
+            context.register(ThymeleafViewProcessor.class);
+
+            // MvcFeature.
+            if (!config.isRegistered(MvcFeature.class)) {
+                context.register(MvcFeature.class);
+            }
+
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafSuppliedConfigurationFactory.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafSuppliedConfigurationFactory.java
new file mode 100644
index 0000000..4f21ce1
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafSuppliedConfigurationFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.server.mvc.thymeleaf;
+
+import org.thymeleaf.TemplateEngine;
+
+/**
+ * {@link ThymeleafConfigurationFactory} that supplies an unchanged
+ * {@link ThymeleafConfigurationFactory Configuration} as passed-in to
+ * the constructor.
+ * <p/>
+ * Used to support backwards-compatibility in {@link ThymeleafViewProcessor}
+ * to wrap directly-configured {@link org.thymeleaf.TemplateEngine}
+ * objects instead of the recommended {@link ThymeleafDefaultConfigurationFactory}
+ * or a sub-class thereof.
+ *
+ * @author Dmytro Dovnar (dimonmc@gmail.com)
+ */
+public class ThymeleafSuppliedConfigurationFactory implements ThymeleafConfigurationFactory {
+    private final ThymeleafConfigurationFactory configurationFactory;
+
+    public ThymeleafSuppliedConfigurationFactory(ThymeleafConfigurationFactory configurationFactory) {
+        this.configurationFactory = configurationFactory;
+    }
+
+    @Override
+    public TemplateEngine getTemplateEngine() {
+        return configurationFactory.getTemplateEngine();
+    }
+
+}
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafViewProcessor.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafViewProcessor.java
new file mode 100644
index 0000000..fc8139c
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafViewProcessor.java
@@ -0,0 +1,104 @@
+/*
+ * 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.server.mvc.thymeleaf;
+
+import jakarta.inject.Inject;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.glassfish.jersey.server.mvc.Viewable;
+import org.glassfish.jersey.server.mvc.spi.AbstractTemplateProcessor;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * {@link org.glassfish.jersey.server.mvc.spi.TemplateProcessor Template processor} providing support for Thymeleaf templates.
+ *
+ * @author Dmytro Dovnar (dimonmc@gmail.com)
+ */
+public final class ThymeleafViewProcessor extends AbstractTemplateProcessor<TemplateEngine> {
+    private final ThymeleafConfigurationFactory factory;
+
+    /**
+     * Create an instance of this processor with injected {@link jakarta.ws.rs.core.Configuration config}.
+     *
+     * @param config           config to configure this processor from.
+     * @param injectionManager injection manager.
+     */
+    @Inject
+    public ThymeleafViewProcessor(Configuration config, InjectionManager injectionManager) {
+        super(config, injectionManager.getInstance(ServletContext.class), "thymeleaf", "html");
+        this.factory = getTemplateObjectFactory(injectionManager::createAndInitialize, ThymeleafConfigurationFactory.class,
+                () -> {
+                    ThymeleafConfigurationFactory configuration =
+                            getTemplateObjectFactory(
+                                    injectionManager::createAndInitialize,
+                                    ThymeleafConfigurationFactory.class, Values.empty());
+                    if (configuration == null) {
+                        return new ThymeleafDefaultConfigurationFactory(config);
+                    } else {
+                        return new ThymeleafSuppliedConfigurationFactory(configuration);
+                    }
+                });
+    }
+
+    @Override
+    protected TemplateEngine resolve(final String templatePath, final Reader reader) throws Exception {
+        return factory.getTemplateEngine();
+    }
+
+    @Override
+    public void writeTo(final TemplateEngine templateEngine, final Viewable viewable, final MediaType mediaType,
+                        final MultivaluedMap<String, Object> httpHeaders, final OutputStream out) throws IOException {
+        Context context = new Context();
+
+        Object model = viewable.getModel();
+        if (!(model instanceof Map)) {
+            context.setVariable("model", viewable.getModel());
+        } else {
+            context.setVariables((Map) viewable.getModel());
+        }
+
+        if (context.containsVariable("lang")) {
+            Object langValue = context.getVariable("lang");
+            if (langValue instanceof Locale) {
+                context.setLocale((Locale) langValue);
+            } else if (langValue instanceof String) {
+                Locale locale = Locale.forLanguageTag((String) langValue);
+                context.setLocale(locale);
+            }
+        }
+
+        Charset encoding = setContentType(mediaType, httpHeaders);
+
+        final Writer writer = new BufferedWriter(new OutputStreamWriter(out, encoding));
+        templateEngine.process(viewable.getTemplateName(), context, writer);
+    }
+}
diff --git a/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.java
new file mode 100644
index 0000000..d8cd7ae
--- /dev/null
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.java
@@ -0,0 +1,17 @@
+/*
+ * 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.server.mvc.thymeleaf;
diff --git a/ext/pom.xml b/ext/pom.xml
index 5257ff1..76629a4 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -50,6 +50,7 @@
         <module>mvc-freemarker</module>
         <module>mvc-jsp</module>
         <module>mvc-mustache</module>
+        <module>mvc-thymeleaf</module>
         <module>proxy-client</module>
         <module>rx</module>
         <module>spring6</module>
diff --git a/ext/spring6/pom.xml b/ext/spring6/pom.xml
index 70e9dc3..41e38f4 100644
--- a/ext/spring6/pom.xml
+++ b/ext/spring6/pom.xml
@@ -94,6 +94,18 @@
                     <artifactId>asm</artifactId>
                 </exclusion>
                 <exclusion>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm-util</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm-tree</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm-analysis</artifactId>
+                </exclusion>
+                <exclusion>
                     <groupId>jakarta.annotation</groupId>
                     <artifactId>jakarta.annotation-api</artifactId>
                 </exclusion>
diff --git a/ext/spring6/src/main/java17/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java b/ext/spring6/src/main/java17/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java
index a489695..11f7984 100644
--- a/ext/spring6/src/main/java17/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java
+++ b/ext/spring6/src/main/java17/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022 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
@@ -98,7 +98,9 @@
                 final AbstractRequestAttributes attributes =
                         (AbstractRequestAttributes) requestContext.getProperty(REQUEST_ATTRIBUTES_PROPERTY);
                 RequestContextHolder.resetRequestAttributes();
-                attributes.requestCompleted();
+                if (attributes != null) {
+                    attributes.requestCompleted();
+                }
             }
         } : EMPTY_ATTRIBUTE_CONTROLLER;
     }
diff --git a/ext/spring6/src/test/java/org/glassfish/jersey/server/spring/filter/SpringRequestContextFilterTest.java b/ext/spring6/src/test/java/org/glassfish/jersey/server/spring/filter/SpringRequestContextFilterTest.java
new file mode 100644
index 0000000..3e08125
--- /dev/null
+++ b/ext/spring6/src/test/java/org/glassfish/jersey/server/spring/filter/SpringRequestContextFilterTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.server.spring.filter;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.WebApplicationContext;
+
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public class SpringRequestContextFilterTest {
+    @Test
+    public void testMissingAttributes() throws IOException {
+        WebApplicationContext webAppCtx = (WebApplicationContext) Proxy.newProxyInstance(
+                WebApplicationContext.class.getClassLoader(),
+                new Class[]{WebApplicationContext.class},
+                new InvocationHandler() {
+                    @Override
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        return null;
+                    }
+                });
+
+        InjectionManager injectionManager = Injections.createInjectionManager();
+        injectionManager.register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(webAppCtx).to(ApplicationContext.class);
+            }
+        });
+        injectionManager.completeRegistration();
+
+        ContainerRequestContext requestContext = (ContainerRequestContext) Proxy.newProxyInstance(
+                ContainerRequestContext.class.getClassLoader(),
+                new Class[]{ContainerRequestContext.class},
+                new InvocationHandler() {
+                    @Override
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        return null;
+                    }
+                });
+
+        RequestContextFilter filter = new RequestContextFilter(injectionManager);
+        filter.filter(requestContext, (ContainerResponseContext) null);
+    }
+}
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2BootstrapBinder.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2BootstrapBinder.java
index 7794aa6..f3fd9d7 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2BootstrapBinder.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2BootstrapBinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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,6 +43,10 @@
 
     @Override
     protected void configure() {
+        // Singletons, install once
+        if (serviceLocator.getService(RequestScope.class) != null) {
+            return;
+        }
         install(
                 // Jersey-like class analyzer that is able to choose the right services' constructor.
                 new JerseyClassAnalyzer.Binder(serviceLocator),
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Helper.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Helper.java
index 0f731f6..bf3c229 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Helper.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Helper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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,8 +20,10 @@
 import java.lang.reflect.Type;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
+import org.glassfish.hk2.api.Factory;
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.internal.inject.AliasBinding;
 import org.glassfish.jersey.internal.inject.Binding;
@@ -121,14 +123,25 @@
      * @param dc      HK2 Dynamic configuration to bind the object.
      * @param binding Jersey descriptor as a holder of information about an injection point.
      */
-    private static void bindBinding(ServiceLocator locator, DynamicConfiguration dc, Binding<?, ?> binding) {
+    private static <T> void bindBinding(ServiceLocator locator, DynamicConfiguration dc, Binding<T, ?> binding) {
         if (ClassBinding.class.isAssignableFrom(binding.getClass())) {
-            ActiveDescriptor<?> activeDescriptor = translateToActiveDescriptor((ClassBinding<?>) binding);
-            bindBinding(locator, dc, activeDescriptor, binding.getAliases());
+            final Class<?> implClass = binding.getImplementationType();
+            if (Factory.class.isAssignableFrom(implClass)) {
+                final Class<? extends Factory<T>> factoryClass = (Class<? extends Factory<T>>) implClass;
+                bindFactory(locator, binding, (binder) -> binder.bindFactory(factoryClass));
+            } else {
+                ActiveDescriptor<?> activeDescriptor = translateToActiveDescriptor((ClassBinding<?>) binding);
+                bindBinding(locator, dc, activeDescriptor, binding.getAliases());
+            }
 
         } else if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
-            ActiveDescriptor<?> activeDescriptor = translateToActiveDescriptor((InstanceBinding<?>) binding);
-            bindBinding(locator, dc, activeDescriptor, binding.getAliases());
+            if (Factory.class.isAssignableFrom(binding.getImplementationType())) {
+                final Factory<?> factory = (Factory) ((InstanceBinding<T>) binding).getService();
+                bindFactory(locator, binding, (binder) -> binder.bindFactory(factory));
+            } else {
+                ActiveDescriptor<?> activeDescriptor = translateToActiveDescriptor((InstanceBinding<?>) binding);
+                bindBinding(locator, dc, activeDescriptor, binding.getAliases());
+            }
 
         } else if (InjectionResolverBinding.class.isAssignableFrom(binding.getClass())) {
             InjectionResolverBinding resolverDescriptor = (InjectionResolverBinding) binding;
@@ -234,6 +247,13 @@
         ServiceLocatorUtilities.bind(locator, createBinder(bindConsumer));
     }
 
+    private static <T> void bindFactory(ServiceLocator locator,
+                                        Binding<T, ?> binding,
+                                        Function<AbstractBinder, ServiceBindingBuilder> builder) {
+        ServiceLocatorUtilities
+                .bind(locator, createBinder((binder) -> setupSupplierFactoryBridge(binding, builder.apply(binder))));
+    }
+
     private static void setupSupplierFactoryBridge(Binding<?, ?> binding, ServiceBindingBuilder<?> builder) {
         builder.named(binding.getName());
         binding.getContracts().forEach(builder::to);
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Registrables.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Registrables.java
new file mode 100644
index 0000000..6231f74
--- /dev/null
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2Registrables.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.inject.hk2;
+
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.innate.inject.spi.ExternalRegistrables;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Hk2Registrables implements ExternalRegistrables {
+    @Override
+    public List<ClassRuntimeTypePair> registrableContracts() {
+        List<ClassRuntimeTypePair> list = new ArrayList<>();
+        list.add(new ClassRuntimeTypePair(AbstractBinder.class, null));
+        return list;
+    }
+}
diff --git a/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.innate.inject.spi.ExternalRegistrables b/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.innate.inject.spi.ExternalRegistrables
new file mode 100644
index 0000000..6f7da1a
--- /dev/null
+++ b/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.innate.inject.spi.ExternalRegistrables
@@ -0,0 +1 @@
+org.glassfish.jersey.inject.hk2.Hk2Registrables
\ No newline at end of file
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 b11c121..d7b9f9c 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
@@ -31,6 +31,7 @@
 
 import java.lang.annotation.Annotation;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.logging.Logger;
 import jakarta.annotation.PostConstruct;
@@ -104,7 +105,13 @@
                         commonConfig.getRuntimeType(),
                         CommonProperties.JSON_JACKSON_ENABLED_MODULES, String.class);
 
-        final List<Module> modules = ObjectMapper.findModules();
+        final List<Module> modules;
+        try {
+            modules = ObjectMapper.findModules();
+        } catch (Throwable e) {
+            LOGGER.warning(LocalizationMessages.ERROR_MODULES_NOT_LOADED(e.getMessage()));
+            return Collections.emptyList();
+        }
         for (String exludeModuleName : EXCLUDE_MODULE_NAMES) {
             modules.removeIf(mod -> mod.getModuleName().contains(exludeModuleName));
         }
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 f8b59da..a9144fd 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 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
@@ -14,4 +14,5 @@
 # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 #
 
-error.jackson.streamreadconstraints=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.15?
\ No newline at end of file
+error.jackson.streamreadconstraints=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.15?
+error.modules.not.loaded=Jackson modules could not be loaded: {0}
\ No newline at end of file
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartProperties.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartProperties.java
index 68abedb..00d6aba 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartProperties.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/MultiPartProperties.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,7 @@
 import jakarta.ws.rs.ext.ContextResolver;
 
 import org.glassfish.jersey.internal.util.PropertiesClass;
+import org.glassfish.jersey.message.internal.ReaderWriter;
 
 /**
  * Injectable JavaBean containing the configuration parameters for
@@ -38,12 +39,17 @@
     /**
      * Default threshold size for buffer.
      */
-    public static final int DEFAULT_BUFFER_THRESHOLD = 4096;
+    public static final int DEFAULT_BUFFER_THRESHOLD = ReaderWriter.BUFFER_SIZE;
 
     /**
+     * <p>
      * Name of a properties resource that (if found in the classpath
      * for this application) will be used to configure the settings returned
      * by our getter methods.
+     * </p>
+     * <p>
+     *     The resource name is {@code jersey-multipart-config.properties}.
+     * </p>
      */
     public static final String MULTI_PART_CONFIG_RESOURCE = "jersey-multipart-config.properties";
 
@@ -51,7 +57,7 @@
      * Name of the resource property for the threshold size (in bytes) above which a body part entity will be
      * buffered to disk instead of being held in memory.
      *
-     * The default value is {@value #DEFAULT_BUFFER_THRESHOLD}.
+     * The default value is {@link #DEFAULT_BUFFER_THRESHOLD}.
      */
     public static final String BUFFER_THRESHOLD = "jersey.config.multipart.bufferThreshold";
 
@@ -61,8 +67,20 @@
     public static final int BUFFER_THRESHOLD_MEMORY_ONLY = -1;
 
     /**
+     * <p>
+     *     Limit the maximum number of parts the multipart entity can have. If the limit is over,
+     *     the error response status {@link jakarta.ws.rs.core.Response.Status#REQUEST_ENTITY_TOO_LARGE} is returned.
+     * </p>
+     * <p>
+     *     By default, the number is unlimited.
+     * </p>
+     * @since 2.44
+     */
+    public static final String MAX_PARTS = "jersey.config.multipart.maxParts";
+
+    /**
      * Name of the resource property for the directory to store temporary files containing body parts of multipart message that
-     * extends allowed memory threshold..
+     * extends allowed memory threshold.
      *
      * The default value is not set (will be taken from {@code java.io.tmpdir} system property).
      */
@@ -80,6 +98,11 @@
     private String tempDir = null;
 
     /**
+     * Maximum number of entity parts allowed.
+     */
+    private int maxParts = Integer.MAX_VALUE;
+
+    /**
      * Load and customize (if necessary) the configuration values for the
      * {@code jersey-multipart} injection binder.
      *
@@ -114,6 +137,15 @@
     }
 
     /**
+     * Return maximum number of entity parts allowed.
+     * @return maximum number of parts.
+     * @since 2.44
+     */
+    public int getMaxParts() {
+        return maxParts;
+    }
+
+    /**
      * Set the size (in bytes) of the entity of an incoming {@link BodyPart} before it will be buffered to disk.
      *
      * @param threshold size of body part.
@@ -139,6 +171,17 @@
     }
 
     /**
+     * Set the maximum number of received parts of a multipart entity.
+     * @param maxParts The maximum number of entity parts.
+     * @return {@code MultiPartProperties} instance.
+     * @since 2.44
+     */
+    public MultiPartProperties maxParts(int maxParts) {
+        this.maxParts = maxParts;
+        return this;
+    }
+
+    /**
      * Configure the values returned by this instance's getters based on
      * the contents of a properties resource, if it exists on the classpath
      * for this application.
@@ -169,6 +212,9 @@
             if (props.containsKey(TEMP_DIRECTORY)) {
                 this.tempDir = props.getProperty(TEMP_DIRECTORY);
             }
+            if (props.contains(MAX_PARTS)) {
+                this.maxParts = Integer.parseInt(props.getProperty(MAX_PARTS));
+            }
         } catch (final IOException e) {
             throw new IllegalArgumentException(e);
         } finally {
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 6c834d9..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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2021 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
@@ -20,6 +20,8 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -234,7 +236,13 @@
         @Override
         public Object apply(ContainerRequest request) {
             // Return the field value for the field specified by the sourceName property.
-            final List<FormDataBodyPart> parts = getEntity(request).getFields(parameter.getSourceName());
+            final String sourceName = parameter.getAnnotations().length == 1
+                    ? parameter.getSourceName()
+                    : Arrays.stream(parameter.getAnnotations())
+                        .filter(ann -> FormDataParam.class.isInstance(ann))
+                        .map(ann -> FormDataParam.class.cast(ann))
+                        .findFirst().get().value();
+            final List<FormDataBodyPart> parts = getEntity(request).getFields(sourceName);
 
             final FormDataBodyPart part = parts != null ? parts.get(0) : null;
             final MediaType mediaType = part != null ? part.getMediaType() : MediaType.TEXT_PLAIN_TYPE;
@@ -396,44 +404,48 @@
             } else {
                 return null;
             }
-        } else if (parameter.getSourceAnnotation().annotationType() == FormDataParam.class) {
-            final String paramName = parameter.getSourceName();
-            if (paramName == null || paramName.isEmpty()) {
-                // Invalid query parameter name
-                return null;
-            }
+        } else {
+            for (Annotation sourceAnnotation : parameter.getAnnotations()) {
+                if (sourceAnnotation.annotationType() == FormDataParam.class) {
+                    final String paramName = ((FormDataParam) sourceAnnotation).value(); // sourceName refers to the last anno
+                    if (paramName == null || paramName.isEmpty()) {
+                        // Invalid query parameter name
+                        return null;
+                    }
 
-            if (Collection.class == rawType || List.class == rawType) {
-                final Class clazz = ReflectionHelper.getGenericTypeArgumentClasses(parameter.getType()).get(0);
+                    if (Collection.class == rawType || List.class == rawType) {
+                        final Class clazz = ReflectionHelper.getGenericTypeArgumentClasses(parameter.getType()).get(0);
 
-                if (FormDataBodyPart.class == clazz) {
-                    // Return a collection of form data body part.
-                    return new ListFormDataBodyPartValueProvider(paramName);
-                } else if (FormDataContentDisposition.class == clazz) {
-                    // Return a collection of form data content disposition.
-                    return new ListFormDataContentDispositionProvider(paramName);
-                } else {
-                    // Return a collection of specific type.
-                    return new FormDataParamValueProvider(parameter, get(parameter));
+                        if (FormDataBodyPart.class == clazz) {
+                            // Return a collection of form data body part.
+                            return new ListFormDataBodyPartValueProvider(paramName);
+                        } else if (FormDataContentDisposition.class == clazz) {
+                            // Return a collection of form data content disposition.
+                            return new ListFormDataContentDispositionProvider(paramName);
+                        } else {
+                            // Return a collection of specific type.
+                            return new FormDataParamValueProvider(parameter, get(parameter));
+                        }
+                    } else if (FormDataBodyPart.class == rawType) {
+                        return new FormDataBodyPartProvider(paramName);
+                    } else if (FormDataContentDisposition.class == rawType) {
+                        return new FormDataContentDispositionProvider(paramName);
+                    } else if (File.class == rawType) {
+                        return new FileProvider(paramName);
+                    } 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);
+                    }
                 }
-            } else if (FormDataBodyPart.class == rawType) {
-                return new FormDataBodyPartProvider(paramName);
-            } else if (FormDataContentDisposition.class == rawType) {
-                return new FormDataContentDispositionProvider(paramName);
-            } else if (File.class == rawType) {
-                return new FileProvider(paramName);
-            } else {
-                return new FormDataParamValueProvider(parameter, get(parameter));
-            }
-        } else if (FormParam.class.equals(parameter.getSourceAnnotation().annotationType())) {
-            final String paramName = parameter.getSourceName();
-            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/MultiPartReaderClientSide.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java
index c867078..edb80bd 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.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
@@ -28,6 +28,7 @@
 import java.util.logging.Logger;
 
 import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.ClientErrorException;
 import jakarta.ws.rs.ConstrainedTo;
 import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.RuntimeType;
@@ -36,6 +37,7 @@
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.ext.ContextResolver;
 import jakarta.ws.rs.ext.MessageBodyReader;
 import jakarta.ws.rs.ext.Providers;
@@ -79,6 +81,7 @@
      */
     private Provider<MessageBodyWorkers> messageBodyWorkers;
     private final MIMEConfig mimeConfig;
+    private final int maxParts;
 
     /**
      * Accepts constructor injection of the configuration parameters for this
@@ -98,6 +101,8 @@
             properties = new MultiPartProperties();
         }
 
+        maxParts = properties.getMaxParts();
+
         this.messageBodyWorkers = messageBodyWorkers;
         mimeConfig = createMimeConfig(properties);
     }
@@ -205,7 +210,12 @@
             fileNameFix = userAgent != null && userAgent.contains(" MSIE ");
         }
 
-        for (final MIMEPart mimePart : getMimeParts(mimeMessage)) {
+        final List<MIMEPart> mimeParts = getMimeParts(mimeMessage);
+        if (mimeParts.size() > maxParts) {
+            throw new ClientErrorException(Response.Status.REQUEST_ENTITY_TOO_LARGE);
+        }
+
+        for (final MIMEPart mimePart : mimeParts) {
             final BodyPart bodyPart = formData ? new FormDataBodyPart(fileNameFix) : new BodyPart();
 
             // Configure providers.
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/OrderParamTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/OrderParamTest.java
new file mode 100644
index 0000000..23cc7a8
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/OrderParamTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.internal;
+
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.ParamQualifier;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.Consumes;
+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 java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class OrderParamTest extends JerseyTest {
+    @Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
+    @Retention(RetentionPolicy.RUNTIME)
+    @ParamQualifier
+    public static @interface AnnoWithValue {
+        String value() default "";
+    }
+
+    @Path("/order")
+    public static class OrderTestResource {
+        @POST
+        @Path("/dataAfter")
+        @Consumes(value = MediaType.MULTIPART_FORM_DATA)
+        public String orderBefore(@FormDataParam("file") @AnnoWithValue("xxx") InputStream inputStream) throws IOException {
+            return ReaderWriter.readFromAsString(inputStream, MediaType.TEXT_PLAIN_TYPE);
+        }
+
+        @POST
+        @Path("/dataBefore")
+        @Consumes(value = MediaType.MULTIPART_FORM_DATA)
+        public String orderAfter(@AnnoWithValue("zzz") @FormDataParam("file") InputStream inputStream) throws IOException {
+            return ReaderWriter.readFromAsString(inputStream, MediaType.TEXT_PLAIN_TYPE);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(OrderTestResource.class).register(MultiPartFeature.class);
+    }
+
+    @Test
+    public void testOrder() {
+        final String MSG = "Hello";
+        FormDataMultiPart multiPart = new FormDataMultiPart();
+        multiPart.field("file", MSG, MediaType.TEXT_PLAIN_TYPE);
+        try (Response response = target("order")
+                .register(MultiPartFeature.class)
+                .path("dataBefore").request()
+                .post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE))) {
+            assertEquals(200, response.getStatus());
+            assertEquals(MSG, response.readEntity(String.class));
+        }
+
+        try (Response response = target("order")
+                .register(MultiPartFeature.class)
+                .path("dataAfter").request()
+                .post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE))) {
+            assertEquals(200, response.getStatus());
+            assertEquals(MSG, response.readEntity(String.class));
+        }
+    }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/RestrictionsTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/RestrictionsTest.java
new file mode 100644
index 0000000..9906f11
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/RestrictionsTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.internal;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.media.multipart.MultiPartProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+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;
+
+public class RestrictionsTest extends JerseyTest {
+    @Path("/")
+    public static class RestrictionsTestResource {
+        @POST
+        @Path("max.parts")
+        public String postMaxPart(@FormDataParam("part1") String part1, @FormDataParam("part2") String part2) {
+            return part1 + part2;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(RestrictionsTestResource.class)
+                .register(MultiPartFeature.class)
+                .register(new MultiPartProperties().maxParts(2).resolver());
+    }
+
+    @Override
+    protected void configureClient(ClientConfig config) {
+        config.register(MultiPartFeature.class);
+    }
+
+    @Test
+    public void testPassNumberOfParts() {
+        FormDataMultiPart multiPart = new FormDataMultiPart();
+        multiPart.field("part1", "he", MediaType.TEXT_PLAIN_TYPE);
+        multiPart.field("part2", "llo", MediaType.TEXT_PLAIN_TYPE);
+        try (Response r = target("max.parts").request().post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE))) {
+            Assertions.assertEquals(200, r.getStatus());
+            Assertions.assertEquals("hello", r.readEntity(String.class));
+        }
+    }
+
+    @Test
+    public void testFailsNumberOfParts() {
+        FormDataMultiPart multiPart = new FormDataMultiPart();
+        multiPart.field("part1", "he", MediaType.TEXT_PLAIN_TYPE);
+        multiPart.field("part2", "llo", MediaType.TEXT_PLAIN_TYPE);
+        multiPart.field("part3", "!", MediaType.TEXT_PLAIN_TYPE);
+        try (Response r = target("max.parts").request().post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE))) {
+            Assertions.assertEquals(Response.Status.REQUEST_ENTITY_TOO_LARGE.getStatusCode(), r.getStatus());
+        }
+    }
+}
diff --git a/pom.xml b/pom.xml
index 493e21f..6045c83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -142,6 +142,9 @@
         <contributor>
             <name>Stepan Vavra</name>
         </contributor>
+        <contributor>
+            <name>Dmytro Dovnar</name>
+        </contributor>
     </contributors>
 
     <licenses>
@@ -305,7 +308,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-clean-plugin</artifactId>
-                    <version>2.5</version>
+                    <version>${clean.mvn.plugin.version}</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
@@ -313,6 +316,8 @@
                     <version>${compiler.mvn.plugin.version}</version>
                     <inherited>true</inherited>
                     <configuration>
+                        <source>${java.version}</source>
+                        <target>${java.version}</target>
                         <compilerArguments>
                             <!--<Werror />-->
                             <!-- TODO work towards eliminating all warnings in order to be able to enable the -Xlint option -->
@@ -468,7 +473,7 @@
                         <doctitle>Jersey ${jersey.version} API Documentation</doctitle>
                         <windowtitle>Jersey ${jersey.version} API</windowtitle>
                         <bottom>
-                            <![CDATA[Copyright &#169; 2007-2023,
+                            <![CDATA[Copyright &#169; 2007-2024,
                                 <a href="http://www.oracle.com">Oracle</a>
                                 and/or its affiliates.
                                 All Rights Reserved. Use is subject to license terms.]]>
@@ -479,7 +484,7 @@
                             <link>https://eclipse-ee4j.github.io/jersey.github.io/apidocs/latest/jersey/</link>
                         </links>
                         <excludePackageNames>
-                            *.internal.*:*.innate.*:*.tests.*
+                            *.innate:*.innate.*:*.tests:*.tests.*
                         </excludePackageNames>
                         <includeDependencySources>false</includeDependencySources>
                         <dependencySourceIncludes>
@@ -544,11 +549,6 @@
                     </configuration>
                 </plugin>
                 <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-site-plugin</artifactId>
-                    <version>${site.mvn.plugin.version}</version>
-                </plugin>
-                <plugin>
                     <groupId>org.codehaus.mojo</groupId>
                     <artifactId>exec-maven-plugin</artifactId>
                     <version>${exec.mvn.plugin.version}</version>
@@ -793,60 +793,10 @@
                         <dependency>
                             <groupId>org.apache.ant</groupId>
                             <artifactId>ant</artifactId>
-                            <version>1.10.12</version>
+                            <version>${mvn.ant.version}</version>
                         </dependency>
                     </dependencies>
                 </plugin>
-                <plugin>
-                    <groupId>org.fortasoft</groupId>
-                    <artifactId>gradle-maven-plugin</artifactId>
-                    <version>1.0.8</version>
-                </plugin>
-                <plugin>
-                    <groupId>com.github.wvengen</groupId>
-                    <artifactId>proguard-maven-plugin</artifactId>
-                    <version>${proguard.mvn.plugin.version}</version>
-                    <dependencies>
-                        <dependency>
-                            <groupId>net.sf.proguard</groupId>
-                            <artifactId>proguard-base</artifactId>
-                            <version>6.2.2</version><!-- transitive dependency version increased from 5.0 -->
-                            <scope>runtime</scope>
-                        </dependency>
-                    </dependencies>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-compiler-plugin</artifactId>
-                    <inherited>true</inherited>
-                    <configuration>
-                        <source>${java.version}</source>
-                        <target>${java.version}</target>
-                    </configuration>
-                    <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>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
             </plugins>
         </pluginManagement>
         <plugins>
@@ -895,7 +845,6 @@
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
-                <version>${buildhelper.mvn.plugin.version}</version>
                 <configuration>
                     <portNames>
                         <portName>jersey.config.test.container.port</portName>
@@ -959,7 +908,6 @@
             <properties>
 <!--                <release.tests.args>-Dskip.tests=true</release.tests.args>-->
                 <skip.tests>true</skip.tests>
-                <skip.e2e>true</skip.e2e>
             </properties>
         </profile>
         <profile>
@@ -1135,7 +1083,7 @@
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-project-info-reports-plugin</artifactId>
-                        <version>3.4.5</version>
+                        <version>${project.info.reports.mvn.plugin.version}</version>
                         <reportSets>
                             <reportSet>
                                 <reports>
@@ -1296,51 +1244,6 @@
             </build>
         </profile>
         <profile>
-            <!--
-            Profile is aimed to run the build on travis
-            due to travis limitations for output (max 4MB) this profile is used along with grep which reduces
-            the output.
-            However some e2e tests produce output which is not grepped (thus is not visible) and run longer than
-            10 minutes which results in the whole build is being murdered by Travis because of death suspection
-
-            the whole build is run as clean install but excludes several e2e tests because of the not grepped output
-            -->
-            <id>travis_e2e_skip</id>
-            <properties>
-                <skip.e2e>true</skip.e2e>
-            </properties>
-        </profile>
-        <profile>
-            <!--
-             Profile is aimed to run the build on travis
-            due to travis limitations for output (max 4MB) this profile is used to run e2e tests only.
-
-            the only thing which is happen using profile is run of e2e tests (with additional build)
-            everything is already build using travis_e2e_skip profile
-
-            the whole build is run as test -Ptravis_e2e
-            -->
-            <id>travis_e2e</id>
-            <properties>
-                <skip.e2e>false</skip.e2e>
-                <skip.tests>true</skip.tests>
-            </properties>
-        </profile>
-        <profile>
-                <!-- Use -Peclipse_repo to use SNAPSHOTs stored in Eclipse's Nexus instance ("Nightly Builds") -->
-                <id>eclipse_repo</id>
-            <repositories>
-                    <repository>
-                        <snapshots>
-                            <enabled>true</enabled>
-                        </snapshots>
-                        <id>repo.jaxrs-api.eclipse.org</id>
-                        <name>JAX-RS API Repository - Snapshots</name>
-                        <url>https://repo.eclipse.org/content/repositories/jax-rs-api-snapshots</url>
-                    </repository>
-                </repositories>
-        </profile>
-        <profile>
             <id>license_check</id>
             <pluginRepositories>
                 <pluginRepository>
@@ -1363,7 +1266,7 @@
                     <plugin>
                         <groupId>org.eclipse.dash</groupId>
                         <artifactId>license-tool-plugin</artifactId>
-                        <version>1.0.2</version>
+                        <version>1.1.0</version>
                         <executions>
                             <execution>
                                 <id>license-check</id>
@@ -1416,20 +1319,20 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
-                <version>3.4.1</version>
+                <version>${javadoc.mvn.plugin.version}</version>
                 <!-- Run this plugin report sets only in the main Jersey pom -->
                 <inherited>false</inherited>
                 <configuration>
                     <doctitle>Jersey ${jersey.version} API Documentation</doctitle>
                     <windowtitle>Jersey ${jersey.version} API</windowtitle>
                     <bottom>
-                        <![CDATA[Copyright &#169; 2007-2023,
+                        <![CDATA[Copyright &#169; 2007-2024,
                             <a href="http://www.oracle.com">Oracle</a>
                             and/or its affiliates.
                             All Rights Reserved. Use is subject to license terms.]]>
                     </bottom>
                     <excludePackageNames>
-                        com.sun.ws.rs.ext:*.examples.*:*.internal.*:*.tests.*
+                        com.sun.ws.rs.ext:*.examples.*:*.innate:*.innate.*:*.tests:*.tests.*
                     </excludePackageNames>
                     <links>
                         <link>https://jax-rs.github.io/apidocs/2.1</link>
@@ -1469,7 +1372,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jxr-plugin</artifactId>
-                <version>2.3</version>
+                <version>${jxr.mvn.plugin.version}</version>
                 <reportSets>
                     <reportSet>
                         <reports>
@@ -2131,7 +2034,6 @@
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 <!--        <release.tests.args>-Dmaven.test.skip=false</release.tests.args>-->
 <!--        <release.preparationGoals>clean install</release.preparationGoals>-->
-        <skip.e2e>false</skip.e2e>
         <skip.tests>false</skip.tests>
         <xdk.absolute.path />
         <surefire.security.argline />
@@ -2142,13 +2044,15 @@
 
         <!-- Versions of Maven plugins -->
         <antrun.mvn.plugin.version>3.1.0</antrun.mvn.plugin.version>
+        <mvn.ant.version>1.10.14</mvn.ant.version>
         <assembly.mvn.plugin.version>3.7.1</assembly.mvn.plugin.version>
+        <clean.mvn.plugin.version>3.3.2</clean.mvn.plugin.version>
         <enforcer.mvn.plugin.version>3.4.1</enforcer.mvn.plugin.version>
         <exec.mvn.plugin.version>3.2.0</exec.mvn.plugin.version>
         <buildhelper.mvn.plugin.version>3.5.0</buildhelper.mvn.plugin.version>
         <buildnumber.mvn.plugin.version>3.2.0</buildnumber.mvn.plugin.version>
         <checkstyle.mvn.plugin.version>3.3.1</checkstyle.mvn.plugin.version>
-        <checkstyle.version>10.14.2</checkstyle.version>
+        <checkstyle.version>10.16.0</checkstyle.version>
         <compiler.mvn.plugin.version>3.13.0</compiler.mvn.plugin.version>
         <!--
         Special version of the compiler plugin just for the jersey-common. All versions above
@@ -2158,23 +2062,22 @@
          -->
         <compiler.common.mvn.plugin.version>3.9.0</compiler.common.mvn.plugin.version>
         <dependency.mvn.plugin.version>3.6.1</dependency.mvn.plugin.version>
-        <deploy.mvn.plugin.version>3.1.1</deploy.mvn.plugin.version>
+        <deploy.mvn.plugin.version>3.1.2</deploy.mvn.plugin.version>
         <ear.mvn.plugin.version>3.3.0</ear.mvn.plugin.version>
         <failsafe.mvn.plugin.version>3.2.5</failsafe.mvn.plugin.version>
         <felix.mvn.plugin.version>5.1.9</felix.mvn.plugin.version>
         <findbugs.mvn.plugin.version>3.0.5</findbugs.mvn.plugin.version>
         <gfembedded.mvn.plugin.version>5.1</gfembedded.mvn.plugin.version>
-        <install.mvn.plugin.version>3.1.1</install.mvn.plugin.version>
+        <install.mvn.plugin.version>3.1.2</install.mvn.plugin.version>
         <istack.mvn.plugin.version>4.2.0</istack.mvn.plugin.version>
-        <jar.mvn.plugin.version>3.3.0</jar.mvn.plugin.version>
+        <jar.mvn.plugin.version>3.4.1</jar.mvn.plugin.version>
         <javadoc.mvn.plugin.version>3.6.3</javadoc.mvn.plugin.version>
         <jxr.mvn.plugin.version>3.3.2</jxr.mvn.plugin.version>
         <paxexam.mvn.plugin.version>1.2.4</paxexam.mvn.plugin.version>
-        <proguard.mvn.plugin.version>2.6.1</proguard.mvn.plugin.version>
+        <project.info.reports.mvn.plugin.version>3.5.0</project.info.reports.mvn.plugin.version>
         <resources.mvn.plugin.version>3.3.1</resources.mvn.plugin.version>
-        <shade.mvn.plugin.version>3.5.2</shade.mvn.plugin.version>
-        <site.mvn.plugin.version>3.12.1</site.mvn.plugin.version>
-        <source.mvn.plugin.version>3.3.0</source.mvn.plugin.version>
+        <shade.mvn.plugin.version>3.5.3</shade.mvn.plugin.version>
+        <source.mvn.plugin.version>3.3.1</source.mvn.plugin.version>
         <surefire.mvn.plugin.version>3.2.5</surefire.mvn.plugin.version>
         <war.mvn.plugin.version>3.4.0</war.mvn.plugin.version>
         <wiremock.mvn.plugin.version>2.11.0</wiremock.mvn.plugin.version>
@@ -2193,7 +2096,7 @@
         <aspectj.weaver.version>1.9.22</aspectj.weaver.version>
 <!--        <bnd.plugin.version>2.3.6</bnd.plugin.version>-->
         <bouncycastle.version>1.70</bouncycastle.version>
-        <commons.io.version>2.15.1</commons.io.version>
+        <commons.io.version>2.16.1</commons.io.version>
         <commons.codec.version>1.16.1</commons.codec.version>
 <!--        <commons-lang3.version>3.3.2</commons-lang3.version>-->
         <commons.logging.version>1.3.1</commons.logging.version>
@@ -2203,8 +2106,8 @@
         <felix.framework.version>7.0.5</felix.framework.version>
         <findbugs.glassfish.version>1.7</findbugs.glassfish.version>
         <freemarker.version>2.3.32</freemarker.version>
-        <gae.version>2.0.25</gae.version>
-        <groovy.version>4.0.20</groovy.version>
+        <gae.version>2.0.26</gae.version>
+        <groovy.version>4.0.21</groovy.version>
         <gson.version>2.10.1</gson.version>
 
         <!--versions, extracted here due to maven-enforcer-plugin -->
@@ -2225,9 +2128,9 @@
         <helidon.config.11.version>1.4.14</helidon.config.11.version> <!-- JDK 11- support -->
         <smallrye.config.version>3.7.1</smallrye.config.version>
 
-        <guava.version>31.1-jre</guava.version>
+        <guava.version>33.1.0-jre</guava.version>
         <hamcrest.version>2.2</hamcrest.version>
-        <xmlunit.version>2.9.1</xmlunit.version>
+        <xmlunit.version>2.10.0</xmlunit.version>
         <httpclient.version>4.5.14</httpclient.version>
         <httpclient5.version>5.3.1</httpclient5.version>
         <jackson.version>2.17.0</jackson.version>
@@ -2241,9 +2144,9 @@
         <junit-platform-suite.version>1.10.2</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>3.12.4</mockito.version> <!-- CQ 17673 -->
-        <mustache.version>0.9.11</mustache.version>
-        <netty.version>4.1.108.Final</netty.version>
+        <mockito.version>4.11.0</mockito.version> <!-- CQ 17673 -->
+        <mustache.version>0.9.12</mustache.version>
+        <netty.version>4.1.109.Final</netty.version>
         <opentracing.version>0.33.0</opentracing.version>
         <osgi.version>6.0.0</osgi.version>
         <osgi.framework.version>1.10.0</osgi.framework.version>
@@ -2259,10 +2162,11 @@
         <servlet6.version>6.0.0</servlet6.version>
 
         <simple.version>6.0.1</simple.version>
-        <slf4j.version>2.0.12</slf4j.version>
+        <slf4j.version>2.0.13</slf4j.version>
         <spring6.version>6.0.18</spring6.version>
         <testng.version>7.9.0</testng.version>
         <testng6.version>6.9.13.6</testng6.version>
+        <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
         <!-- Jakartified, eligible for CQ -->
         <weld.version>5.1.1.Final</weld.version>
         <weld3.version>3.1.9.Final</weld3.version>
@@ -2272,7 +2176,7 @@
         <xerces.version>2.12.2</xerces.version>
 
         <!-- Graal VM       -->
-        <graalvm.version>20.3.13</graalvm.version>
+        <graalvm.version>20.3.14</graalvm.version>
 
         <!-- do not need CQs (below this line till the end of version properties)-->
         <gf.impl.version>7.0.6</gf.impl.version>
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
index 5abee5c..3a155a8 100644
--- a/tests/e2e-client/pom.xml
+++ b/tests/e2e-client/pom.xml
@@ -41,7 +41,6 @@
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                     <systemPropertyVariables>
                         <sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
                     </systemPropertyVariables>
diff --git a/tests/e2e-entity/pom.xml b/tests/e2e-entity/pom.xml
index 68c4cfc..2cb4920 100644
--- a/tests/e2e-entity/pom.xml
+++ b/tests/e2e-entity/pom.xml
@@ -41,7 +41,6 @@
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                 </configuration>
                 <executions>
                     <execution>
diff --git a/tests/e2e-inject/hk2/pom.xml b/tests/e2e-inject/hk2/pom.xml
index e8ccf7a..e2dc477 100644
--- a/tests/e2e-inject/hk2/pom.xml
+++ b/tests/e2e-inject/hk2/pom.xml
@@ -36,6 +36,11 @@
             <type>pom</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-client</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 
diff --git a/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2FactoryBindingTest.java b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2FactoryBindingTest.java
new file mode 100644
index 0000000..abc0981
--- /dev/null
+++ b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2FactoryBindingTest.java
@@ -0,0 +1,340 @@
+/*
+ * 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.e2e.inject.hk2;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.InjectionManagerClientProvider;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Map;
+import java.util.function.Supplier;
+
+public class HK2FactoryBindingTest {
+
+    public static interface ConfigurationProperties {
+        Map<String, Object> getProperties();
+    }
+
+    public static class ConfigurationPropertiesFactory implements org.glassfish.hk2.api.Factory<ConfigurationProperties> {
+
+        private final Configuration configuration;
+
+        @Inject
+        public ConfigurationPropertiesFactory(Configuration configuration) {
+            this.configuration = configuration;
+        }
+
+        @Override
+        public ConfigurationProperties provide() {
+            return new ConfigurationProperties() {
+                @Override
+                public Map<String, Object> getProperties() {
+                    return configuration.getProperties();
+                }
+            };
+        }
+
+        @Override
+        public void dispose(ConfigurationProperties configurationProperties) {
+
+        }
+    }
+
+    @Priority(Priorities.USER)
+    public static class ConfigurationPropertiesFilter implements ClientRequestFilter {
+        @Inject
+        ConfigurationProperties properties;
+
+        @Override
+        public void filter(ClientRequestContext requestContext) throws IOException {
+            requestContext.abortWith(Response.ok(properties.getProperties().get(PROPERTY_NAME)).build());
+        }
+    }
+
+    private static final String PROPERTY_NAME = "TEST_PROPERTY";
+    private static final String PROPERTY_VALUE = "HELLO_PROPERTY";
+
+    @Test
+    public void testFactoryClassBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(ConfigurationPropertiesFactory.class).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    @Test
+    public void testFactoryInstanceBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(new ConfigurationPropertiesFactory(config)).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    static final class ConfigurationPropertiesImpl implements ConfigurationProperties {
+        private final Configuration configuration;
+        @Inject
+        public ConfigurationPropertiesImpl(Configuration configuration) {
+            this.configuration = configuration;
+        }
+
+        @Override
+        public Map<String, Object> getProperties() {
+            return configuration.getProperties();
+        }
+    }
+
+    static class ConfigurationPropertiesSupplier implements Supplier<ConfigurationPropertiesImpl> {
+        private final Configuration configuration;
+
+        @Inject
+        ConfigurationPropertiesSupplier(Configuration configuration) {
+            this.configuration = configuration;
+        }
+
+        @Override
+        public ConfigurationPropertiesImpl get() {
+            return new ConfigurationPropertiesImpl(configuration);
+        }
+    }
+
+    @Test
+    public void testSupplierJerseyInstanceBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bindFactory(() -> new ConfigurationPropertiesImpl(config)).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    @Test
+    public void testSupplierJerseyClassBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bindFactory(ConfigurationPropertiesSupplier.class).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    public static interface ConfigurationPropertiesProvider {
+        Map<String, Object> getProperties();
+
+        ConfigurationProperties getConfigurationProperties();
+    }
+
+    public static class ConfigurationPropertiesProviderImpl implements ConfigurationPropertiesProvider {
+        private final Configuration configuration;
+        @Inject
+        public ConfigurationPropertiesProviderImpl(Configuration configuration) {
+            this.configuration = configuration;
+        }
+
+        @Override
+        public Map<String, Object> getProperties() {
+            return configuration.getProperties();
+        }
+
+        @Override
+        public ConfigurationProperties getConfigurationProperties() {
+            return new ConfigurationPropertiesImpl(configuration);
+        }
+    }
+
+    public static class ConfigurationPropertiesProviderSupplier implements Supplier<ConfigurationProperties> {
+        final ConfigurationPropertiesProvider impl;
+
+        @Inject
+        public ConfigurationPropertiesProviderSupplier(ConfigurationPropertiesProvider impl) {
+            this.impl = impl;
+        }
+
+        @Override
+        public ConfigurationProperties get() {
+            return impl.getConfigurationProperties();
+        }
+    }
+
+    public static class ConfigurationProperties2Filter implements ClientRequestFilter {
+        @Inject
+        ConfigurationProperties properties;
+
+        @Override
+        public void filter(ClientRequestContext requestContext) throws IOException {
+            requestContext.abortWith(Response.ok(properties.getProperties().get(PROPERTY_NAME)).build());
+        }
+    }
+
+    @Test
+    public void testSupplierOfProviderClassBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(ConfigurationPropertiesProviderImpl.class).to(ConfigurationPropertiesProvider.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+                bindFactory(ConfigurationPropertiesProviderSupplier.class).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationProperties2Filter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    @Test
+    public void testFactoryHk2ClassBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
+            @Override
+            protected void configure() {
+                bindFactory(ConfigurationPropertiesFactory.class).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    @Test
+    public void testFactoryHk2InstanceBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
+            @Override
+            protected void configure() {
+                bindFactory(new ConfigurationPropertiesFactory(config)).to(ConfigurationProperties.class).proxy(true)
+                        .proxyForSameScope(false).in(RequestScoped.class);
+            }
+        }).register(ConfigurationPropertiesFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    static @interface ConfigurationPropertiesInject {
+
+    }
+
+    static class ConfigurationPropertiesInjectResolver implements InjectionResolver<ConfigurationPropertiesInject> {
+
+        private final InjectionManager injectionManager;
+
+        ConfigurationPropertiesInjectResolver(InjectionManager injectionManager) {
+            this.injectionManager = injectionManager;
+        }
+
+        @Override
+        public Object resolve(Injectee injectee) {
+            if (injectee.getRequiredType() == ConfigurationProperties.class) {
+                return new ConfigurationPropertiesImpl(injectionManager.getInstance(Configuration.class));
+            }
+            return null;
+        }
+
+        @Override
+        public boolean isConstructorParameterIndicator() {
+            return false;
+        }
+
+        @Override
+        public boolean isMethodParameterIndicator() {
+            return false;
+        }
+
+        @Override
+        public Class<ConfigurationPropertiesInject> getAnnotation() {
+            return ConfigurationPropertiesInject.class;
+        }
+    }
+
+    public static class ConfigurationPropertiesInjectFilter implements ClientRequestFilter {
+        @ConfigurationPropertiesInject
+        ConfigurationProperties properties;
+
+        @Override
+        public void filter(ClientRequestContext requestContext) throws IOException {
+            requestContext.abortWith(Response.ok(properties.getProperties().get(PROPERTY_NAME)).build());
+        }
+    }
+
+    @Test
+    public void testInjectionResolverBinding() {
+        ClientConfig config = new ClientConfig();
+        config.property(PROPERTY_NAME, PROPERTY_VALUE);
+        String response = ClientBuilder.newClient(config).register(new Feature() {
+            @Override
+            public boolean configure(FeatureContext context) {
+                final InjectionManager injectionManager = InjectionManagerClientProvider.getInjectionManager(context);
+                context.register(new AbstractBinder() {
+                    @Override
+                    protected void configure() {
+                        bind(new ConfigurationPropertiesInjectResolver(injectionManager))
+                                //.to(ConfigurationProperties.class)
+                                .to(new GenericType<ConfigurationProperties>(){})
+                                .in(Singleton.class);
+                    }
+                });
+                return true;
+            }
+        }).register(ConfigurationPropertiesInjectFilter.class).target("http://test.com").request().get(String.class);
+        Assertions.assertEquals(PROPERTY_VALUE, response);
+    }
+}
diff --git a/tests/e2e-jdk-specifics/pom.xml b/tests/e2e-jdk-specifics/pom.xml
new file mode 100644
index 0000000..015079a
--- /dev/null
+++ b/tests/e2e-jdk-specifics/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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
+
+-->
+
+<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</groupId>
+        <artifactId>project</artifactId>
+        <version>3.1.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>e2e-jdk-specifics</artifactId>
+    <name>jersey-tests-e2e-specifics</name>
+    <packaging>jar</packaging>
+
+    <description>Jersey E2E tests for testing JDK 17+ specifics</description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <forkCount>1</forkCount>
+                    <reuseForks>false</reuseForks>
+                    <enableAssertions>false</enableAssertions>
+                    <argLine>
+                        ${http.patch.addopens}
+                    </argLine>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-bundle</artifactId>
+            <type>pom</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-util</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-suite</artifactId>
+            <version>${junit-platform-suite.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>jdk15-</id>
+            <activation>
+                <jdk>[8, 16)</jdk>
+            </activation>
+            <properties>
+                <http.patch.addopens> </http.patch.addopens>
+            </properties>
+        </profile>
+        <profile>
+            <id>jdk16+</id>
+            <activation>
+                <jdk>[16, )</jdk>
+            </activation>
+            <properties>
+                <http.patch.addopens>--add-opens java.base/java.net=ALL-UNNAMED</http.patch.addopens>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/tests/e2e-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk17/HttpPatchTest.java b/tests/e2e-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk17/HttpPatchTest.java
new file mode 100644
index 0000000..c949958
--- /dev/null
+++ b/tests/e2e-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk17/HttpPatchTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.e2e.jdk17;
+
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+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;
+
+public class HttpPatchTest extends JerseyTest {
+
+    public static final String PATCH_ENTITY = "HelloPatch";
+
+    @Target({ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    @HttpMethod(HttpMethod.PATCH)
+    public @interface PATCH {
+
+    }
+
+    @Path("/")
+    public static class HttpPatchResource {
+        @PATCH
+        public String patchEcho(String entity) {
+            return entity;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(HttpPatchResource.class);
+    }
+
+    @Test
+    void testPatchWithHttpUrlConnector() {
+        try (Response response = target()
+                .property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
+                .request().method(HttpMethod.PATCH, Entity.text(PATCH_ENTITY))) {
+            MatcherAssert.assertThat(200, Matchers.equalTo(response.getStatus()));
+            response.bufferEntity();
+            System.out.println(response.readEntity(String.class));
+            MatcherAssert.assertThat(PATCH_ENTITY, Matchers.equalTo(response.readEntity(String.class)));
+        }
+    }
+}
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index 34d73a8..64d5f26 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -41,7 +41,6 @@
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                 </configuration>
                 <executions>
                     <execution>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java
index 64c0422..f8dab62 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ChunkedInputOutputTest.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
@@ -61,13 +61,33 @@
     @Path("/test")
     public static class TestResource {
         /**
+         * Get chunk stream with a queue capacity of 2.
+         *
+         * @return chunk stream.
+         */
+        @GET
+        @Path("/testWithBuilder")
+        public ChunkedOutput<String> getWithBuilder() {
+            return getOutput(ChunkedOutput.<String>builder(String.class).queueCapacity(2)
+                             .chunkDelimiter("\r\n".getBytes()).build());
+        }
+
+        /**
          * Get chunk stream.
          *
          * @return chunk stream.
          */
         @GET
         public ChunkedOutput<String> get() {
-            final ChunkedOutput<String> output = new ChunkedOutput<>(String.class, "\r\n");
+            return getOutput(new ChunkedOutput<>(String.class, "\r\n"));
+        }
+
+        /**
+         * Get chunk stream.
+         *
+         * @return chunk stream.
+         */
+        private ChunkedOutput<String> getOutput(ChunkedOutput<String> output) {
 
             new Thread() {
                 @Override
@@ -183,6 +203,19 @@
     }
 
     /**
+     * Test retrieving chunked response stream as a single response string, when a builder with capacity is used.
+     *
+     * @throws Exception in case of a failure during the test execution.
+     */
+    @Test
+    public void testChunkedOutputToSingleStringWithBuilder() throws Exception {
+        final String response = target().path("test/testWithBuilder").request().get(String.class);
+
+        assertEquals("test\r\ntest\r\ntest\r\n", response,
+                "Unexpected value of chunked response unmarshalled as a single string.");
+    }
+
+    /**
      * Test retrieving chunked response stream sequentially as individual chunks using chunked input.
      *
      * @throws Exception in case of a failure during the test execution.
diff --git a/tests/e2e-testng/pom.xml b/tests/e2e-testng/pom.xml
index 05a1502..022ebc7 100644
--- a/tests/e2e-testng/pom.xml
+++ b/tests/e2e-testng/pom.xml
@@ -46,7 +46,6 @@
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                 </configuration>
                 <dependencies>
                     <dependency>
diff --git a/tests/e2e-tls/pom.xml b/tests/e2e-tls/pom.xml
index ffb3b3f..55665dd 100644
--- a/tests/e2e-tls/pom.xml
+++ b/tests/e2e-tls/pom.xml
@@ -40,8 +40,6 @@
                 <configuration>
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
-                    <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                     <systemPropertyVariables>
                         <sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
                         <jdk.httpclient.allowRestrictedHeaders>Host</jdk.httpclient.allowRestrictedHeaders>
@@ -51,6 +49,24 @@
                         </property>
                     </systemPropertyVariables>
                 </configuration>
+                <executions>
+                    <execution>
+                        <id>HttpsPatch</id>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>
+                                <include>**/HttpsPatchTest.java</include>
+                            </includes>
+                            <systemPropertyVariables>
+                                <jersey.added.opens>true</jersey.added.opens>
+                            </systemPropertyVariables>
+                            <!-- Allow HTTP PATCH by property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true) -->
+                            <argLine>${http.patch.addopens}</argLine>
+                        </configuration>
+                    </execution>
+                </executions>
             </plugin>
         </plugins>
     </build>
@@ -125,6 +141,15 @@
 
     <profiles>
         <profile>
+            <id>jdk8</id>
+            <activation>
+                <jdk>8</jdk>
+            </activation>
+            <properties>
+                <http.patch.addopens> </http.patch.addopens>
+            </properties>
+        </profile>
+        <profile>
             <id>jdk11+</id>
             <activation>
                 <jdk>[11,)</jdk>
@@ -139,6 +164,10 @@
             <properties>
                 <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
                 <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
+                <http.patch.addopens>
+                    --add-opens java.base/java.net=ALL-UNNAMED
+                    --add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED
+                </http.patch.addopens>
             </properties>
         </profile>
     </profiles>
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 3964fce..7da4a6b 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 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
@@ -74,10 +74,29 @@
         ClientConfig clientConfig = new ClientConfig();
         clientConfig.connectorProvider(provider);
         clientConfig.property(ClientProperties.SNI_HOST_NAME, "www.host1.com");
-        serverTest(clientConfig, provider, "www.host1.com");
+        serverTest(clientConfig, provider, "www.host1.com", "www.host1.com");
     }
 
-    public void serverTest(ClientConfig clientConfig, ConnectorProvider provider, String hostName) {
+    @ParameterizedTest
+    @MethodSource("getConnectors")
+    public void sniHostNamePropertyTest(ConnectorProvider provider) {
+        ClientConfig clientConfig = new ClientConfig();
+        clientConfig.connectorProvider(provider);
+        clientConfig.property(ClientProperties.SNI_HOST_NAME, "www.host3.com");
+        serverTest(clientConfig, provider, "www.host4.com", "www.host3.com");
+    }
+
+    @ParameterizedTest
+    @MethodSource("getConnectors")
+    public void turnOffSniTest(ConnectorProvider provider) {
+        ClientConfig clientConfig = new ClientConfig();
+        clientConfig.connectorProvider(provider);
+        clientConfig.property(ClientProperties.SNI_HOST_NAME, LOCALHOST);
+        serverTest(clientConfig, provider, "www.host4.com", null);
+    }
+
+
+    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];
@@ -121,12 +140,14 @@
 
         server.stop();
 
-        if (serverNames.isEmpty()) {
+        if (resultHostName != null && serverNames.isEmpty()) {
             throw new IllegalStateException("ServerNames are empty");
+        } else if (resultHostName == null) {
+            return;
         }
 
         String clientSniName = new String(serverNames.get(0).getEncoded());
-        if (!hostName.equals(clientSniName)) {
+        if (!resultHostName.equals(clientSniName)) {
             throw new IllegalStateException("Unexpected client SNI name " + clientSniName);
         }
 
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslContextPerRequestTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslContextPerRequestTest.java
index 944f284..d2564e9 100644
--- a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslContextPerRequestTest.java
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslContextPerRequestTest.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
@@ -53,10 +53,8 @@
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 
-public class SslContextPerRequestTest extends JerseyTest {
+public class SslContextPerRequestTest extends SslParentTest {
 
-    private SSLContext serverSslContext;
-    private SSLParameters serverSslParameters;
     private static final String MESSAGE = "Message for Netty with SSL";
 
     @Override
@@ -77,33 +75,6 @@
         return new ResourceConfig(TestResource.class);
     }
 
-    @Override
-    protected URI getBaseUri() {
-        return UriBuilder
-                .fromUri("https://localhost")
-                .port(getPort())
-                .build();
-    }
-
-    @Override
-    protected Optional<SSLContext> getSslContext() {
-        if (serverSslContext == null) {
-            serverSslContext = SslUtils.createServerSslContext();
-        }
-
-        return Optional.of(serverSslContext);
-    }
-
-    @Override
-    protected Optional<SSLParameters> getSslParameters() {
-        if (serverSslParameters == null) {
-            serverSslParameters = new SSLParameters();
-            serverSslParameters.setNeedClientAuth(false);
-        }
-
-        return Optional.of(serverSslParameters);
-    }
-
     public static Stream<ConnectorProvider> connectorProviders() {
         return Stream.of(
                 new HttpUrlConnectorProvider(),
@@ -168,43 +139,4 @@
         String s = target.request().get(String.class);
         Assertions.assertEquals(MESSAGE, s);
     }
-
-    private static 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 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() {
-            return new SslContextClientBuilder()
-                    .keyStore(getKeyStore(SERVER_IDENTITY_PATH, SERVER_IDENTITY_PASSWORD), SERVER_IDENTITY_PASSWORD)
-                    .get();
-        }
-
-        public static Supplier<SSLContext> createClientSslContext() {
-            return new SslContextClientBuilder()
-                    .trustStore(getKeyStore(CLIENT_TRUSTSTORE_PATH, CLIENT_TRUSTSTORE_PASSWORD));
-
-        }
-
-        private static KeyStore getKeyStore(String path, char[] keyStorePassword) {
-            try (InputStream inputStream = getResource(path)) {
-                KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
-                keyStore.load(inputStream, keyStorePassword);
-                return keyStore;
-            } catch (Exception e) {
-                throw new ProcessingException(e);
-            }
-        }
-
-        private static InputStream getResource(String path) {
-            return SslUtils.class.getClassLoader().getResourceAsStream(path);
-        }
-    }
 }
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslParentTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslParentTest.java
new file mode 100644
index 0000000..abfe245
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SslParentTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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
+ * 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.tls;
+
+import org.glassfish.jersey.client.SslContextClientBuilder;
+import org.glassfish.jersey.test.JerseyTest;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.UriBuilder;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.KeyStore;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+public class SslParentTest extends JerseyTest {
+
+    protected SSLContext serverSslContext;
+    protected SSLParameters serverSslParameters;
+
+    @Override
+    protected Optional<SSLContext> getSslContext() {
+        if (serverSslContext == null) {
+            serverSslContext = SslUtils.createServerSslContext();
+        }
+
+        return Optional.of(serverSslContext);
+    }
+
+    @Override
+    protected Optional<SSLParameters> getSslParameters() {
+        if (serverSslParameters == null) {
+            serverSslParameters = new SSLParameters();
+            serverSslParameters.setNeedClientAuth(false);
+        }
+
+        return Optional.of(serverSslParameters);
+    }
+
+    @Override
+    protected URI getBaseUri() {
+        return UriBuilder
+                .fromUri("https://localhost")
+                .port(getPort())
+                .build();
+    }
+
+    protected static 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 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() {
+            return new SslContextClientBuilder()
+                    .keyStore(getKeyStore(SERVER_IDENTITY_PATH, SERVER_IDENTITY_PASSWORD), SERVER_IDENTITY_PASSWORD)
+                    .get();
+        }
+
+        public static Supplier<SSLContext> createClientSslContext() {
+            return new SslContextClientBuilder()
+                    .trustStore(getKeyStore(CLIENT_TRUSTSTORE_PATH, CLIENT_TRUSTSTORE_PASSWORD));
+
+        }
+
+        private static KeyStore getKeyStore(String path, char[] keyStorePassword) {
+            try (InputStream inputStream = getResource(path)) {
+                KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
+                keyStore.load(inputStream, keyStorePassword);
+                return keyStore;
+            } catch (Exception e) {
+                throw new ProcessingException(e);
+            }
+        }
+
+        private static InputStream getResource(String path) {
+            return SslUtils.class.getClassLoader().getResourceAsStream(path);
+        }
+    }
+}
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/patch/HttpsPatchTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/patch/HttpsPatchTest.java
new file mode 100644
index 0000000..37b63c8
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/patch/HttpsPatchTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.e2e.tls.patch;
+
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.tests.e2e.tls.SslParentTest;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import javax.net.ssl.SSLContext;
+import jakarta.ws.rs.HttpMethod;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+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.function.Supplier;
+
+public class HttpsPatchTest extends SslParentTest {
+
+    public static final String PATCH_ENTITY = "HelloPatch";
+
+    @Target({ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    @HttpMethod(HttpMethod.PATCH)
+    public @interface PATCH {
+
+    }
+
+    @Path("/")
+    public static class HttpPatchResource {
+        @PATCH
+        public String patchEcho(String entity) {
+            return entity;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(HttpPatchResource.class);
+    }
+
+    @Test
+    void testPatchWithHttpUrlConnector() {
+        String value = System.getProperty("jersey.added.opens");
+        if (null == value) {
+            System.out.println("JDK add-opens not set - exiting...");
+            return;
+        }
+
+        Supplier<SSLContext> clientSslContext = SslUtils.createClientSslContext();
+        try (Response response = target()
+                .property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
+                .property(ClientProperties.SSL_CONTEXT_SUPPLIER, clientSslContext)
+                .request().method(HttpMethod.PATCH, Entity.text(PATCH_ENTITY))) {
+            MatcherAssert.assertThat(200, Matchers.equalTo(response.getStatus()));
+            response.bufferEntity();
+            System.out.println(response.readEntity(String.class));
+            MatcherAssert.assertThat(PATCH_ENTITY, Matchers.equalTo(response.readEntity(String.class)));
+        }
+    }
+}
diff --git a/tests/e2e/pom.xml b/tests/e2e/pom.xml
index f17cda4..1d0afdd 100644
--- a/tests/e2e/pom.xml
+++ b/tests/e2e/pom.xml
@@ -41,10 +41,10 @@
                     <forkCount>1</forkCount>
                     <reuseForks>false</reuseForks>
                     <enableAssertions>false</enableAssertions>
-                    <skipTests>${skip.e2e}</skipTests>
                     <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>
@@ -211,6 +211,7 @@
                             <testExcludes>
                                 <testExclude>org/glassfish/jersey/tests/e2e/container/Jersey2462Test.java</testExclude>
                                 <testExclude>org/glassfish/jersey/tests/e2e/container/JettyEmptyHeaderParamTest.java</testExclude>
+                                <testExclude>org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java</testExclude>
                             </testExcludes>
                         </configuration>
                     </plugin>
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
new file mode 100644
index 0000000..2c4cc35
--- /dev/null
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/inject/SingleRequestScopeInjectionTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.e2e.inject;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Inject;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+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.GenericType;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SingleRequestScopeInjectionTest extends JerseyTest {
+    @Path("hello")
+    public static class HelloResource {
+        @GET
+        public String getHello() {
+            return "Hello World!";
+        }
+    }
+    @Override
+    protected Application configure() {
+        ResourceConfig resourceConfig = new ResourceConfig(HelloResource.class);
+        resourceConfig.register(new InjectedFilterRegistrar(InjectedFilter.class));
+        return resourceConfig;
+    }
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new JettyTestContainerFactory();
+    }
+    @Test
+    public void test() {
+        final String hello = target("hello").request().get(String.class);
+        assertEquals("Hello World!", hello);
+    }
+    public static class InjectedFilter implements ContainerRequestFilter {
+        @Inject
+        private InjectionManager injectionManager;
+        @Override
+        public void filter(ContainerRequestContext requestContext) throws IOException {
+            Ref<HttpServletRequest> requestRef =
+                    injectionManager.getInstance((new GenericType<Ref<HttpServletRequest>>() {}).getType());
+            if (requestRef == null || requestRef.get() == null) {
+                throw new IllegalStateException("Request not injected");
+            }
+        }
+    }
+    public static class InjectedFilterRegistrar implements DynamicFeature {
+        private final Class<?> filterToRegister;
+        public InjectedFilterRegistrar(Class<?> filterToRegister) {
+            this.filterToRegister = filterToRegister;
+        }
+        @Override
+        public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+            context.register(filterToRegister);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/integration/tracing-support/pom.xml b/tests/integration/tracing-support/pom.xml
index a7e5a9c..83e185f 100644
--- a/tests/integration/tracing-support/pom.xml
+++ b/tests/integration/tracing-support/pom.xml
@@ -43,12 +43,27 @@
             <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>
     </dependencies>
 
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <systemPropertyVariables>
+                        <java.util.logging.config.file>${project.build.testOutputDirectory}/logging.properties</java.util.logging.config.file>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
             </plugin>
             <plugin>
@@ -89,13 +104,32 @@
     </build>
     <profiles>
         <profile>
-            <id>jdk11</id>
+            <id>jdk11+</id>
             <activation>
-                <jdk>[11,21)</jdk>
+                <jdk>[11,)</jdk>
             </activation>
-            <properties>
-                <jetty.version>${jetty.tracing.version}</jetty.version>
-            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <!--
+                            Since Jetty 11 for some reason is not possibly to properly set responseHeaderSize property
+                            which should be jetty.response.header.size with adjusted value 16192. The property however
+                            is never recognized by the plugin so resulting in the
+                                            org.eclipse.jetty.http.BadMessageException: 500: Response header too large
+                            exception. For this reason the test is being excluded.
+                              -->
+                            <testExcludes>
+                                <testExclude>
+                                    org/glassfish/jersey/tests/integration/tracing/AllTracingSupportITCase.java
+                                </testExclude>
+                            </testExcludes>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
         </profile>
     </profiles>
 </project>
diff --git a/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java
new file mode 100644
index 0000000..6afcd91
--- /dev/null
+++ b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tracing;
+
+import org.glassfish.jersey.message.internal.TracingLogger;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.server.TracingConfig;
+import org.glassfish.jersey.server.internal.ServerTraceEvent;
+import org.glassfish.jersey.test.JerseyTest;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+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 java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+public class TracingMatchResourceMethodTest extends JerseyTest {
+    GatheringHandler handler = new GatheringHandler();
+    Logger logger;
+
+    @Path("/echo")
+    public static class TracingMatchResourceMethodResource {
+        @Path("echo")
+        @POST
+        public String echo(String entity) {
+            return entity;
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(TracingMatchResourceMethodResource.class)
+                .property(ServerProperties.TRACING, TracingConfig.ALL.name())
+                .property(ServerProperties.TRACING_THRESHOLD, TracingLogger.Level.VERBOSE.name());
+    }
+
+    @Test
+    public void testEcho() {
+        logger = Logger.getLogger("org.glassfish.jersey.tracing.general");
+        logger.addHandler(handler);
+
+        try (Response r = target("echo").path("echo").request().post(Entity.entity("ECHO", MediaType.TEXT_PLAIN_TYPE))) {
+            MatcherAssert.assertThat(r.getStatus(), Matchers.equalTo(200));
+            MatcherAssert.assertThat(r.readEntity(String.class), Matchers.equalTo("ECHO"));
+        }
+
+        List<LogRecord> matched = handler.logRecords.stream()
+                .filter(logRecord -> logRecord.getMessage().startsWith(ServerTraceEvent.MATCH_RESOURCE_METHOD.name()))
+                .collect(Collectors.toList());
+        MatcherAssert.assertThat(matched.size(), Matchers.equalTo(1));
+    }
+
+    private static class GatheringHandler extends Handler {
+
+        List<LogRecord> logRecords = new ArrayList<>();
+
+        @Override
+        public void publish(LogRecord record) {
+            logRecords.add(record);
+        }
+
+        @Override
+        public void flush() {
+        }
+
+        @Override
+        public void close() throws SecurityException {
+        }
+    }
+}
diff --git a/tests/pom.xml b/tests/pom.xml
index d548897..8611c67 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -42,6 +42,7 @@
         <module>e2e-core-common</module>
         <module>e2e-entity</module>
         <module>e2e-inject</module>
+        <module>e2e-jdk-specifics</module>
         <module>e2e-server</module>
         <module>e2e-testng</module>
         <module>e2e-tls</module>
diff --git a/tests/release-test/src/test/resources/non-bom-pom-deps.xml b/tests/release-test/src/test/resources/non-bom-pom-deps.xml
index 7ced6b0..e3aca57 100644
--- a/tests/release-test/src/test/resources/non-bom-pom-deps.xml
+++ b/tests/release-test/src/test/resources/non-bom-pom-deps.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.eclipse.ee4j</groupId>
         <artifactId>project</artifactId>
-        <version>1.0.8</version>
+        <version>1.0.9</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests</groupId>
diff --git a/tests/release-test/src/test/resources/release-test-pom.xml b/tests/release-test/src/test/resources/release-test-pom.xml
index 4fac652..58966b3 100644
--- a/tests/release-test/src/test/resources/release-test-pom.xml
+++ b/tests/release-test/src/test/resources/release-test-pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2022, 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.eclipse.ee4j</groupId>
         <artifactId>project</artifactId>
-        <version>1.0.8</version>
+        <version>1.0.9</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tests</groupId>
diff --git a/tools/jersey-doc-modulelist-maven-plugin/pom.xml b/tools/jersey-doc-modulelist-maven-plugin/pom.xml
index 53df1f1..876adef 100644
--- a/tools/jersey-doc-modulelist-maven-plugin/pom.xml
+++ b/tools/jersey-doc-modulelist-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2013, 2022 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.eclipse.ee4j</groupId>
         <artifactId>project</artifactId>
-        <version>1.0.8</version>
+        <version>1.0.9</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tools.plugins</groupId>
diff --git a/tools/jersey-release-notes-maven-plugin/pom.xml b/tools/jersey-release-notes-maven-plugin/pom.xml
index 79fd77b..fa51932 100644
--- a/tools/jersey-release-notes-maven-plugin/pom.xml
+++ b/tools/jersey-release-notes-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 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
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.eclipse.ee4j</groupId>
         <artifactId>project</artifactId>
-        <version>1.0.8</version>
+        <version>1.0.9</version>
     </parent>
 
     <groupId>org.glassfish.jersey.tools.plugins</groupId>