merge of the actual 3.1 into the 3.1.JPMS
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 6e6046c..b047d80 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation
+# Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
@@ -10,7 +10,7 @@
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
-name: Jersey
+name: Eclipse Required License Check
on: [push, pull_request]
@@ -29,11 +29,11 @@
steps:
- name: Checkout for build
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4.1.0
with:
distribution: 'zulu'
java-version: ${{ matrix.java_version }}
@@ -44,7 +44,7 @@
- name: Build
run: mvn -V -U -B ${{matrix.verify_profiles}} org.eclipse.dash:license-tool-plugin:license-check -DexcludeArtifactIds=bsh,jmh-core,jmh-generator-annprocess,swing-layout -pl '!:version-agnostic'
- name: Upload license-check info
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: license-summary.txt
path: target/dash/summary
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
new file mode 100644
index 0000000..ddf4e77
--- /dev/null
+++ b/.github/workflows/validate.yml
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2024 Contributors to the Eclipse Foundation
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0,
+# or the Eclipse Distribution License v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+
+name: "Validate"
+
+on: [pull_request, push]
+
+env:
+ JAVA_VERSION: '21'
+ JAVA_DISTRO: 'temurin'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ copyright:
+ timeout-minutes: 10
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Set up JDK ${{ env.JAVA_VERSION }}
+ uses: actions/setup-java@v4.1.0
+ with:
+ distribution: ${{ env.JAVA_DISTRO }}
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: maven
+ - name: Copyright
+ run: etc/scripts/copyright.sh
+ - name: Upload copyright info
+ uses: actions/upload-artifact@v4
+ with:
+ name: copyright_results
+ path: copyright.log
+ retention-days: 5
+ checkstyle:
+ timeout-minutes: 10
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK ${{ env.JAVA_VERSION }}
+ uses: actions/setup-java@v4.1.0
+ with:
+ distribution: ${{ env.JAVA_DISTRO }}
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: maven
+ - name: Checkstyle
+ run: etc/scripts/checkstyle.sh
+ - name: Upload checkstyle info
+ uses: actions/upload-artifact@v4
+ with:
+ name: checkstyle_results
+ path: target/checkstyle/checkstyle-result.xml
+ retention-days: 5
+ apidocs:
+ timeout-minutes: 30
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4.1.0
+ with:
+ distribution: ${{ env.JAVA_DISTRO }}
+ java-version: 17
+ cache: maven
+ - name: Build JDK17+ required modules
+ run: mvn -B -U -V clean install -DskipTests -pl :jersey-helidon-connector -am
+ - name: Set up JDK ${{ env.JAVA_VERSION }}
+ uses: actions/setup-java@v4.1.0
+ with:
+ distribution: ${{ env.JAVA_DISTRO }}
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: maven
+ - name: Build ApiDocs
+ run: etc/scripts/apidocs.sh
+ archetypes:
+ timeout-minutes: 45
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK ${{ env.JAVA_VERSION }}
+ uses: actions/setup-java@v4.1.0
+ with:
+ distribution: ${{ env.JAVA_DISTRO }}
+ java-version: ${{ env.JAVA_VERSION }}
+ cache: maven
+ - name: Test archetypes
+ run: etc/scripts/test-archetypes.sh
\ No newline at end of file
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/NOTICE.md b/NOTICE.md
index 724bef4..1935ed0 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1,4 +1,4 @@
-# Notice for Jersey
+# Notice for Jersey
This content is produced and maintained by the Eclipse Jersey project.
* Project home: https://projects.eclipse.org/projects/ee4j.jersey
@@ -57,25 +57,25 @@
* Project: http://getbootstrap.com
* Copyright: 2011-2016 Twitter, Inc
-Google Guava Version 18.0
+Google Guava Version 33.3.0-jre
* License: Apache License, 2.0
-* Copyright (C) 2009 The Guava Authors
+* Copyright (C) 2009, 2024 The Guava Authors
-jakarta.inject Version: 1
+jakarta.inject Version: 2.0.1
* License: Apache License, 2.0
-* Copyright (C) 2009 The JSR-330 Expert Group
+* Copyright (C) 2009, 2021 The JSR-330 Expert Group
-Javassist Version 3.29.2-GA
+Javassist Version 3.30.2-GA
* License: Apache License, 2.0
* Project: http://www.javassist.org/
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
-Jackson JAX-RS Providers Version 2.15.3
+Jackson JAX-RS Providers Version 2.18.0
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
-* Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
+* Copyright: (c) 2009-2024 FasterXML, LLC. All rights reserved unless otherwise indicated.
-jQuery v1.12.4
+jQuery v3.7.1
* License: jquery.org/license
* Project: jquery.org
* Copyright: (c) jQuery Foundation
@@ -95,7 +95,7 @@
* Project: http://www.kineticjs.com, https://github.com/ericdrowell/KineticJS
* Copyright: Eric Rowell
-org.objectweb.asm Version 9.6
+org.objectweb.asm Version 9.7.1
* License: Modified BSD (https://asm.ow2.io/license.html)
* Copyright (c) 2000-2011 INRIA, France Telecom. All rights reserved.
diff --git a/archetypes/jersey-example-java8-webapp/pom.xml b/archetypes/jersey-example-java8-webapp/pom.xml
index 9950ec2..0deeaea 100644
--- a/archetypes/jersey-example-java8-webapp/pom.xml
+++ b/archetypes/jersey-example-java8-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
index af97394..678b7e2 100644
--- a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- 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
@@ -125,6 +125,5 @@
<properties>
<java.version>11</java.version>
<jersey.config.test.container.port>8080</jersey.config.test.container.port>
- <war.mvn.plugin.version>3.4.0</war.mvn.plugin.version>
</properties>
</project>
diff --git a/archetypes/jersey-heroku-webapp/pom.xml b/archetypes/jersey-heroku-webapp/pom.xml
index 5c30a45..98a4479 100644
--- a/archetypes/jersey-heroku-webapp/pom.xml
+++ b/archetypes/jersey-heroku-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -37,7 +37,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
- <version>2.5</version>
+ <version>${resources.mvn.plugin.version}</version>
<configuration>
<escapeString>\</escapeString>
</configuration>
diff --git a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
index 3b60fd3..edfed3d 100644
--- a/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-heroku-webapp/src/main/resources/archetype-resources/pom.xml
@@ -64,7 +64,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.1</version>
+ <version>${compiler.mvn.plugin.version}</version>
<inherited>true</inherited>
<configuration>
<source>11</source>
@@ -117,9 +117,6 @@
<properties>
<jersey.version>${project.version}</jersey.version>
- <jetty.version>12.0.3</jetty.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <surefire.mvn.plugin.version>3.2.1</surefire.mvn.plugin.version>
- <war.mvn.plugin.version>3.4.0</war.mvn.plugin.version>
</properties>
</project>
diff --git a/archetypes/jersey-quickstart-grizzly2/pom.xml b/archetypes/jersey-quickstart-grizzly2/pom.xml
index 4964159..ed7462f 100644
--- a/archetypes/jersey-quickstart-grizzly2/pom.xml
+++ b/archetypes/jersey-quickstart-grizzly2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -45,7 +45,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
- <version>${maven.resources.plugin.version}</version>
+ <version>${resources.mvn.plugin.version}</version>
<configuration>
<escapeString>\</escapeString>
</configuration>
diff --git a/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml b/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml
index e932741..58e9ba4 100644
--- a/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml
+++ b/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022 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
diff --git a/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml
index 682a44b..2690b43 100644
--- a/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
- <version>\${junit-jupiter.version}</version>
+ <version>\${junit5.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -50,13 +50,13 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.10.1</version>
+ <version>${compiler.mvn.plugin.version}</version>
<inherited>true</inherited>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
- <version>3.0.0</version>
+ <version>${exec.mvn.plugin.version}</version>
<executions>
<execution>
<goals>
@@ -79,8 +79,7 @@
<properties>
<jersey.version>${project.version}</jersey.version>
- <junit-jupiter.version>5.10.0</junit-jupiter.version>
+ <junit5.version>${junit5.version}</junit5.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <surefire.mvn.plugin.version>3.2.1</surefire.mvn.plugin.version>
</properties>
</project>
diff --git a/archetypes/jersey-quickstart-webapp/pom.xml b/archetypes/jersey-quickstart-webapp/pom.xml
index 27228bc..3ee5e7f 100644
--- a/archetypes/jersey-quickstart-webapp/pom.xml
+++ b/archetypes/jersey-quickstart-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,7 +36,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
- <version>${maven.resources.plugin.version}</version>
+ <version>${resources.mvn.plugin.version}</version>
<configuration>
<escapeString>\</escapeString>
</configuration>
diff --git a/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml b/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml
index 53d7ba6..97e49d3 100644
--- a/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml
+++ b/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022 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
diff --git a/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml
index 8de4e4d..0db4b81 100644
--- a/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml
+++ b/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml
@@ -15,7 +15,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.10.1</version>
+ <version>${compiler.mvn.plugin.version}</version>
<inherited>true</inherited>
</plugin>
<plugin>
@@ -59,6 +59,5 @@
<properties>
<jersey.version>${project.version}</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <war.mvn.plugin.version>3.4.0</war.mvn.plugin.version>
</properties>
</project>
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
index b12574c..3899e2d 100644
--- a/archetypes/pom.xml
+++ b/archetypes/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/bom/pom.xml b/bom/pom.xml
index 91ce899..5aef522 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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 c7bb57e..e2d0f86 100644
--- a/bundles/apidocs/pom.xml
+++ b/bundles/apidocs/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -63,12 +63,6 @@
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>${project.version}</version>
- <!--<exclusions>
- <exclusion>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </exclusion>
- </exclusions>-->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
@@ -131,11 +125,7 @@
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.servlet</artifactId>
- <version>3.1</version>
- </dependency>
- <dependency>
- <groupId>jakarta.persistence</groupId>
- <artifactId>jakarta.persistence-api</artifactId>
+ <version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
@@ -299,24 +289,35 @@
<fileExclude>META-INF/versions/17/org/glassfish/jersey/jetty/connector/*.java</fileExclude>
<fileExclude>META-INF/versions/17/org/glassfish/jersey/helidon/connector/*.java</fileExclude>
<fileExclude>org/glassfish/jersey/helidon/connector/*.java</fileExclude>
+ <fileExclude>org/glassfish/jersey/jetty/*.java</fileExclude>
+ <fileExclude>org/glassfish/jersey/jetty/connector/*.java</fileExclude>
<fileExclude>org/glassfish/jersey/wadl/doclet/*.java</fileExclude>
+ <fileExclude>module-info.java</fileExclude>
</sourceFileExcludes>
+ <source>${java.version}</source>
+ <disableSourcepathUsage>true</disableSourcepathUsage>
<dependencySourceIncludes>
<dependencySourceInclude>org.glassfish.jersey.*:*</dependencySourceInclude>
</dependencySourceIncludes>
- <excludePackageNames>*.internal.*:*.innate.*</excludePackageNames>
+ <excludePackageNames>*.innate:*.innate.*</excludePackageNames>
+ <legacyMode>true</legacyMode>
+ <verbose>false</verbose>
+ <debug>true</debug>
+ <detectJavaApiLink>false</detectJavaApiLink>
+ <detectLinks>false</detectLinks>
+ <doclint>none</doclint>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>exclude-jar</id>
<goals>
- <goal>remove-project-artifact</goal>
+ <goal>purge-local-repository</goal>
</goals>
</execution>
</executions>
diff --git a/bundles/examples/pom.xml b/bundles/examples/pom.xml
index 3aefefe..69f2757 100644
--- a/bundles/examples/pom.xml
+++ b/bundles/examples/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/bundles/jaxrs-ri/pom.xml b/bundles/jaxrs-ri/pom.xml
index 9b4d43f..a90dd5a 100644
--- a/bundles/jaxrs-ri/pom.xml
+++ b/bundles/jaxrs-ri/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -208,8 +208,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<inherited>false</inherited>
<configuration>
- <source>${java.version}</source>
- <target>${java.version}</target>
+ <release>${java.version}</release>
<compilerArguments>
<!-- Do not warn about using sun.misc.Unsafe -->
<XDignore.symbol.file />
@@ -217,7 +216,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,7 +315,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
- <version>3.2.4</version>
+ <version>${shade.mvn.plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
@@ -421,7 +422,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
- <version>1.0-beta-4</version>
+ <version>2.0.2</version>
<inherited>false</inherited>
<executions>
<execution>
@@ -463,6 +464,15 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>java_version</id>
+ <activation>
+ <jdk>21</jdk>
+ </activation>
+ <properties>
+ <java.version>21</java.version>
+ </properties>
+ </profile>
</profiles>
<properties>
diff --git a/bundles/pom.xml b/bundles/pom.xml
index c3f6520..2a6ce36 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/connectors/apache-connector/pom.xml b/connectors/apache-connector/pom.xml
index b429cd2..19829c2 100644
--- a/connectors/apache-connector/pom.xml
+++ b/connectors/apache-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -40,6 +40,16 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
@@ -55,6 +65,17 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>${commons.codec.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
</dependencies>
<build>
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 264c453..8af222a 100644
--- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
+++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
@@ -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
@@ -31,9 +31,11 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -58,6 +60,7 @@
import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.message.internal.HeaderUtils;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
@@ -521,7 +524,7 @@
try {
final ConnectionClosingMechanism closingMechanism = new ConnectionClosingMechanism(clientRequest, request);
- responseContext.setEntityStream(getInputStream(response, closingMechanism));
+ responseContext.setEntityStream(getInputStream(response, closingMechanism, () -> clientRequest.isCancelled()));
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, null, e);
}
@@ -730,17 +733,19 @@
}
private static InputStream getInputStream(final CloseableHttpResponse response,
- final ConnectionClosingMechanism closingMechanism) throws IOException {
+ final ConnectionClosingMechanism closingMechanism,
+ final Supplier<Boolean> isCancelled) throws IOException {
final InputStream inputStream;
if (response.getEntity() == null) {
inputStream = new ByteArrayInputStream(new byte[0]);
} else {
- final InputStream i = response.getEntity().getContent();
+ final InputStream i = new CancellableInputStream(response.getEntity().getContent(), isCancelled);
if (i.markSupported()) {
inputStream = i;
} else {
- inputStream = new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
+ inputStream = ReaderWriter.AUTOSIZE_BUFFER ? new BufferedInputStream(i)
+ : new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
}
}
@@ -879,10 +884,34 @@
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).build();
sniConfig.setSNIServerName(socket);
}
}
}
}
+
+ private static class CancellableInputStream extends InputStreamWrapper {
+ private final InputStream in;
+ private final Supplier<Boolean> isCancelled;
+
+ private CancellableInputStream(InputStream in, Supplier<Boolean> isCancelled) {
+ this.in = in;
+ this.isCancelled = isCancelled;
+ }
+
+ @Override
+ protected InputStream getWrapped() {
+ return in;
+ }
+
+ @Override
+ protected InputStream getWrappedIOE() throws IOException {
+ if (isCancelled.get()) {
+ throw new IOException(new CancellationException());
+ }
+ return in;
+ }
+ }
}
diff --git a/connectors/apache5-connector/pom.xml b/connectors/apache5-connector/pom.xml
index 825bcc8..0181c22 100644
--- a/connectors/apache5-connector/pom.xml
+++ b/connectors/apache5-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/connectors/apache5-connector/src/main/java/module-info.java b/connectors/apache5-connector/src/main/java/module-info.java
index 33af279..ab997c4 100644
--- a/connectors/apache5-connector/src/main/java/module-info.java
+++ b/connectors/apache5-connector/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -14,7 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-module org.glassfish.jersey.apache.connector {
+module org.glassfish.jersey.apache5.connector {
requires java.logging;
requires jakarta.ws.rs;
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 f7c30a9..99e5c7a 100644
--- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
+++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
@@ -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
@@ -32,8 +32,10 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
+import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -103,6 +105,7 @@
import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.message.internal.HeaderUtils;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
@@ -519,7 +522,7 @@
final HttpEntity entity = response.getEntity();
if (entity != null) {
- if (headers.get(HttpHeaders.CONTENT_LENGTH) == null) {
+ if (headers.get(HttpHeaders.CONTENT_LENGTH) == null && entity.getContentLength() >= 0) {
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getContentLength()));
}
@@ -531,7 +534,7 @@
try {
final ConnectionClosingMechanism closingMechanism = new ConnectionClosingMechanism(clientRequest, request);
- responseContext.setEntityStream(getInputStream(response, closingMechanism));
+ responseContext.setEntityStream(getInputStream(response, closingMechanism, () -> clientRequest.isCancelled()));
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, null, e);
}
@@ -741,17 +744,19 @@
}
private static InputStream getInputStream(final CloseableHttpResponse response,
- final ConnectionClosingMechanism closingMechanism) throws IOException {
+ final ConnectionClosingMechanism closingMechanism,
+ final Supplier<Boolean> isCancelled) throws IOException {
final InputStream inputStream;
if (response.getEntity() == null) {
inputStream = new ByteArrayInputStream(new byte[0]);
} else {
- final InputStream i = response.getEntity().getContent();
+ final InputStream i = new CancellableInputStream(response.getEntity().getContent(), isCancelled);
if (i.markSupported()) {
inputStream = i;
} else {
- inputStream = new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
+ inputStream = ReaderWriter.AUTOSIZE_BUFFER ? new BufferedInputStream(i)
+ : new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
}
}
@@ -878,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).build();
sniConfig.setSNIServerName(socket);
final int socketTimeout = ((ClientRequest) objectRequest).resolveProperty(ClientProperties.READ_TIMEOUT, -1);
@@ -889,4 +895,28 @@
}
}
}
+
+ private static class CancellableInputStream extends InputStreamWrapper {
+ private final InputStream in;
+ private final Supplier<Boolean> isCancelled;
+
+ private CancellableInputStream(InputStream in, Supplier<Boolean> isCancelled) {
+ this.in = in;
+ this.isCancelled = isCancelled;
+ }
+
+ @Override
+ protected InputStream getWrapped() {
+ return in;
+ }
+
+ @Override
+ protected InputStream getWrappedIOE() throws IOException {
+ if (isCancelled.get()) {
+ throw new IOException(new CancellationException());
+ }
+ return in;
+ }
+ }
+
}
diff --git a/connectors/apache5-connector/src/test/java/module-info.java b/connectors/apache5-connector/src/test/java/module-info.java
index 4545e85..9351a82 100644
--- a/connectors/apache5-connector/src/test/java/module-info.java
+++ b/connectors/apache5-connector/src/test/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -14,7 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-module org.glassfish.jersey.apache.connector.test {
+module org.glassfish.jersey.apache5.connector.test {
requires java.logging;
requires jakarta.inject;
@@ -26,7 +26,7 @@
requires org.glassfish.jersey.core.client;
requires org.glassfish.jersey.core.server;
- requires org.glassfish.jersey.apache.connector;
+ requires org.glassfish.jersey.apache5.connector;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.grizzly;
diff --git a/connectors/grizzly-connector/pom.xml b/connectors/grizzly-connector/pom.xml
index 852a203..5ec9ef8 100644
--- a/connectors/grizzly-connector/pom.xml
+++ b/connectors/grizzly-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/connectors/helidon-connector/pom.xml b/connectors/helidon-connector/pom.xml
index daaf815..930f8ce 100644
--- a/connectors/helidon-connector/pom.xml
+++ b/connectors/helidon-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,13 +36,14 @@
<java8.sourceDirectory>${project.basedir}/src/main/java8</java8.sourceDirectory>
<java17.build.outputDirectory>${project.basedir}/target17</java17.build.outputDirectory>
<java17.sourceDirectory>${project.basedir}/src/main/java17</java17.sourceDirectory>
+ <javadoc.skip>${maven.javadoc.skip}</javadoc.skip>
</properties>
<dependencies>
<dependency>
<groupId>io.helidon.jersey</groupId>
<artifactId>helidon-jersey-connector</artifactId>
- <version>${helidon.jersey.connector.version}</version>
+ <version>${helidon.connector.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -80,8 +81,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
- <source>8</source>
- <detectJavaApiLink>false</detectJavaApiLink>
+ <skip>${javadoc.skip}</skip>
</configuration>
</plugin>
</plugins>
@@ -93,6 +93,9 @@
<activation>
<jdk>[1.8,17)</jdk>
</activation>
+ <properties>
+ <javadoc.skip>true</javadoc.skip>
+ </properties>
<build>
<directory>${java8.build.outputDirectory}</directory>
<plugins>
diff --git a/connectors/jdk-connector/pom.xml b/connectors/jdk-connector/pom.xml
index 39b1bd7..55be765 100644
--- a/connectors/jdk-connector/pom.xml
+++ b/connectors/jdk-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -92,6 +92,27 @@
</build>
<profiles>
+ <profile> <!-- we still require JDK 1.8 TLS 1.3 limitations -->
+ <id>jdk8</id>
+ <activation>
+ <jdk>(,9)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <reuseForks>false</reuseForks>
+ <excludes>
+ <exclude>**/SslFilterTLS13Test.java</exclude>
+ <exclude>**/SslFilterTLS13UrlStoresTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
<profile>
<id>disable_tls1and11</id>
<!-- TLS 1 and TLS 1.1 are disabled for JDK 16 -->
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..6099e8e 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;
@@ -514,8 +514,15 @@
}
return;
+ } else if (httpResponse.getHasContent()) {
+ // missing Content-Length
+ transferEncodingParser = TransferEncodingParser
+ .createFixedLengthParser(httpResponse.getBodyStream(), Long.MAX_VALUE);
+ return;
}
+
+
// TODO what now? Expect no content or fail loudly?
}
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..1a94ff7 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;
}
@@ -63,7 +63,7 @@
responseBody.notifyDataAvailable(parsed);
consumedLength += data.length;
- return consumedLength == expectedLength;
+ return consumedLength == expectedLength || expectedLength == Long.MAX_VALUE /* unknown at the beginning */;
}
}
diff --git a/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTLS13UrlStoresTest.java b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTLS13UrlStoresTest.java
new file mode 100644
index 0000000..b8e96c0
--- /dev/null
+++ b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTLS13UrlStoresTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.jdk.connector.internal;
+
+import org.glassfish.jersey.SslConfigurator;
+
+public class SslFilterTLS13UrlStoresTest extends SslFilterTest {
+
+ public SslFilterTLS13UrlStoresTest() {
+ System.setProperty("jdk.tls.server.protocols", "TLSv1.3");
+ System.setProperty("jdk.tls.client.protocols", "TLSv1.3");
+ }
+
+ @Override
+ protected SslConfigurator getSslConfigurator() {
+ return SslConfigurator.newInstance()
+ .trustStoreUrl(this.getClass().getResource("/truststore_client"))
+ .trustStorePassword("asdfgh")
+ .keyStoreUrl(this.getClass().getResource("/keystore_client"))
+ .keyStorePassword("asdfgh");
+ }
+}
diff --git a/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java
index ef13997..7f3b00a 100644
--- a/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java
+++ b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.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
@@ -388,11 +388,7 @@
final CountDownLatch completionLatch,
HostnameVerifier customHostnameVerifier)
throws Throwable {
- SslConfigurator sslConfig = SslConfigurator.newInstance()
- .trustStoreFile(this.getClass().getResource("/truststore_client").getPath())
- .trustStorePassword("asdfgh")
- .keyStoreFile(this.getClass().getResource("/keystore_client").getPath())
- .keyStorePassword("asdfgh");
+ SslConfigurator sslConfig = getSslConfigurator();
TransportFilter transportFilter = new TransportFilter(17_000, ThreadPoolConfig.defaultConfig(), 100_000);
final SSLParamConfigurator sslParamConfigurator = SSLParamConfigurator.builder()
@@ -481,6 +477,14 @@
return clientSocket;
}
+ protected SslConfigurator getSslConfigurator() {
+ return SslConfigurator.newInstance()
+ .trustStoreFile(this.getClass().getResource("/truststore_client").getPath())
+ .trustStorePassword("asdfgh")
+ .keyStoreFile(this.getClass().getResource("/keystore_client").getPath())
+ .keyStorePassword("asdfgh");
+ }
+
/**
* SSL echo server. It expects a message to be terminated with \n.
*/
diff --git a/connectors/jetty-connector/pom.xml b/connectors/jetty-connector/pom.xml
index cdd1f0e..7f2b377 100644
--- a/connectors/jetty-connector/pom.xml
+++ b/connectors/jetty-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -45,17 +45,6 @@
<dependencies>
<dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-client</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${project.version}</version>
@@ -107,6 +96,11 @@
<version>${jetty.servlet.api.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
</dependencies>
<build>
@@ -150,6 +144,18 @@
<properties>
<jetty.version>${jetty11.version}</jetty.version>
</properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
<build>
<directory>${java11.build.outputDirectory}</directory>
<plugins>
@@ -187,6 +193,18 @@
<activation>
<jdk>[17,)</jdk>
</activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
<build>
<directory>${java17.build.outputDirectory}</directory>
<plugins>
diff --git a/connectors/jetty-connector/src/main/java/module-info.java b/connectors/jetty-connector/src/main/java/module-info.java
index 1c9c76f..41d7d8c 100644
--- a/connectors/jetty-connector/src/main/java/module-info.java
+++ b/connectors/jetty-connector/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,6 +16,7 @@
module org.glassfish.jersey.jetty.connector {
requires java.logging;
+ requires org.slf4j;
requires jakarta.ws.rs;
diff --git a/connectors/jetty-http2-connector/pom.xml b/connectors/jetty-http2-connector/pom.xml
index adc7d54..1293426 100644
--- a/connectors/jetty-http2-connector/pom.xml
+++ b/connectors/jetty-http2-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -44,10 +44,22 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
@@ -159,10 +171,22 @@
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>jetty-http2-client</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>jetty-http2-client-transport</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
diff --git a/connectors/jetty11-connector/pom.xml b/connectors/jetty11-connector/pom.xml
index a57b94f..b83092e 100644
--- a/connectors/jetty11-connector/pom.xml
+++ b/connectors/jetty11-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -151,6 +151,13 @@
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <configuration>
+ <rulesToSkip>dependencyConvergence</rulesToSkip>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
\ No newline at end of file
diff --git a/connectors/jnh-connector/pom.xml b/connectors/jnh-connector/pom.xml
index 5f7e685..3b1cd60 100644
--- a/connectors/jnh-connector/pom.xml
+++ b/connectors/jnh-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
index 69d25eb..57296c6 100644
--- a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -360,24 +360,30 @@
@Override
public int read() throws IOException {
lock.lock();
- final int r = zero != -1 ? zero : inner.read();
- zero = -1;
- lock.unlock();
- return r;
+ try {
+ final int r = zero != -1 ? zero : inner.read();
+ zero = -1;
+ return r;
+ } finally {
+ lock.unlock();
+ }
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
lock.lock();
int r;
- if (zero != -1) {
- b[off] = (byte) (zero & 0xFF);
- r = inner.read(b, off + 1, len - 1);
- } else {
- r = inner.read(b, off, len);
+ try {
+ if (zero != -1) {
+ b[off] = (byte) (zero & 0xFF);
+ r = inner.read(b, off + 1, len - 1);
+ } else {
+ r = inner.read(b, off, len);
+ }
+ zero = -1;
+ } finally {
+ lock.unlock();
}
- zero = -1;
- lock.unlock();
return r;
}
@@ -385,23 +391,24 @@
@Override
public int available() throws IOException {
lock.lock();
- if (zero != -1) {
- lock.unlock();
- return 1;
- }
+ try {
+ if (zero != -1) {
+ return 1;
+ }
- int available = inner.available();
- if (available != 1) {
- lock.unlock();
+ int available = inner.available();
+ if (available != 1) {
+ return available;
+ }
+
+ zero = inner.read();
+ if (zero == -1) {
+ available = 0;
+ }
return available;
+ } finally {
+ lock.unlock();
}
-
- zero = inner.read();
- if (zero == -1) {
- available = 0;
- }
- lock.unlock();
- return available;
}
@Override
@@ -418,10 +425,14 @@
}
@Override
- public synchronized void mark(int readlimit) {
+ public void mark(int readlimit) {
inner.mark(readlimit);
}
+ @Override
+ public void reset() throws IOException {
+ inner.reset();
+ }
}
}
diff --git a/connectors/netty-connector/pom.xml b/connectors/netty-connector/pom.xml
index 92c0896..e540f9c 100644
--- a/connectors/netty-connector/pom.xml
+++ b/connectors/netty-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -34,6 +34,14 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <surefire.coverage.argline>
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
+ --add-opens java.base/java.lang=org.glassfish.jersey.netty.connector
+ --add-opens java.base/java.lang.reflect=org.glassfish.jersey.netty.connector
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
</properties>
<dependencies>
@@ -55,6 +63,17 @@
<version>${project.version}</version>
<!-- <scope>test</scope>-->
</dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-jetty</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
@@ -81,4 +100,25 @@
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>JettyExclude</id>
+ <activation>
+ <jdk>(1.8,17)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <testExcludes>
+ <testExclude>org/glassfish/jersey/netty/connector/HugeHeaderTest.java</testExclude>
+ </testExcludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java
index 87551dd..398fd2e 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,13 +17,13 @@
package org.glassfish.jersey.netty.connector;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
@@ -46,7 +46,6 @@
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpResponse;
-import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.timeout.IdleStateEvent;
import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
@@ -97,6 +96,8 @@
if (readTimedOut) {
responseDone.completeExceptionally(new TimeoutException("Stream closed: read timeout"));
+ } else if (jerseyRequest.isCancelled()) {
+ responseDone.completeExceptionally(new CancellationException());
} else {
responseDone.completeExceptionally(new IOException("Stream closed"));
}
@@ -142,7 +143,21 @@
ClientRequest newReq = new ClientRequest(jerseyRequest);
newReq.setUri(newUri);
restrictRedirectRequest(newReq, cr);
- connector.execute(newReq, redirectUriHistory, responseAvailable);
+
+ final NettyConnector newConnector = new NettyConnector(newReq.getClient());
+ newConnector.execute(newReq, redirectUriHistory, new CompletableFuture<ClientResponse>() {
+ @Override
+ public boolean complete(ClientResponse value) {
+ newConnector.close();
+ return responseAvailable.complete(value);
+ }
+
+ @Override
+ public boolean completeExceptionally(Throwable ex) {
+ newConnector.close();
+ return responseAvailable.completeExceptionally(ex);
+ }
+ });
}
} catch (IllegalArgumentException e) {
responseAvailable.completeExceptionally(
@@ -157,6 +172,10 @@
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
+ if (jerseyRequest.isCancelled()) {
+ responseAvailable.completeExceptionally(new CancellationException());
+ return;
+ }
if (msg instanceof HttpResponse) {
final HttpResponse response = (HttpResponse) msg;
jerseyResponse = new ClientResponse(new Response.StatusType() {
@@ -181,21 +200,10 @@
}
// request entity handling.
- if ((response.headers().contains(HttpHeaders.CONTENT_LENGTH) && HttpUtil.getContentLength(response) > 0)
- || HttpUtil.isTransferEncodingChunked(response)) {
+ nis = new NettyInputStream();
+ responseDone.whenComplete((_r, th) -> nis.complete(th));
- nis = new NettyInputStream();
- responseDone.whenComplete((_r, th) -> nis.complete(th));
-
- jerseyResponse.setEntityStream(nis);
- } else {
- jerseyResponse.setEntityStream(new InputStream() {
- @Override
- public int read() throws IOException {
- return -1;
- }
- });
- }
+ jerseyResponse.setEntityStream(nis);
}
if (msg instanceof HttpContent) {
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
index 8bceac6..bdede02 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyExpectContinueHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -59,7 +59,8 @@
ctx.pipeline().remove(JerseyExpectContinueHandler.class);
}
} else {
- if (!isExpected) {
+ if (!isExpected
+ && ctx.pipeline().context(JerseyExpectContinueHandler.class) != null) {
ctx.pipeline().remove(JerseyExpectContinueHandler.class);
}
ctx.fireChannelRead(msg); //bypass the message to the next handler in line
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
index 9c79d12..562edad 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -129,4 +129,56 @@
public static final Integer
DEFAULT_EXPECT_100_CONTINUE_TIMEOUT_VALUE = 500;
+
+ /**
+ * Parameter which allows extending of the header size for the Netty connector
+ *
+ * @since 2.44
+ */
+ public static final String
+ MAX_HEADER_SIZE = "jersey.config.client.netty.maxHeaderSize";
+
+ /**
+ * Default header size for Netty Connector.
+ * Taken from {@link io.netty.handler.codec.http.HttpClientCodec#HttpClientCodec(int, int, int)}
+ *
+ * @since 2.44
+ */
+ public static final Integer
+ DEFAULT_HEADER_SIZE = 8192;
+
+ /**
+ * Parameter which allows extending of the initial line length for the Netty connector
+ *
+ * @since 2.44
+ */
+ public static final String
+ MAX_INITIAL_LINE_LENGTH = "jersey.config.client.netty.maxInitialLineLength";
+
+ /**
+ * Default initial line length for Netty Connector.
+ * Taken from {@link io.netty.handler.codec.http.HttpClientCodec#HttpClientCodec(int, int, int)}
+ *
+ * @since 2.44
+ */
+ public static final Integer
+ DEFAULT_INITIAL_LINE_LENGTH = 4096;
+
+ /**
+ * Parameter which allows extending of the chunk size for the Netty connector
+ *
+ * @since 2.44
+ */
+ public static final String
+ MAX_CHUNK_SIZE = "jersey.config.client.netty.maxChunkSize";
+
+ /**
+ * Default chunk size for Netty Connector.
+ * Taken from {@link io.netty.handler.codec.http.HttpClientCodec#HttpClientCodec(int, int, int)}
+ *
+ * @since 2.44
+ */
+ public static final Integer
+ DEFAULT_CHUNK_SIZE = 8192;
+
}
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..ebdfda4 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
@@ -34,7 +34,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -89,6 +88,10 @@
import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+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.OutboundMessageContext;
import org.glassfish.jersey.netty.connector.internal.NettyEntityWriter;
@@ -104,6 +107,17 @@
final Client client;
final HashMap<String, ArrayList<Channel>> connections = new HashMap<>();
+ private static final LazyValue<String> NETTY_VERSION = Values.lazy(
+ (Value<String>) () -> {
+ String nettyVersion = null;
+ try {
+ nettyVersion = io.netty.util.Version.identify().values().iterator().next().artifactVersion();
+ } catch (Throwable t) {
+ nettyVersion = "4.1.x";
+ }
+ return "Netty " + nettyVersion;
+ });
+
// If HTTP keepalive is enabled the value of "http.maxConnections" determines the maximum number
// of idle connections that will be simultaneously kept alive, per destination.
private static final String HTTP_KEEPALIVE_STRING = System.getProperty("http.keepAlive");
@@ -130,14 +144,15 @@
NettyConnector(Client client) {
- final Map<String, Object> properties = client.getConfiguration().getProperties();
+ final Configuration configuration = client.getConfiguration();
+ final Map<String, Object> properties = configuration.getProperties();
final Object threadPoolSize = properties.get(ClientProperties.ASYNC_THREADPOOL_SIZE);
if (threadPoolSize != null && threadPoolSize instanceof Integer && (Integer) threadPoolSize > 0) {
- executorService = Executors.newFixedThreadPool((Integer) threadPoolSize);
+ executorService = VirtualThreadUtil.withConfig(configuration).newFixedThreadPool((Integer) threadPoolSize);
this.group = new NioEventLoopGroup((Integer) threadPoolSize);
} else {
- executorService = Executors.newCachedThreadPool();
+ executorService = VirtualThreadUtil.withConfig(configuration).newCachedThreadPool();
this.group = new NioEventLoopGroup();
}
@@ -208,7 +223,7 @@
try {
final SSLParamConfigurator sslConfig = SSLParamConfigurator.builder()
- .request(jerseyRequest).setSNIAlways(true).build();
+ .request(jerseyRequest).setSNIAlways(true).setSNIHostName(jerseyRequest).build();
String key = requestUri.getScheme() + "://" + sslConfig.getSNIHostName() + ":" + port;
ArrayList<Channel> conns;
@@ -303,7 +318,17 @@
p.addLast(sslHandler);
}
- p.addLast(new HttpClientCodec());
+ final Integer maxHeaderSize = ClientProperties.getValue(config.getProperties(),
+ NettyClientProperties.MAX_HEADER_SIZE,
+ NettyClientProperties.DEFAULT_HEADER_SIZE);
+ final Integer maxChunkSize = ClientProperties.getValue(config.getProperties(),
+ NettyClientProperties.MAX_CHUNK_SIZE,
+ NettyClientProperties.DEFAULT_CHUNK_SIZE);
+ final Integer maxInitialLineLength = ClientProperties.getValue(config.getProperties(),
+ NettyClientProperties.MAX_INITIAL_LINE_LENGTH,
+ NettyClientProperties.DEFAULT_INITIAL_LINE_LENGTH);
+
+ p.addLast(new HttpClientCodec(maxInitialLineLength, maxHeaderSize, maxChunkSize));
p.addLast(new ChunkedWriteHandler());
p.addLast(new HttpContentDecompressor());
}
@@ -391,11 +416,7 @@
// headers
if (!jerseyRequest.hasEntity()) {
setHeaders(jerseyRequest, nettyRequest.headers(), false);
-
- // host header - http 1.1
- if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
- nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
- }
+ setHostHeader(jerseyRequest, nettyRequest);
}
if (jerseyRequest.hasEntity()) {
@@ -411,7 +432,7 @@
};
ch.closeFuture().addListener(closeListener);
- final NettyEntityWriter entityWriter = NettyEntityWriter.getInstance(jerseyRequest, ch);
+ final NettyEntityWriter entityWriter = nettyEntityWriter(jerseyRequest, ch);
switch (entityWriter.getType()) {
case CHUNKED:
HttpUtil.setTransferEncodingChunked(nettyRequest, true);
@@ -443,9 +464,7 @@
@Override
public OutputStream getOutputStream(int contentLength) throws IOException {
replaceHeaders(jerseyRequest, nettyRequest.headers()); // WriterInterceptor changes
- if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
- nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
- }
+ setHostHeader(jerseyRequest, nettyRequest);
headersSet.countDown();
return entityWriter.getOutputStream();
@@ -499,6 +518,10 @@
}
}
+ /* package */ NettyEntityWriter nettyEntityWriter(ClientRequest clientRequest, Channel channel) {
+ return NettyEntityWriter.getInstance(clientRequest, channel);
+ }
+
private SSLContext getSslContext(Client client, ClientRequest request) {
Supplier<SSLContext> supplier = request.resolveProperty(ClientProperties.SSL_CONTEXT_SUPPLIER, Supplier.class);
return supplier == null ? client.getSslContext() : supplier.get();
@@ -514,7 +537,7 @@
@Override
public String getName() {
- return "Netty 4.1.x";
+ return NETTY_VERSION.get();
}
@Override
@@ -591,4 +614,18 @@
private static boolean additionalProxyHeadersToKeep(String key) {
return key.length() > 2 && (key.charAt(0) == 'x' || key.charAt(0) == 'X') && (key.charAt(1) == '-');
}
+
+ private static void setHostHeader(ClientRequest jerseyRequest, HttpRequest nettyRequest) {
+ // host header - http 1.1
+ if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
+ int requestPort = jerseyRequest.getUri().getPort();
+ final String hostHeader;
+ if (requestPort != 80 && requestPort != 443) {
+ hostHeader = jerseyRequest.getUri().getHost() + ":" + requestPort;
+ } else {
+ hostHeader = jerseyRequest.getUri().getHost();
+ }
+ nettyRequest.headers().add(HttpHeaderNames.HOST, hostHeader);
+ }
+ }
}
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/JerseyChunkedInput.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/JerseyChunkedInput.java
index ad6da7e..4ffe52e 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/JerseyChunkedInput.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/JerseyChunkedInput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2020 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
@@ -101,7 +101,15 @@
@Override
public ByteBuf readChunk(ByteBufAllocator allocator) throws Exception {
+ try {
+ return readChunk0(allocator);
+ } catch (Exception e) {
+ closeOnThrowable();
+ throw e;
+ }
+ }
+ private ByteBuf readChunk0(ByteBufAllocator allocator) throws Exception {
if (!open) {
return null;
}
@@ -143,6 +151,14 @@
return offset;
}
+ private void closeOnThrowable() {
+ try {
+ close();
+ } catch (Throwable t) {
+ // do not throw other throwable
+ }
+ }
+
@Override
public void close() throws IOException {
@@ -208,10 +224,12 @@
try {
boolean queued = queue.offer(bufferSupplier.get(), WRITE_TIMEOUT, TimeUnit.MILLISECONDS);
if (!queued) {
+ closeOnThrowable();
throw new IOException("Buffer overflow.");
}
} catch (InterruptedException e) {
+ closeOnThrowable();
throw new IOException(e);
}
}
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java
index a9e7040..bcd3fd8 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.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
@@ -24,8 +24,10 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* The Entity Writer is used to write entity in Netty. One implementation is delayed,
@@ -196,10 +198,7 @@
for (Runnable runnable : delayedOps) {
runnable.run();
}
-
- if (outputStream.b != null) {
- writer.getOutputStream().write(outputStream.b, outputStream.off, outputStream.len);
- }
+ outputStream._flush();
}
}
@@ -216,7 +215,7 @@
@Override
public long getLength() {
- return outputStream.len - outputStream.off;
+ return outputStream.writeLen;
}
@Override
@@ -225,9 +224,9 @@
}
private class DelayedOutputStream extends OutputStream {
- private byte[] b;
- private int off;
- private int len;
+ private final List<WriteAction> actions = new ArrayList<>();
+ private int writeLen = 0;
+ private AtomicBoolean streamFlushed = new AtomicBoolean(false);
@Override
public void write(int b) throws IOException {
@@ -241,15 +240,39 @@
@Override
public void write(byte[] b, int off, int len) throws IOException {
- if (!flushed && this.b == null) {
- this.b = b;
- this.off = off;
- this.len = len;
+ if (!flushed) {
+ actions.add(new WriteAction(b, off, len));
+ writeLen += len;
} else {
- DelayedEntityWriter.this._flush();
+ _flush();
writer.getOutputStream().write(b, off, len);
+ writer.getOutputStream().flush();
}
}
+
+ public void _flush() throws IOException {
+ if (streamFlushed.compareAndSet(false, true)) {
+ DelayedEntityWriter.this._flush();
+ for (WriteAction action : actions) {
+ action.run();
+ }
+ actions.clear();
+ }
+ }
+ }
+
+ private class WriteAction {
+ private final byte[] b;
+
+ private WriteAction(byte[] b, int off, int len) {
+ this.b = new byte[len]; // b passed in can be reused
+ System.arraycopy(b, off, this.b, 0, len);
+ }
+
+ public void run() throws IOException {
+ writer.getOutputStream().write(b, 0, b.length);
+ writer.getOutputStream().flush();
+ }
}
}
}
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/ChunkedInputWriteErrorSimulationTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/ChunkedInputWriteErrorSimulationTest.java
new file mode 100644
index 0000000..78a3448
--- /dev/null
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/ChunkedInputWriteErrorSimulationTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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.netty.connector;
+
+import io.netty.channel.Channel;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.netty.connector.internal.JerseyChunkedInput;
+import org.glassfish.jersey.netty.connector.internal.NettyEntityWriter;
+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.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.Response;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class ChunkedInputWriteErrorSimulationTest extends JerseyTest {
+ private static final String EXCEPTION_MSG = "BOGUS BUFFER OVERFLOW";
+ private static final AtomicReference<Throwable> caught = new AtomicReference<>(null);
+
+ public static class ClientThread extends Thread {
+
+ public static AtomicInteger count = new AtomicInteger();
+ public static String url;
+ public static int nLoops;
+
+ private static Client client;
+
+ public static void main(DequeOffer offer, String[] args) throws InterruptedException {
+ url = args[0];
+ int nThreads = Integer.parseInt(args[1]);
+ nLoops = Integer.parseInt(args[2]);
+ initClient(offer);
+ Thread[] threads = new Thread[nThreads];
+ for (int i = 0; i < nThreads; i++) {
+ threads[i] = new ClientThread();
+ threads[i].start();
+ }
+
+ for (int i = 0; i < nThreads; i++) {
+ threads[i].join();
+ }
+ // System.out.println("Processed calls: " + count);
+ }
+
+ private static void initClient(DequeOffer offer) {
+ ClientConfig defaultConfig = new ClientConfig();
+ defaultConfig.property(ClientProperties.CONNECT_TIMEOUT, 10 * 1000);
+ defaultConfig.property(ClientProperties.READ_TIMEOUT, 10 * 1000);
+ defaultConfig.connectorProvider(getJerseyChunkedInputModifiedNettyConnector(offer));
+ client = ClientBuilder.newBuilder()
+ .withConfig(defaultConfig)
+ .build();
+ }
+
+ public void doCall() {
+ CompletableFuture<Response> cf = invokeResponse().toCompletableFuture()
+ .whenComplete((rsp, t) -> {
+ if (t != null) {
+// System.out.println(Thread.currentThread() + " async complete. Caught exception " + t);
+// t.printStackTrace();
+ while (t.getCause() != null) {
+ t = t.getCause();
+ }
+ caught.set(t);
+ }
+ })
+ .handle((rsp, t) -> {
+ if (rsp != null) {
+ rsp.readEntity(String.class);
+ } else {
+ System.out.println(Thread.currentThread().getName() + " response is null");
+ }
+ return rsp;
+ }).exceptionally(t -> {
+ System.out.println("async complete. completed exceptionally " + t);
+ throw new RuntimeException(t);
+ });
+
+ try {
+ cf.get();
+ System.out.println("Done call " + count.incrementAndGet());
+ } catch (InterruptedException | ExecutionException ex) {
+ Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private static CompletionStage<Response> invokeResponse() {
+ WebTarget target = client.target(url);
+ MultivaluedHashMap hdrs = new MultivaluedHashMap<>();
+ StringBuilder sb = new StringBuilder("{");
+ for (int i = 0; i < 10000; i++) {
+ sb.append("\"fname\":\"foo\", \"lname\":\"bar\"");
+ }
+ sb.append("}");
+ String jsonPayload = sb.toString();
+ Invocation.Builder builder = ((WebTarget) target).request().headers(hdrs);
+ return builder.rx().method("POST", Entity.entity(jsonPayload, MediaType.APPLICATION_JSON_TYPE));
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < nLoops; i++) {
+ try {
+ doCall();
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+ }
+ }
+
+ @Path("/console")
+ public static class HangingEndpoint {
+ @Path("/login")
+ @POST
+ public String post(String entity) {
+ return "Welcome";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HangingEndpoint.class);
+ }
+
+ @Test
+ public void testNoHangOnOfferInterrupt() throws InterruptedException {
+ String path = getBaseUri() + "console/login";
+ ClientThread.main(new InterruptedExceptionOffer(), new String[] {path, "5", "10"});
+ Assertions.assertTrue(caught.get().getMessage().contains(EXCEPTION_MSG));
+ }
+
+ @Test
+ public void testNoHangOnPollInterrupt() throws InterruptedException {
+ String path = getBaseUri() + "console/login";
+ ClientThread.main(new DequePoll(), new String[] {path, "5", "10"});
+ Assertions.assertNotNull(caught.get());
+ }
+
+ @Test
+ public void testNoHangOnOfferNoData() throws InterruptedException {
+ String path = getBaseUri() + "console/login";
+ ClientThread.main(new ReturnFalseOffer(), new String[] {path, "5", "10"});
+ Assertions.assertTrue(caught.get().getMessage().contains("Buffer overflow")); //JerseyChunkedInput
+ Thread.sleep(1_000L); // Sleep for the server to finish
+ }
+
+ private interface DequeOffer {
+ public boolean offer(ByteBuffer e, long timeout, TimeUnit unit) throws InterruptedException;
+ }
+
+ private static class InterruptedExceptionOffer implements DequeOffer {
+ private AtomicInteger ai = new AtomicInteger(0);
+
+ @Override
+ public boolean offer(ByteBuffer e, long timeout, TimeUnit unit) throws InterruptedException {
+ if ((ai.getAndIncrement() % 10) == 0) {
+ throw new InterruptedException(EXCEPTION_MSG);
+ }
+ return true;
+ }
+ }
+
+ private static class ReturnFalseOffer implements DequeOffer {
+ private AtomicInteger ai = new AtomicInteger(0);
+ @Override
+ public boolean offer(ByteBuffer e, long timeout, TimeUnit unit) throws InterruptedException {
+ return !((ai.getAndIncrement() % 10) == 1);
+ }
+ }
+
+ private static class DequePoll extends InterruptedExceptionOffer {
+ }
+
+
+ private static ConnectorProvider getJerseyChunkedInputModifiedNettyConnector(DequeOffer offer) {
+ return new ConnectorProvider() {
+ @Override
+ public Connector getConnector(Client client, Configuration runtimeConfig) {
+ return new NettyConnector(client) {
+ NettyEntityWriter nettyEntityWriter(ClientRequest clientRequest, Channel channel) {
+ NettyEntityWriter wrapped = NettyEntityWriter.getInstance(clientRequest, channel);
+
+ JerseyChunkedInput chunkedInput = (JerseyChunkedInput) wrapped.getChunkedInput();
+ try {
+ Field field = JerseyChunkedInput.class.getDeclaredField("queue");
+ field.setAccessible(true);
+
+ removeFinal(field);
+
+ field.set(chunkedInput, new LinkedBlockingDeque<ByteBuffer>() {
+ @Override
+ public boolean offer(ByteBuffer e, long timeout, TimeUnit unit) throws InterruptedException {
+ if (!DequePoll.class.isInstance(offer) && !offer.offer(e, timeout, unit)) {
+ return false;
+ }
+ return super.offer(e, timeout, unit);
+ }
+
+ @Override
+ public ByteBuffer poll(long timeout, TimeUnit unit) throws InterruptedException {
+ if (DequePoll.class.isInstance(offer)) {
+ offer.offer(null, timeout, unit);
+ }
+ return super.poll(timeout, unit);
+ }
+ });
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ NettyEntityWriter proxy = (NettyEntityWriter) Proxy.newProxyInstance(
+ ConnectorProvider.class.getClassLoader(), new Class[]{NettyEntityWriter.class},
+ (proxy1, method, args) -> {
+ if (method.getName().equals("readChunk")) {
+ try {
+ return method.invoke(wrapped, args);
+ } catch (RuntimeException e) {
+ // consume
+ }
+ }
+ return method.invoke(wrapped, args);
+ });
+ return proxy;
+ }
+ };
+ }
+ };
+ }
+
+ public static void removeFinal(Field field) throws RuntimeException {
+ try {
+ Method[] classMethods = Class.class.getDeclaredMethods();
+ Method declaredFieldMethod = Arrays
+ .stream(classMethods).filter(x -> Objects.equals(x.getName(), "getDeclaredFields0"))
+ .findAny().orElseThrow(() -> new NoSuchElementException("No value present"));
+ declaredFieldMethod.setAccessible(true);
+ Field[] declaredFieldsOfField = (Field[]) declaredFieldMethod.invoke(Field.class, false);
+ Field modifiersField = Arrays
+ .stream(declaredFieldsOfField).filter(x -> Objects.equals(x.getName(), "modifiers"))
+ .findAny().orElseThrow(() -> new NoSuchElementException("No value present"));
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ } catch (RuntimeException re) {
+ throw re;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java
index 3a1cf69..d63b904 100644
--- a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.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
@@ -24,16 +24,20 @@
import java.util.logging.Logger;
import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.netty.connector.internal.RedirectException;
import org.glassfish.jersey.server.ResourceConfig;
@@ -60,6 +64,11 @@
return "GET";
}
+ @POST
+ public String post() {
+ return "POST";
+ }
+
@GET
@Path("redirect")
public Response redirect() {
@@ -77,6 +86,12 @@
public Response redirect2() {
return Response.seeOther(URI.create(TEST_URL_REF.get() + "/redirect")).build();
}
+
+ @POST
+ @Path("status307")
+ public Response status307() {
+ return Response.temporaryRedirect(URI.create(TEST_URL_REF.get())).build();
+ }
}
@Override
@@ -169,4 +184,15 @@
assertEquals(200, r.getStatus());
assertEquals("GET", r.readEntity(String.class));
}
+
+ @Test
+ public void testRedirect307PostBuffered() {
+ try (Response response = target("test/status307")
+ .property(ClientProperties.FOLLOW_REDIRECTS, true)
+ .property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
+ .request().post(Entity.entity("Something", MediaType.TEXT_PLAIN_TYPE))) {
+ assertEquals(200, response.getStatus());
+ assertEquals("POST", response.readEntity(String.class));
+ }
+ }
}
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HostHeaderTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HostHeaderTest.java
new file mode 100644
index 0000000..a456acd
--- /dev/null
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HostHeaderTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.netty.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+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.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+public class HostHeaderTest extends JerseyTest {
+
+ private static final String HTTP_HEADER_NAME = "HTTP_PORT_INT";
+
+ @Path("/")
+ public static class HostHeaderTestEchoResource {
+
+ @POST
+ public String post(@Context HttpHeaders headers) {
+ return get(headers);
+ }
+
+ @GET
+ public String get(@Context HttpHeaders headers) {
+ String sPort = headers.getHeaderString(HTTP_HEADER_NAME);
+ String hostPort = headers.getHeaderString(HttpHeaders.HOST);
+ int indexColon = hostPort.indexOf(':');
+ if (indexColon != -1) {
+ hostPort = hostPort.substring(indexColon + 1);
+ }
+ if (sPort.equals(hostPort.trim())) {
+ return GET.class.getName();
+ } else {
+ return "Expected port " + sPort + " but found " + hostPort;
+ }
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HostHeaderTestEchoResource.class);
+ }
+
+ @Test
+ public void testHostHeaderAndPort() {
+ int port = getPort();
+ ClientConfig config = new ClientConfig();
+ config.connectorProvider(new NettyConnectorProvider());
+ try (Response response = ClientBuilder.newClient(config).target(target().getUri())
+ .request()
+ .header(HTTP_HEADER_NAME, port)
+ .get()) {
+ MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
+ MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
+ }
+ }
+
+ @Test
+ public void testHostHeaderAndPortAfterRemovedFromFilter() {
+ int port = getPort();
+ ClientConfig config = new ClientConfig();
+ config.connectorProvider(new NettyConnectorProvider());
+ try (Response response = ClientBuilder.newClient(config)
+ .target(target().getUri())
+ .request()
+ .header(HTTP_HEADER_NAME, port)
+ .post(Entity.entity("xxx", MediaType.TEXT_PLAIN_TYPE))) {
+ MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
+ MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
+ }
+ }
+
+}
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HugeHeaderTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HugeHeaderTest.java
new file mode 100644
index 0000000..dddf8d9
--- /dev/null
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/HugeHeaderTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.netty.connector;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.jetty.JettyTestContainerProperties;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class HugeHeaderTest extends JerseyTest {
+
+ private static final int SERVER_HEADER_SIZE = 1234567;
+
+ private static final String hugeHeader =
+ "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz"
+ + "abcdefghijklmnopqrstuvwxyz";
+
+ @Path("/test")
+ public static class HttpMethodResource {
+ @POST
+ public Response post(
+ @HeaderParam("X-HUGE-HEADER") String hugeHeader,
+ String entity) {
+
+ return Response.noContent()
+ .header("X-HUGE-HEADER", hugeHeader)
+ .header("X-HUGE-HEADER-SIZE", hugeHeader.length())
+ .build();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(HugeHeaderTest.HttpMethodResource.class);
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ final Map<String, Object> configurationProperties = new HashMap<>();
+ configurationProperties.put(JettyTestContainerProperties.HEADER_SIZE, SERVER_HEADER_SIZE);
+ return new JettyTestContainerFactory(configurationProperties);
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.connectorProvider(new NettyConnectorProvider());
+ }
+
+ @Test
+ public void testContentHeaderTrunked() {
+ final StringBuffer veryHugeHeader = new StringBuffer();
+ for (int i = 1; i < 33; i++) {
+ veryHugeHeader.append(hugeHeader);
+ }
+ final Response response = target("test").request()
+ .header("X-HUGE-HEADER", veryHugeHeader.toString())
+ .post(null);
+
+ assertNull(response.getHeaderString("X-HUGE-HEADER-SIZE"));
+ assertNull(response.getHeaderString("X-HUGE-HEADER"));
+ response.close();
+ }
+
+ @Test
+ public void testConnectorHeaderSize() {
+ final StringBuffer veryHugeHeader = new StringBuffer();
+ for (int i = 1; i < 35; i++) {
+ veryHugeHeader.append(hugeHeader);
+ }
+ int headerSize = veryHugeHeader.length();
+ Response response = target("test")
+ .property(NettyClientProperties.MAX_HEADER_SIZE, 77750)
+ .request()
+
+
+ .header("X-HUGE-HEADER", veryHugeHeader.toString())
+ .post(null);
+ assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
+
+ assertEquals(String.valueOf(headerSize), response.getHeaderString("X-HUGE-HEADER-SIZE"));
+ assertEquals(veryHugeHeader.toString(), response.getHeaderString("X-HUGE-HEADER"));
+ response.close();
+ }
+}
diff --git a/connectors/pom.xml b/connectors/pom.xml
index d25c8e1..89aedd2 100644
--- a/connectors/pom.xml
+++ b/connectors/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/glassfish/jersey-gf-ejb/pom.xml b/containers/glassfish/jersey-gf-ejb/pom.xml
index e0b9fb4..5873489 100644
--- a/containers/glassfish/jersey-gf-ejb/pom.xml
+++ b/containers/glassfish/jersey-gf-ejb/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/glassfish/pom.xml b/containers/glassfish/pom.xml
index 7987145..52a5591 100644
--- a/containers/glassfish/pom.xml
+++ b/containers/glassfish/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/grizzly2-http/pom.xml b/containers/grizzly2-http/pom.xml
index 2ae6dde..999d371 100644
--- a/containers/grizzly2-http/pom.xml
+++ b/containers/grizzly2-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
index 28d03d4..11d74a6 100644
--- a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyHttpServerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,10 +18,15 @@
import java.io.IOException;
import java.net.URI;
+import java.util.concurrent.ThreadFactory;
import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
import org.glassfish.jersey.grizzly2.httpserver.internal.LocalizationMessages;
+import org.glassfish.jersey.innate.VirtualThreadSupport;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
import org.glassfish.jersey.server.ApplicationHandler;
@@ -281,11 +286,20 @@
: uri.getPort();
final NetworkListener listener = new NetworkListener("grizzly", host, port);
+ final Configuration configuration = handler != null ? handler.getConfiguration().getConfiguration() : null;
- listener.getTransport().getWorkerThreadPoolConfig().setThreadFactory(new ThreadFactoryBuilder()
+ final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
+ final ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("grizzly-http-server-%d")
.setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
- .build());
+ .setThreadFactory(executors.getThreadFactory())
+ .build();
+
+ if (executors.isVirtual()) {
+ listener.getTransport().setWorkerThreadPool(executors.newCachedThreadPool());
+ } else {
+ listener.getTransport().getWorkerThreadPoolConfig().setThreadFactory(threadFactory);
+ }
listener.setSecure(secure);
if (sslEngineConfigurator != null) {
diff --git a/containers/grizzly2-servlet/pom.xml b/containers/grizzly2-servlet/pom.xml
index 9433817..cdaf24b 100644
--- a/containers/grizzly2-servlet/pom.xml
+++ b/containers/grizzly2-servlet/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/grizzly2-servlet/src/main/java/module-info.java b/containers/grizzly2-servlet/src/main/java/module-info.java
index 2acb16f..229f2ac 100644
--- a/containers/grizzly2-servlet/src/main/java/module-info.java
+++ b/containers/grizzly2-servlet/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,7 @@
requires org.glassfish.grizzly.http.server;
requires org.glassfish.jersey.core.common;
+ requires org.glassfish.jersey.core.server;
requires org.glassfish.jersey.container.servlet.core;
requires org.glassfish.jersey.container.grizzly2.http;
diff --git a/containers/grizzly2-servlet/src/main/java/org/glassfish/jersey/grizzly2/servlet/GrizzlyWebContainerFactory.java b/containers/grizzly2-servlet/src/main/java/org/glassfish/jersey/grizzly2/servlet/GrizzlyWebContainerFactory.java
index a70ee7f..d513d0a 100644
--- a/containers/grizzly2-servlet/src/main/java/org/glassfish/jersey/grizzly2/servlet/GrizzlyWebContainerFactory.java
+++ b/containers/grizzly2-servlet/src/main/java/org/glassfish/jersey/grizzly2/servlet/GrizzlyWebContainerFactory.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
@@ -23,6 +23,7 @@
import jakarta.servlet.Servlet;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.uri.UriComponent;
@@ -251,11 +252,13 @@
}
}
+ ResourceConfig configuration = new ResourceConfig();
if (initParams != null) {
registration.setInitParameters(initParams);
+ configuration.addProperties((Map) initParams);
}
- HttpServer server = GrizzlyHttpServerFactory.createHttpServer(u);
+ HttpServer server = GrizzlyHttpServerFactory.createHttpServer(u, configuration);
context.deploy(server);
return server;
}
diff --git a/containers/jdk-http/pom.xml b/containers/jdk-http/pom.xml
index f3f68df..5a4dd85 100644
--- a/containers/jdk-http/pom.xml
+++ b/containers/jdk-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jersey-servlet-core/pom.xml b/containers/jersey-servlet-core/pom.xml
index 6ac5fcc..3a34557 100644
--- a/containers/jersey-servlet-core/pom.xml
+++ b/containers/jersey-servlet-core/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
index 56cf0ea..19810fa 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
@@ -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
@@ -294,6 +294,7 @@
final URI baseUri;
final URI requestUri;
try {
+ LOGGER.debugLog("ServletContainer.service(...) started");
baseUri = absoluteUriBuilder.replacePath(encodedBasePath).build();
String queryParameters = ContainerUtils.encodeUnsafeCharacters(request.getQueryString());
if (queryParameters == null) {
@@ -530,6 +531,7 @@
final URI baseUri;
final URI requestUri;
try {
+ LOGGER.debugLog("ServletContainer.doFilter(...) started");
final UriBuilder absoluteUriBuilder = UriBuilder.fromUri(request.getRequestURL().toString());
// depending on circumstances, use the correct path to replace in the absolute request URI
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
index 584aef0..e6f5155 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
@@ -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
@@ -17,6 +17,8 @@
package org.glassfish.jersey.servlet;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.security.AccessController;
@@ -54,6 +56,7 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.ServiceFinderBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -412,7 +415,7 @@
}
/**
- * Initialize {@code ContainerRequest} instance to used used to handle {@code servletRequest}.
+ * Initialize {@code ContainerRequest} instance to handle {@code servletRequest}.
*/
private void initContainerRequest(
final ContainerRequest requestContext,
@@ -420,7 +423,21 @@
final HttpServletResponse servletResponse,
final ResponseWriter responseWriter) throws IOException {
- requestContext.setEntityStream(servletRequest.getInputStream());
+ try {
+ requestContext.setEntityStream(new InputStreamWrapper() {
+ @Override
+ protected InputStream getWrapped() {
+ try {
+ return servletRequest.getInputStream();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ });
+ } catch (UncheckedIOException e) {
+ throw e.getCause();
+ }
+
requestContext.setRequestScopedInitializer(requestScopedInitializer.get(new RequestContextProvider() {
@Override
public HttpServletRequest getHttpServletRequest() {
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
index 2335932..5cf6812 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
@@ -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
@@ -142,12 +142,7 @@
}
}
- final String reasonPhrase = responseContext.getStatusInfo().getReasonPhrase();
- if (reasonPhrase != null) {
- response.setStatus(responseContext.getStatus());
- } else {
- response.setStatus(responseContext.getStatus());
- }
+ response.setStatus(responseContext.getStatus());
if (!responseContext.hasEntity()) {
return null;
@@ -214,12 +209,13 @@
try {
if (!response.isCommitted()) {
try {
+ final int statusCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
if (configSetStatusOverSendError) {
response.reset();
//noinspection deprecation
- response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+ response.setStatus(statusCode);
} else {
- response.sendError(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()/*, "Request failed."*/);
+ response.sendError(statusCode, "Request failed.");
}
} catch (final IllegalStateException ex) {
// a race condition externally committing the response can still occur...
diff --git a/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java b/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java
new file mode 100644
index 0000000..feb899c
--- /dev/null
+++ b/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.servlet.internal;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.servlet.WebComponent;
+import org.glassfish.jersey.servlet.WebConfig;
+import org.glassfish.jersey.servlet.WebFilterConfig;
+import org.junit.jupiter.api.Test;
+
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Enumeration;
+
+public class RequestInputStreamTest {
+ @Test
+ public void test404RequestInputStream() throws ServletException, IOException {
+ InvocationHandler handler = new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ switch (method.getName()) {
+ case "getHeaderNames":
+ return Collections.emptyEnumeration();
+ case "getInputStream":
+ throw new IllegalStateException("ServletRequest#getInputStream clashes with ServletRequest#getReader");
+ }
+ return null;
+ }
+ };
+
+ FilterConfig filterConfig = new FilterConfig() {
+ @Override
+ public String getFilterName() {
+ return null;
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return (ServletContext) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{ServletContext.class},
+ handler);
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return null;
+ }
+ };
+ WebConfig dummyWebConfig = new WebFilterConfig(filterConfig);
+ ResourceConfig resourceConfig = new ResourceConfig()
+ .property(CommonProperties.PROVIDER_DEFAULT_DISABLE, "ALL")
+ .property(ServerProperties.WADL_FEATURE_DISABLE, true)
+ .property(ServletProperties.FILTER_FORWARD_ON_404, true)
+ .property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
+ WebComponent component = new WebComponent(dummyWebConfig, resourceConfig);
+ component.service(URI.create("http://localhost"), URI.create("http://localhost"),
+ (HttpServletRequest) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[] {HttpServletRequest.class},
+ handler
+ ),
+ (HttpServletResponse) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{HttpServletResponse.class},
+ handler)
+ );
+ }
+}
diff --git a/containers/jersey-servlet/pom.xml b/containers/jersey-servlet/pom.xml
index 69010ed..21adf8c 100644
--- a/containers/jersey-servlet/pom.xml
+++ b/containers/jersey-servlet/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jetty-http/pom.xml b/containers/jetty-http/pom.xml
index 1be9851..52cfe67 100644
--- a/containers/jetty-http/pom.xml
+++ b/containers/jetty-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
index 55258ea..3d519b6 100644
--- a/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
+++ b/containers/jetty-http/src/main/java11/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -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
diff --git a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java
index dfe20f2..c555e92 100644
--- a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java
+++ b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -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
@@ -23,10 +23,13 @@
import java.security.Principal;
import java.util.List;
import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -43,11 +46,13 @@
import org.eclipse.jetty.security.AuthenticationState;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.thread.Scheduler;
import org.glassfish.jersey.internal.MapPropertiesDelegate;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.ReferencingFactory;
import org.glassfish.jersey.internal.util.ExtendedLogger;
import org.glassfish.jersey.internal.util.collection.Ref;
+import org.glassfish.jersey.jetty.internal.LocalizationMessages;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ContainerException;
@@ -137,6 +142,7 @@
final ResponseWriter responseWriter = new ResponseWriter(request, response, callback, configSetStatusOverSendError);
try {
+ LOGGER.debugLog(LocalizationMessages.CONTAINER_STARTED());
final URI baseUri = getBaseUri(request);
final URI requestUri = getRequestUri(request, baseUri);
final ContainerRequest requestContext = new ContainerRequest(
@@ -246,38 +252,51 @@
}
}
- private static final class ResponseWriter implements ContainerResponseWriter {
+ private static class ResponseWriter implements ContainerResponseWriter {
private final Request request;
private final Response response;
private final Callback callback;
private final boolean configSetStatusOverSendError;
- private final Timer timer = new Timer();
- private final long asyncStartTimeMillis;
+ private final long asyncStartTimeNanos;
+ private final Scheduler scheduler;
private final ConcurrentLinkedQueue<TimeoutHandler> timeoutHandlerQueue = new ConcurrentLinkedQueue<>();
- private TimerTask currentTimerTask;
+ private Scheduler.Task currentTimerTask;
- ResponseWriter(final Request request, final Response response, final Callback callback,
- final boolean configSetStatusOverSendError) {
+ ResponseWriter(final Request request, final Response response,
+ final Callback callback, final boolean configSetStatusOverSendError) {
this.request = request;
this.response = response;
this.callback = callback;
- this.asyncStartTimeMillis = System.currentTimeMillis();
+ this.asyncStartTimeNanos = System.nanoTime();
this.configSetStatusOverSendError = configSetStatusOverSendError;
+
+ this.scheduler = request.getComponents().getScheduler();
}
private synchronized void setNewTimeout(long timeOut, TimeUnit timeUnit) {
- long timeOutMillis = timeUnit.toMillis(timeOut);
+ long timeOutNanos = timeUnit.toNanos(timeOut);
if (currentTimerTask != null) {
+ // Do not interrupt, see callTimeoutHandlers()
currentTimerTask.cancel();
}
- currentTimerTask = new TimerTask() {
- @Override
- public void run() {
- timeoutHandlerQueue.forEach(timeoutHandler -> timeoutHandler.onTimeout(ResponseWriter.this));
+ // Use System.nanoTime() as the clock source here, because the returned value is not prone to wall-clock
+ // drift - unlike System.currentTimeMillis().
+ long delayNanos = Math.max(asyncStartTimeNanos - System.nanoTime() + timeOutNanos, 0L);
+ currentTimerTask = scheduler.schedule(this::callTimeoutHandlers, delayNanos, TimeUnit.NANOSECONDS);
+ }
+
+ private void callTimeoutHandlers() {
+ // Note: Although it might not happen in practice, it is in theory possible that this function is
+ // called multiple times concurrently. To prevent any timeout handler being called twice, we poll()
+ // timeout handlers from the queue, instead of iterating over the queue.
+ while (true) {
+ TimeoutHandler handler = timeoutHandlerQueue.poll();
+ if (handler == null) {
+ break;
}
- };
- timer.schedule(currentTimerTask, Math.max(0, timeOutMillis + asyncStartTimeMillis - System.currentTimeMillis()));
+ handler.onTimeout(ResponseWriter.this);
+ }
}
@Override
@@ -417,8 +436,15 @@
super.doStop();
appHandler.onShutdown(this);
appHandler = null;
+
+ boolean needInterrupt = false;
+ if (needInterrupt) {
+ Thread.currentThread().interrupt();
+ }
}
+ private static final AtomicInteger TIMEOUT_HANDLER_ID_GEN = new AtomicInteger();
+
/**
* Create a new Jetty HTTP container.
*
diff --git a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
index 26a4b79..cb66f21 100644
--- a/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
+++ b/containers/jetty-http/src/main/java17/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
@@ -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
@@ -20,7 +20,10 @@
import java.util.concurrent.ThreadFactory;
import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.glassfish.jersey.jetty.internal.LocalizationMessages;
import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
@@ -254,7 +257,8 @@
}
final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
- final Server server = new Server(new JettyConnectorThreadPool());
+ final Configuration configuration = handler != null ? handler.getConfiguration() : null;
+ final Server server = new Server(new JettyConnectorThreadPool(configuration));
final HttpConfiguration config = new HttpConfiguration();
if (sslContextFactory != null) {
config.setSecureScheme("https");
@@ -292,10 +296,20 @@
//
// Keeping this for backwards compatibility for the time being
private static final class JettyConnectorThreadPool extends QueuedThreadPool {
- private final ThreadFactory threadFactory = new ThreadFactoryBuilder()
- .setNameFormat("jetty-http-server-%d")
- .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
- .build();
+ private final ThreadFactory threadFactory;
+
+ private JettyConnectorThreadPool(Configuration configuration) {
+ final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
+ if (executors.isVirtual()) {
+ super.setMaxThreads(Integer.MAX_VALUE - 1);
+ }
+
+ this.threadFactory = new ThreadFactoryBuilder()
+ .setNameFormat("jetty-http-server-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .setThreadFactory(executors.getThreadFactory())
+ .build();
+ }
@Override
public Thread newThread(Runnable runnable) {
diff --git a/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties b/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
index 8d507d5..2fb2350 100644
--- a/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
+++ b/containers/jetty-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 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
@@ -15,6 +15,7 @@
#
# {0} - status code; {1} - status reason message
+container.started=JettyHttpContainer.handle(...) started.
exception.sending.error.response=I/O exception occurred while sending "{0}/{1}" error response.
error.when.creating.server=Exception thrown when trying to create jetty server.
unable.to.close.response=Unable to close response output.
diff --git a/containers/jetty-http2/pom.xml b/containers/jetty-http2/pom.xml
index 5f0dea5..526b275 100644
--- a/containers/jetty-http2/pom.xml
+++ b/containers/jetty-http2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jetty-servlet/pom.xml b/containers/jetty-servlet/pom.xml
index 0bd1c5b..1042c36 100644
--- a/containers/jetty-servlet/pom.xml
+++ b/containers/jetty-servlet/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/jetty11-http/pom.xml b/containers/jetty11-http/pom.xml
index 0eea308..154d085 100644
--- a/containers/jetty11-http/pom.xml
+++ b/containers/jetty11-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -114,6 +114,13 @@
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <configuration>
+ <rulesToSkip>dependencyConvergence</rulesToSkip>
+ </configuration>
+ </plugin>
</plugins>
<resources>
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java
index 36be72d..dc680a3 100644
--- a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java
@@ -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
@@ -147,6 +147,7 @@
final Response response = request.getResponse();
final ResponseWriter responseWriter = new ResponseWriter(request, response, configSetStatusOverSendError);
try {
+ LOGGER.debugLog(LocalizationMessages.CONTAINER_STARTED());
final URI baseUri = getBaseUri(request);
final URI requestUri = getRequestUri(request, baseUri);
final ContainerRequest requestContext = new ContainerRequest(
diff --git a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
index 26a4b79..cb66f21 100644
--- a/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
+++ b/containers/jetty11-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainerFactory.java
@@ -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
@@ -20,7 +20,10 @@
import java.util.concurrent.ThreadFactory;
import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.glassfish.jersey.jetty.internal.LocalizationMessages;
import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
@@ -254,7 +257,8 @@
}
final int port = (uri.getPort() == -1) ? defaultPort : uri.getPort();
- final Server server = new Server(new JettyConnectorThreadPool());
+ final Configuration configuration = handler != null ? handler.getConfiguration() : null;
+ final Server server = new Server(new JettyConnectorThreadPool(configuration));
final HttpConfiguration config = new HttpConfiguration();
if (sslContextFactory != null) {
config.setSecureScheme("https");
@@ -292,10 +296,20 @@
//
// Keeping this for backwards compatibility for the time being
private static final class JettyConnectorThreadPool extends QueuedThreadPool {
- private final ThreadFactory threadFactory = new ThreadFactoryBuilder()
- .setNameFormat("jetty-http-server-%d")
- .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
- .build();
+ private final ThreadFactory threadFactory;
+
+ private JettyConnectorThreadPool(Configuration configuration) {
+ final LoomishExecutors executors = VirtualThreadUtil.withConfig(configuration, false);
+ if (executors.isVirtual()) {
+ super.setMaxThreads(Integer.MAX_VALUE - 1);
+ }
+
+ this.threadFactory = new ThreadFactoryBuilder()
+ .setNameFormat("jetty-http-server-%d")
+ .setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler())
+ .setThreadFactory(executors.getThreadFactory())
+ .build();
+ }
@Override
public Thread newThread(Runnable runnable) {
diff --git a/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties b/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
index b3094ba..f6be7cf 100644
--- a/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
+++ b/containers/jetty11-http/src/main/resources/org/glassfish/jersey/jetty/internal/localization.properties
@@ -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
@@ -15,6 +15,7 @@
#
# {0} - status code; {1} - status reason message
+container.started=JettyHttpContainer.handle(...) started.
exception.sending.error.response=I/O exception occurred while sending "{0}/{1}" error response.
error.when.creating.server=Exception thrown when trying to create jetty server.
unable.to.close.response=Unable to close response output.
diff --git a/containers/netty-http/pom.xml b/containers/netty-http/pom.xml
index d3929cb..2e9ce74 100644
--- a/containers/netty-http/pom.xml
+++ b/containers/netty-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/pom.xml b/containers/pom.xml
index cf9fd5d..ef2ca0a 100644
--- a/containers/pom.xml
+++ b/containers/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/containers/simple-http/pom.xml b/containers/simple-http/pom.xml
index 3d91398..2636623 100644
--- a/containers/simple-http/pom.xml
+++ b/containers/simple-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/core-client/pom.xml b/core-client/pom.xml
index 0af1530..9227e81 100644
--- a/core-client/pom.xml
+++ b/core-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java b/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
index 74c8cfb..fa020cf 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,6 +35,7 @@
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.ReaderInterceptorExecutor;
/**
* {@link jakarta.ws.rs.ext.MessageBodyWriter} for {@link ChunkedInput}.
@@ -71,7 +72,7 @@
return new ChunkedInput(
chunkType,
- inputStream,
+ ReaderInterceptorExecutor.closeableInputStream(inputStream),
annotations,
mediaType,
headers,
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
index df26b22..ab5b9f5 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021 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
@@ -32,11 +32,12 @@
import org.glassfish.jersey.internal.util.collection.Value;
import org.glassfish.jersey.internal.util.collection.Values;
import org.glassfish.jersey.model.internal.ComponentBag;
-import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
import org.glassfish.jersey.process.internal.AbstractExecutorProvidersConfigurator;
import org.glassfish.jersey.spi.ExecutorServiceProvider;
import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
+import jakarta.ws.rs.core.Configuration;
+
/**
* Configurator which initializes and register {@link ExecutorServiceProvider} and
* {@link ScheduledExecutorServiceProvider}.
@@ -64,7 +65,8 @@
@Override
public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
- Map<String, Object> runtimeProperties = bootstrapBag.getConfiguration().getProperties();
+ final Configuration configuration = bootstrapBag.getConfiguration();
+ Map<String, Object> runtimeProperties = configuration.getProperties();
ExecutorServiceProvider defaultAsyncExecutorProvider;
ScheduledExecutorServiceProvider defaultScheduledExecutorProvider;
@@ -94,12 +96,12 @@
.named("ClientAsyncThreadPoolSize");
injectionManager.register(asyncThreadPoolSizeBinding);
- defaultAsyncExecutorProvider = new DefaultClientAsyncExecutorProvider(asyncThreadPoolSize);
+ defaultAsyncExecutorProvider = new DefaultClientAsyncExecutorProvider(asyncThreadPoolSize, configuration);
} else {
if (MANAGED_EXECUTOR_SERVICE != null) {
defaultAsyncExecutorProvider = new ClientExecutorServiceProvider(MANAGED_EXECUTOR_SERVICE);
} else {
- defaultAsyncExecutorProvider = new DefaultClientAsyncExecutorProvider(0);
+ defaultAsyncExecutorProvider = new DefaultClientAsyncExecutorProvider(0, configuration);
}
}
}
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..364bff0 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
@@ -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
@@ -241,10 +241,33 @@
public static final String OUTBOUND_CONTENT_LENGTH_BUFFER = CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_CLIENT;
/**
+ * If {@code true} then disable configuration of Json Binding (JSR-367)
+ * feature on client.
+ * <p>
+ * By default, Json Binding on client is automatically enabled if global
+ * property
+ * {@value org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE}
+ * is not disabled. If set then the client property value overrides the
+ * global property value.
+ * <p>
+ * The default value is {@code false}.
+ * </p>
+ * <p>
+ * The name of the configuration property is <tt>{@value}</tt>.
+ * </p>
+ * <p>This constant is an alias for {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE_CLIENT}.</p>
+ *
+ * @see org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE
+ * @since 2.45
+ */
+ @PropertyAlias
+ public static final String JSON_BINDING_FEATURE_DISABLE = CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT;
+
+ /**
* If {@code true} then disable configuration of Json Processing (JSR-353)
* feature on client.
* <p>
- * By default Json Processing on client is automatically enabled if global
+ * By default, Json Processing on client is automatically enabled if global
* property
* {@value org.glassfish.jersey.CommonProperties#JSON_PROCESSING_FEATURE_DISABLE}
* is not disabled. If set then the client property value overrides the
@@ -265,7 +288,7 @@
/**
* If {@code true} then disable META-INF/services lookup on client.
* <p>
- * By default Jersey looks up SPI implementations described by {@code META-INF/services/*} files.
+ * By default, Jersey looks up SPI implementations described by {@code META-INF/services/*} files.
* Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}.
* </p>
* <p>
@@ -467,24 +490,6 @@
public static final String QUERY_PARAM_STYLE = "jersey.config.client.uri.query.param.style";
/**
- * <p>
- * Most connectors support HOST header value to be used as an SNIHostName. However, the HOST header is restricted in JDK.
- * {@code HttpUrlConnector} and {@code JavaNetHttpConnector} need
- * to have an extra System Property set to allow HOST header.
- * As an option to HOST header, this property allows the HOST name to be pre-set on a Client and does not need to
- * be set on each request.
- * </p>
- * <p>
- * The value MUST be an instance of {@link java.lang.String}.
- * </p>
- * <p>
- * The name of the configuration property is <tt>{@value}</tt>.
- * </p>
- * @since 3.1.2
- */
- public static final String SNI_HOST_NAME = "jersey.config.client.sniHostName";
-
- /**
* Sets the {@link org.glassfish.jersey.client.spi.ConnectorProvider} class. Overrides the value from META-INF/services.
*
* <p>
@@ -501,6 +506,31 @@
public static final String CONNECTOR_PROVIDER = "jersey.config.client.connector.provider";
/**
+ * <p>
+ * Sets the {@code hostName} to be used for calculating the {@link javax.net.ssl.SNIHostName} during the HTTPS request.
+ * 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>
+ * <p>
+ * Most connectors support HOST header value to be used as an SNIHostName. However, the HOST header is restricted in JDK.
+ * {@code HttpUrlConnector} and {@code JavaNetHttpConnector} need
+ * to have an extra System Property set to allow HOST header.
+ * </p>
+ * <p>
+ * The value MUST be an instance of {@link java.lang.String}.
+ * </p>
+ * <p>
+ * The name of the configuration property is <tt>{@value}</tt>.
+ * </p>
+ * @since 3.1.2
+ */
+ public static final String SNI_HOST_NAME = "jersey.config.client.snihostname";
+
+ /**
* <p>The {@link javax.net.ssl.SSLContext} {@link java.util.function.Supplier} to be used to set ssl context in the current
* HTTP request. Has precedence over the {@link Client#getSslContext()}.
* </p>
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
index 9b0e9c1..9896c7a 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java
@@ -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
@@ -25,6 +25,10 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -90,6 +94,8 @@
private LazyValue<PropertiesResolver> propertiesResolver = Values.lazy(
(Value<PropertiesResolver>) () -> PropertiesResolver.create(getConfiguration(), getPropertiesDelegate())
);
+ // by default nothing to be cancelled.
+ private Future cancellable = NotCancellable.INSTANCE;
private static final Logger LOGGER = Logger.getLogger(ClientRequest.class.getName());
@@ -126,6 +132,7 @@
this.writerInterceptors = original.writerInterceptors;
this.propertiesDelegate = new MapPropertiesDelegate(original.propertiesDelegate);
this.ignoreUserAgent = original.ignoreUserAgent;
+ this.cancellable = original.cancellable;
}
@Override
@@ -599,4 +606,66 @@
public void ignoreUserAgent(final boolean ignore) {
this.ignoreUserAgent = ignore;
}
+
+ /**
+ * Sets the new {@code Future} that may cancel this {@link ClientRequest}.
+ * @param cancellable
+ */
+ void setCancellable(Future cancellable) {
+ this.cancellable = cancellable;
+ }
+
+ /**
+ * Cancels this {@link ClientRequest}. May result in {@link java.util.concurrent.CancellationException} later in this
+ * request processing if this {@link ClientRequest} is backed by a {@link Future} provided to
+ * {@link JerseyInvocation.Builder#setCancellable(Future)}.
+ * @param mayInterruptIfRunning may have no effect or {@code true} if the thread executing this task should be interrupted
+ * (if the thread is known to the implementation);
+ * otherwise, in-progress tasks are allowed to complete
+ */
+ public void cancel(boolean mayInterruptIfRunning) {
+ cancellable.cancel(mayInterruptIfRunning);
+ }
+
+ /**
+ * Returns {@code true} if this {@link ClientRequest} was cancelled
+ * before it completed normally.
+ *
+ * @return {@code true} if this {@link ClientRequest} was cancelled
+ * before it completed normally
+ */
+ public boolean isCancelled() {
+ return cancellable.isCancelled();
+ }
+
+ private static class NotCancellable implements Future {
+ public static final Future INSTANCE = new NotCancellable();
+ private boolean isCancelled = false;
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ isCancelled = true;
+ return isCancelled;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return isCancelled;
+ }
+
+ @Override
+ public boolean isDone() {
+ return false;
+ }
+
+ @Override
+ public Object get() throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ return null;
+ }
+ }
}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/DefaultClientAsyncExecutorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/DefaultClientAsyncExecutorProvider.java
index 2f9fa71..2a19b0d 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/DefaultClientAsyncExecutorProvider.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/DefaultClientAsyncExecutorProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,9 @@
import jakarta.inject.Inject;
import jakarta.inject.Named;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Context;
+
import org.glassfish.jersey.client.internal.LocalizationMessages;
import org.glassfish.jersey.internal.util.collection.LazyValue;
@@ -46,8 +49,9 @@
* See also {@link org.glassfish.jersey.client.ClientProperties#ASYNC_THREADPOOL_SIZE}.
*/
@Inject
- public DefaultClientAsyncExecutorProvider(@Named("ClientAsyncThreadPoolSize") final int poolSize) {
- super("jersey-client-async-executor");
+ public DefaultClientAsyncExecutorProvider(@Named("ClientAsyncThreadPoolSize") final int poolSize,
+ @Context Configuration configuration) {
+ super("jersey-client-async-executor", configuration);
this.asyncThreadPoolSize = Values.lazy(new Value<Integer>() {
@Override
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..dd96928 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";
@@ -283,9 +287,7 @@
* @throws java.io.IOException in case the connection cannot be provided.
*/
default HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException {
- synchronized (this){
- return (proxy == null) ? getConnection(url) : (HttpURLConnection) url.openConnection(proxy);
- }
+ return (proxy == null) ? getConnection(url) : (HttpURLConnection) url.openConnection(proxy);
}
}
@@ -293,7 +295,16 @@
@Override
public HttpURLConnection getConnection(final URL url) throws IOException {
- return (HttpURLConnection) url.openConnection();
+ return connect(url, null);
+ }
+
+ @Override
+ public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException {
+ return connect(url, proxy);
+ }
+
+ private HttpURLConnection connect(URL url, Proxy proxy) throws IOException {
+ return (proxy == null) ? (HttpURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection(proxy);
}
}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java b/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java
index 222c2a9..c120856 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2021 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
@@ -573,6 +573,18 @@
throw new IllegalStateException(
LocalizationMessages.CLIENT_RX_PROVIDER_NOT_REGISTERED(clazz.getSimpleName()));
}
+
+ /**
+ * Sets Future that backs {@link ClientRequest} {@link ClientRequest#isCancelled()} method. Can be used for instance
+ * by {@link CompletionStageRxInvoker} to pass the created {@link CompletableFuture} to the provided {@link SyncInvoker}.
+ * @param cancellable the {@link Future} whose result of {@link Future#cancel(boolean)} will be available by
+ * {@link ClientRequest#isCancelled()}.
+ * @return the updated builder.
+ */
+ public Builder setCancellable(Future cancellable) {
+ requestContext.setCancellable(cancellable);
+ return this;
+ }
}
/* package */ static class AsyncInvoker extends CompletableFutureAsyncInvoker implements jakarta.ws.rs.client.AsyncInvoker {
@@ -711,6 +723,8 @@
public Future<Response> submit() {
final CompletableFuture<Response> responseFuture = new CompletableFuture<>();
final ClientRuntime runtime = request().getClientRuntime();
+
+ requestContext.setCancellable(responseFuture);
runtime.submit(runtime.createRunnableForAsyncProcessing(requestForCall(requestContext),
new InvocationResponseCallback<>(responseFuture, (request, scope) -> translate(request, scope, Response.class))));
@@ -725,6 +739,7 @@
final CompletableFuture<T> responseFuture = new CompletableFuture<>();
final ClientRuntime runtime = request().getClientRuntime();
+ requestContext.setCancellable(responseFuture);
runtime.submit(runtime.createRunnableForAsyncProcessing(requestForCall(requestContext),
new InvocationResponseCallback<T>(responseFuture, (request, scope) -> translate(request, scope, responseType))));
@@ -764,6 +779,7 @@
final CompletableFuture<T> responseFuture = new CompletableFuture<>();
final ClientRuntime runtime = request().getClientRuntime();
+ requestContext.setCancellable(responseFuture);
runtime.submit(runtime.createRunnableForAsyncProcessing(requestForCall(requestContext),
new InvocationResponseCallback<T>(responseFuture, (request, scope) -> translate(request, scope, responseType))));
@@ -888,6 +904,7 @@
}
};
final ClientRuntime runtime = request().getClientRuntime();
+ requestContext.setCancellable(responseFuture);
runtime.submit(runtime.createRunnableForAsyncProcessing(requestForCall(requestContext), responseCallback));
} catch (final Throwable error) {
final ProcessingException ce;
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java b/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
index 0b9da83..1ac6b75 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/RequestProcessingInitializationStage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,7 +16,9 @@
package org.glassfish.jersey.client;
+import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -26,6 +28,7 @@
import jakarta.inject.Provider;
+import org.glassfish.jersey.innate.spi.MessageBodyWorkersSettable;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.Providers;
import org.glassfish.jersey.internal.util.collection.Ref;
@@ -80,6 +83,21 @@
requestContext.setWriterInterceptors(writerInterceptors);
requestContext.setReaderInterceptors(readerInterceptors);
+ if (requestContext.getEntity() != null) {
+ setWorkers(requestContext.getEntity());
+ }
+
return requestContext;
}
+
+ private void setWorkers(Object entity) {
+ if (MessageBodyWorkersSettable.class.isInstance(entity)) {
+ ((MessageBodyWorkersSettable) entity).setMessageBodyWorkers(workersProvider);
+ } else if (Collection.class.isInstance(entity)) {
+ Iterator it = ((Collection) entity).iterator();
+ while (it.hasNext()) {
+ setWorkers(it.next());
+ }
+ }
+ }
}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
index cb32a5c..79dc60e 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
@@ -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,25 +16,23 @@
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.http.HttpHeaders;
+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.UriBuilder;
-import org.glassfish.jersey.internal.PropertiesResolver;
-import org.glassfish.jersey.internal.util.PropertiesHelper;
-
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
-import java.util.Properties;
/**
* A unified routines to configure {@link SSLParameters}.
@@ -48,11 +46,12 @@
* Builder of the {@link SSLParamConfigurator} instance.
*/
public static final class Builder {
- private URI uri = null;
+ private URI uri;
private String sniHostNameHeader = null;
- private String sniHostNameProperty = null;
+ private String sniHostPrecedence = null;
private boolean setAlways = false;
+
/**
* Sets the SNIHostName and {@link URI} from the {@link ClientRequest} instance.
* @param clientRequest the {@link ClientRequest}
@@ -60,7 +59,7 @@
*/
public Builder request(ClientRequest clientRequest) {
this.sniHostNameHeader = getSniHostNameHeader(clientRequest.getHeaders());
- this.sniHostNameProperty = clientRequest.resolveProperty(ClientProperties.SNI_HOST_NAME, String.class);
+ this.sniHostPrecedence = resolveSniHostNameProperty(clientRequest);
this.uri = clientRequest.getUri();
return this;
}
@@ -71,7 +70,7 @@
* @return the builder instance
*/
public Builder configuration(Configuration configuration) {
- this.sniHostNameProperty = (String) configuration.getProperty(ClientProperties.SNI_HOST_NAME);
+ this.sniHostPrecedence = getSniHostNameProperty(configuration);
return this;
}
@@ -107,6 +106,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 = 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(getSniHostNameProperty(configuration));
+ }
+
+ /**
+ * <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(resolveSniHostNameProperty(resolver));
+ }
+
+ /**
* Builds the {@link SSLParamConfigurator} instance.
* @return the configured {@link SSLParamConfigurator} instance.
*/
@@ -121,23 +176,34 @@
}
final String hostHeader = hostHeaders.get(0).toString();
- 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;
- } else {
- trimmedHeader = null;
- }
+ return hostHeader;
+ }
- return trimmedHeader;
+ private static String resolveSniHostNameProperty(PropertiesResolver resolver) {
+ String property = resolver.resolveProperty(ClientProperties.SNI_HOST_NAME, String.class);
+ if (property == null) {
+ property = resolver.resolveProperty(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT), String.class);
+ }
+ return property;
+ }
+
+ private static String getSniHostNameProperty(Configuration configuration) {
+ Object property = configuration.getProperty(ClientProperties.SNI_HOST_NAME);
+ if (property == null) {
+ property = configuration.getProperty(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT));
+ }
+ return (String) property;
}
}
private SSLParamConfigurator(SSLParamConfigurator.Builder builder) {
- String sniHostName = builder.sniHostNameHeader == null ? builder.sniHostNameProperty : builder.sniHostNameHeader;
uri = builder.uri;
- sniConfigurator = SniConfigurator.createWhenHostHeader(uri, sniHostName, builder.setAlways);
+ if (builder.sniHostPrecedence == null) {
+ sniConfigurator = SniConfigurator.createWhenHostHeader(uri, builder.sniHostNameHeader, builder.setAlways);
+ } else {
+ // Do not set SNI always, the property can be used to turn the SNI off
+ sniConfigurator = SniConfigurator.createWhenHostHeader(uri, builder.sniHostPrecedence, false);
+ }
}
/**
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..baf1c28 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
@@ -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,26 +50,31 @@
}
/**
- * Create ClientSNI when {@link HttpHeaders#HOST} is set different from the request URI host (or {@code whenDiffer}.is false).
+ * Create {@link SniConfigurator} when {@code sniHost} 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 sniHost the preferred host name to create the {@link SNIHostName}
* @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 {@code sniHost} is equal to the requestHost
*/
- static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, String sniHostName, boolean whenDiffer) {
- if (sniHostName == null) {
+ static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, String sniHost, boolean whenDiffer) {
+ final String trimmedHeader;
+ if (sniHost != null) {
+ int index = sniHost.indexOf(':'); // RFC 7230 Host = uri-host [ ":" port ] ;
+ final String trimmedHeader0 = index != -1 ? sniHost.substring(0, index).trim() : sniHost.trim();
+ trimmedHeader = trimmedHeader0.isEmpty() ? sniHost : trimmedHeader0;
+ } else {
return Optional.empty();
}
if (hostUri != null) {
final String hostUriString = hostUri.getHost();
- if (!whenDiffer && hostUriString.equals(sniHostName)) {
+ if (!whenDiffer && hostUriString.equals(trimmedHeader)) {
return Optional.empty();
}
}
- return Optional.of(new SniConfigurator(sniHostName));
+ return Optional.of(new SniConfigurator(trimmedHeader));
}
/**
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
index 047bba8..09d8d88 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
@@ -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
@@ -17,6 +17,7 @@
package org.glassfish.jersey.client.innate.inject;
import org.glassfish.jersey.client.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.Binder;
import org.glassfish.jersey.internal.inject.Binding;
import org.glassfish.jersey.internal.inject.ClassBinding;
@@ -52,10 +53,13 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
-import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -74,8 +78,6 @@
private final MultivaluedMap<Type, SupplierInstanceBinding<?>> supplierTypeInstanceBindings = new MultivaluedHashMap<>();
private final MultivaluedMap<Type, SupplierClassBinding<?>> supplierTypeClassBindings = new MultivaluedHashMap<>();
- private final MultivaluedMap<DisposableSupplier, Object> disposableSupplierObjects = new MultivaluedHashMap<>();
-
private final Instances instances = new Instances();
private final Types types = new Types();
@@ -88,22 +90,28 @@
* @param <TYPE> the type for which the instance is created, either Class, or ParametrizedType (for instance
* Provider<SomeClass>).
*/
- private class TypedInstances<TYPE> {
+ private class TypedInstances<TYPE extends Type> {
private final MultivaluedMap<TYPE, InstanceContext<?>> singletonInstances = new MultivaluedHashMap<>();
- private final ThreadLocal<MultivaluedMap<TYPE, InstanceContext<?>>> threadInstances = new ThreadLocal<>();
- private final List<Object> threadPredestroyables = Collections.synchronizedList(new LinkedList<>());
+ private ThreadLocal<MultivaluedMap<TYPE, InstanceContext<?>>> threadInstances = new ThreadLocal<>();
+ private final ReentrantLock singletonInstancesLock = new ReentrantLock();
+ private ThreadLocal<MultivaluedMap<DisposableSupplier, Object>> disposableSupplierObjects =
+ ThreadLocal.withInitial(() -> new MultivaluedHashMap<>());
private <T> List<InstanceContext<?>> _getSingletons(TYPE clazz) {
List<InstanceContext<?>> si;
- synchronized (singletonInstances) {
+ singletonInstancesLock.lock();
+ try {
si = singletonInstances.get(clazz);
+ } finally {
+ singletonInstancesLock.unlock();
}
return si;
}
@SuppressWarnings("unchecked")
- <T> T _addSingleton(TYPE clazz, T instance, Binding<?, ?> binding, Annotation[] qualifiers) {
- synchronized (singletonInstances) {
+ <T> T _addSingleton(TYPE clazz, T instance, Binding<?, ?> binding, Annotation[] qualifiers, boolean destroy) {
+ singletonInstancesLock.lock();
+ try {
// check existing singleton with a qualifier already created by another thread io a meantime
List<InstanceContext<?>> values = singletonInstances.get(clazz);
if (values != null) {
@@ -115,19 +123,21 @@
return (T) qualified.get(0).instance;
}
}
- singletonInstances.add(clazz, new InstanceContext<>(instance, binding, qualifiers));
- threadPredestroyables.add(instance);
+ InstanceContext<?> instanceContext = new InstanceContext<>(instance, binding, qualifiers, !destroy);
+ singletonInstances.add(clazz, instanceContext);
return instance;
+ } finally {
+ singletonInstancesLock.unlock();
}
}
@SuppressWarnings("unchecked")
<T> T addSingleton(TYPE clazz, T t, Binding<?, ?> binding, Annotation[] instanceQualifiers) {
- T t2 = _addSingleton(clazz, t, binding, instanceQualifiers);
+ T t2 = _addSingleton(clazz, t, binding, instanceQualifiers, true);
if (t2 == t) {
for (Type contract : binding.getContracts()) {
if (!clazz.equals(contract) && isClass(contract)) {
- _addSingleton((TYPE) contract, t, binding, instanceQualifiers);
+ _addSingleton((TYPE) contract, t, binding, instanceQualifiers, false);
}
}
}
@@ -143,21 +153,22 @@
return list;
}
- private <T> void _addThreadInstance(TYPE clazz, T instance, Binding<T, ?> binding, Annotation[] qualifiers) {
+ private <T> void _addThreadInstance(
+ TYPE clazz, T instance, Binding<T, ?> binding, Annotation[] qualifiers, boolean destroy) {
MultivaluedMap<TYPE, InstanceContext<?>> map = threadInstances.get();
if (map == null) {
map = new MultivaluedHashMap<>();
threadInstances.set(map);
}
- map.add(clazz, new InstanceContext<>(instance, binding, qualifiers));
- threadPredestroyables.add(instance);
+ InstanceContext<?> instanceContext = new InstanceContext<>(instance, binding, qualifiers, !destroy);
+ map.add(clazz, instanceContext);
}
<T> void addThreadInstance(TYPE clazz, T t, Binding<T, ?> binding, Annotation[] instanceQualifiers) {
- _addThreadInstance(clazz, t, binding, instanceQualifiers);
+ _addThreadInstance(clazz, t, binding, instanceQualifiers, true);
for (Type contract : binding.getContracts()) {
if (!clazz.equals(contract) && isClass(contract)) {
- _addThreadInstance((TYPE) contract, t, binding, instanceQualifiers);
+ _addThreadInstance((TYPE) contract, t, binding, instanceQualifiers, false);
}
}
}
@@ -175,26 +186,78 @@
private <T> List<InstanceContext<?>> _getContexts(TYPE clazz) {
List<InstanceContext<?>> si = _getSingletons(clazz);
List<InstanceContext<?>> ti = _getThreadInstances(clazz);
- if (si == null && ti != null) {
- si = ti;
- } else if (ti != null) {
- si.addAll(ti);
- }
- return si;
+ return InstanceContext.merge(si, ti);
}
<T> T getInstance(TYPE clazz, Annotation[] annotations) {
List<T> i = getInstances(clazz, annotations);
if (i != null) {
checkUnique(i);
- return i.get(0);
+ return instanceOrSupply(clazz, i.get(0));
}
return null;
}
+ private <T> T instanceOrSupply(TYPE clazz, T t) {
+ if (!Class.class.isInstance(clazz) || ((Class) clazz).isInstance(t)) {
+ return t;
+ } else if (Supplier.class.isInstance(t)) {
+ return (T) registerDisposableSupplierAndGet((Supplier) t, this);
+ } else if (Provider.class.isInstance(t)) {
+ return (T) ((Provider) t).get();
+ } else {
+ return t;
+ }
+ }
+
void dispose() {
singletonInstances.forEach((clazz, instances) -> instances.forEach(instance -> preDestroy(instance.getInstance())));
- threadPredestroyables.forEach(NonInjectionManager.this::preDestroy);
+ disposeThreadInstances(true);
+ /* The java.lang.ThreadLocal$ThreadLocalMap$Entry[] keeps references to this NonInjectionManager */
+ threadInstances = null;
+ disposableSupplierObjects = null;
+ }
+
+ void disposeThreadInstances(boolean allThreadInstances) {
+ MultivaluedMap<TYPE, InstanceContext<?>> ti = threadInstances.get();
+ if (ti == null) {
+ return;
+ }
+ Set<Map.Entry<TYPE, List<InstanceContext<?>>>> tiSet = ti.entrySet();
+ Iterator<Map.Entry<TYPE, List<InstanceContext<?>>>> tiSetIt = tiSet.iterator();
+ while (tiSetIt.hasNext()) {
+ Map.Entry<TYPE, List<InstanceContext<?>>> entry = tiSetIt.next();
+ Iterator<InstanceContext<?>> listIt = entry.getValue().iterator();
+ while (listIt.hasNext()) {
+ InstanceContext<?> instanceContext = listIt.next();
+ if (allThreadInstances || instanceContext.getBinding().getScope() != PerThread.class) {
+ listIt.remove();
+ if (DisposableSupplier.class.isInstance(instanceContext.getInstance())) {
+ MultivaluedMap<DisposableSupplier, Object> disposeMap = disposableSupplierObjects.get();
+ Iterator<Map.Entry<DisposableSupplier, List<Object>>> disposeMapIt = disposeMap.entrySet().iterator();
+ while (disposeMapIt.hasNext()) {
+ Map.Entry<DisposableSupplier, List<Object>> disposeMapEntry = disposeMapIt.next();
+ if (disposeMapEntry.getKey() == /* identity */ instanceContext.getInstance()) {
+ Iterator<Object> disposeMapEntryIt = disposeMapEntry.getValue().iterator();
+ while (disposeMapEntryIt.hasNext()) {
+ Object disposeInstance = disposeMapEntryIt.next();
+ ((DisposableSupplier) instanceContext.getInstance()).dispose(disposeInstance);
+ disposeMapEntryIt.remove();
+ }
+ }
+ if (disposeMapEntry.getValue().isEmpty()) {
+ disposeMapIt.remove();
+ }
+ }
+ }
+ instanceContext.destroy(NonInjectionManager.this);
+ }
+ if (entry.getValue().isEmpty()) {
+ tiSetIt.remove();
+ }
+ }
+ }
+ disposableSupplierObjects.remove();
}
}
@@ -205,9 +268,19 @@
}
public NonInjectionManager() {
+ Binding binding = new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(NonInjectionRequestScope.class).to(RequestScope.class).in(Singleton.class);
+ }
+ }.getBindings().iterator().next();
+ RequestScope scope = new NonInjectionRequestScope(this);
+ instances.addSingleton(RequestScope.class, scope, binding, null);
+ types.addSingleton(RequestScope.class, scope, binding, null);
}
public NonInjectionManager(boolean warning) {
+ this();
if (warning) {
logger.warning(LocalizationMessages.NONINJECT_FALLBACK());
} else {
@@ -217,20 +290,21 @@
@Override
public void completeRegistration() {
- instances._addSingleton(InjectionManager.class, this, new InjectionManagerBinding(), null);
+ instances._addSingleton(InjectionManager.class, this, new InjectionManagerBinding(), null, false);
}
@Override
public void shutdown() {
shutdown = true;
-
- disposableSupplierObjects.forEach((supplier, objects) -> objects.forEach(supplier::dispose));
- disposableSupplierObjects.clear();
-
instances.dispose();
types.dispose();
}
+ void disposeRequestScopedInstances() {
+ instances.disposeThreadInstances(false);
+ types.disposeThreadInstances(false);
+ }
+
@Override
public boolean isShutdown() {
return shutdown;
@@ -409,12 +483,7 @@
return (T) this;
}
if (RequestScope.class.equals(createMe)) {
- if (!isRequestScope) {
- isRequestScope = true;
- return (T) new NonInjectionRequestScope();
- } else {
- throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED());
- }
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED());
}
ClassBindings<T> classBindings = classBindings(createMe);
@@ -429,12 +498,7 @@
return (T) this;
}
if (RequestScope.class.equals(createMe)) {
- if (!isRequestScope) {
- isRequestScope = true;
- return (T) new NonInjectionRequestScope();
- } else {
- throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED());
- }
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED());
}
ClassBindings<T> classBindings = classBindings(createMe);
@@ -533,7 +597,9 @@
@Override
public void preDestroy(Object preDestroyMe) {
- Method preDestroy = getAnnotatedMethod(preDestroyMe, PreDestroy.class);
+ Method preDestroy = Method.class.isInstance(preDestroyMe)
+ ? (Method) preDestroyMe
+ : getAnnotatedMethod(preDestroyMe, PreDestroy.class);
if (preDestroy != null) {
ensureAccessible(preDestroy);
try {
@@ -565,20 +631,27 @@
* @return The proxy for the instance supplied by a supplier or the instance if not required to be proxied.
*/
@SuppressWarnings("unchecked")
- private <T> T createSupplierProxyIfNeeded(Boolean createProxy, Class<T> iface, Supplier<T> supplier) {
+ private <T> T createSupplierProxyIfNeeded(
+ Boolean createProxy, Class<T> iface, Supplier<Supplier<T>> supplier, TypedInstances<?> typedInstances) {
if (createProxy != null && createProxy && iface.isInterface()) {
T proxy = (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new InvocationHandler() {
- final SingleRegisterSupplier<T> singleSupplierRegister = new SingleRegisterSupplier<>(supplier);
+ final Set<Object> instances = new HashSet<>();
+
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- T t = singleSupplierRegister.get();
+ Supplier<T> supplierT = supplier.get();
+ T t = supplierT.get();
+ if (DisposableSupplier.class.isInstance(supplierT) && !instances.contains(t)) {
+ MultivaluedMap<DisposableSupplier, Object> map = typedInstances.disposableSupplierObjects.get();
+ map.add((DisposableSupplier) supplierT, t);
+ }
Object ret = method.invoke(t, args);
return ret;
}
});
return proxy;
} else {
- return registerDisposableSupplierAndGet(supplier);
+ return registerDisposableSupplierAndGet(supplier.get(), typedInstances);
}
}
@@ -590,8 +663,8 @@
private class SingleRegisterSupplier<T> {
private final LazyValue<T> once;
- private SingleRegisterSupplier(Supplier<T> supplier) {
- once = Values.lazy((Value<T>) () -> registerDisposableSupplierAndGet(supplier));
+ private SingleRegisterSupplier(Supplier<T> supplier, TypedInstances<?> instances) {
+ once = Values.lazy((Value<T>) () -> registerDisposableSupplierAndGet(supplier, instances));
}
T get() {
@@ -599,10 +672,10 @@
}
}
- private <T> T registerDisposableSupplierAndGet(Supplier<T> supplier) {
+ private <T> T registerDisposableSupplierAndGet(Supplier<T> supplier, TypedInstances<?> typedInstances) {
T instance = supplier.get();
if (DisposableSupplier.class.isInstance(supplier)) {
- disposableSupplierObjects.add((DisposableSupplier<T>) supplier, instance);
+ typedInstances.disposableSupplierObjects.get().add((DisposableSupplier<T>) supplier, instance);
}
return instance;
}
@@ -676,7 +749,7 @@
* @param <X> The expected return type for the TYPE.
* @param <TYPE> The Type for which a {@link Binding} has been created.
*/
- private abstract class XBindings<X, TYPE> {
+ private abstract class XBindings<X, TYPE extends Type> {
protected final List<InstanceBinding<X>> instanceBindings = new LinkedList<>();
protected final List<SupplierInstanceBinding<X>> supplierInstanceBindings = new LinkedList<>();
@@ -757,12 +830,8 @@
private X _create(SupplierInstanceBinding<X> binding) {
Supplier<X> supplier = binding.getSupplier();
- X t = registerDisposableSupplierAndGet(supplier);
- if (Singleton.class.equals(binding.getScope())) {
- _addInstance(t, binding);
- } else if (_isPerThread(binding.getScope())) {
- _addThreadInstance(t, binding);
- }
+ X t = registerDisposableSupplierAndGet(supplier, instances);
+ t = addInstance(type, t, binding);
return t;
}
@@ -826,20 +895,17 @@
protected abstract X _createAndStore(ClassBinding<X> binding);
- protected <T> T _addInstance(TYPE type, T instance, Binding<?, ?> binding) {
+ protected <T> T _addSingletonInstance(TYPE type, T instance, Binding<?, ?> binding) {
return instances.addSingleton(type, instance, binding, instancesQualifiers);
}
- protected void _addThreadInstance(TYPE type, Object instance, Binding binding) {
- instances.addThreadInstance(type, instance, binding, instancesQualifiers);
- }
-
- protected <T> T _addInstance(T instance, Binding<?, ?> binding) {
- return instances.addSingleton(type, instance, binding, instancesQualifiers);
- }
-
- protected void _addThreadInstance(Object instance, Binding binding) {
- instances.addThreadInstance(type, instance, binding, instancesQualifiers);
+ protected <T> T addInstance(TYPE type, T instance, Binding binding) {
+ if (Singleton.class.equals(binding.getScope())) {
+ instance = instances.addSingleton(type, instance, binding, instancesQualifiers);
+ } else if (_isPerThread(binding.getScope())) {
+ instances.addThreadInstance(type, instance, binding, instancesQualifiers);
+ }
+ return instance;
}
}
@@ -899,28 +965,27 @@
}
protected T _create(SupplierClassBinding<T> binding) {
- Supplier<T> supplier = instances.getInstance(binding.getSupplierClass(), null);
- if (supplier == null) {
- supplier = justCreate(binding.getSupplierClass());
- if (Singleton.class.equals(binding.getSupplierScope())) {
- supplier = instances.addSingleton(binding.getSupplierClass(), supplier, binding, null);
- } else if (_isPerThread(binding.getSupplierScope())) {
- instances.addThreadInstance(binding.getSupplierClass(), supplier, binding, null);
+ Supplier<Supplier<T>> supplierSupplier = () -> {
+ Supplier<T> supplier = instances.getInstance(binding.getSupplierClass(), null);
+ if (supplier == null) {
+ supplier = justCreate(binding.getSupplierClass());
+ if (Singleton.class.equals(binding.getSupplierScope())) {
+ supplier = instances.addSingleton(binding.getSupplierClass(), supplier, binding, null);
+ } else if (_isPerThread(binding.getSupplierScope()) || binding.getSupplierScope() == null) {
+ instances.addThreadInstance(binding.getSupplierClass(), supplier, binding, null);
+ }
}
- }
+ return supplier;
+ };
- T t = createSupplierProxyIfNeeded(binding.isProxiable(), (Class<T>) type, supplier);
- if (Singleton.class.equals(binding.getScope())) {
- t = _addInstance(type, t, binding);
- } else if (_isPerThread(binding.getScope())) {
- _addThreadInstance(type, t, binding);
- }
+ T t = createSupplierProxyIfNeeded(binding.isProxiable(), (Class<T>) type, supplierSupplier, instances);
+// t = addInstance(type, t, binding); The supplier here creates instances that ought not to be registered as beans
return t;
}
protected T _createAndStore(ClassBinding<T> binding) {
T result = justCreate(binding.getService());
- result = _addInstance(binding.getService(), result, binding);
+ result = addInstance(binding.getService(), result, binding);
return result;
}
}
@@ -933,19 +998,15 @@
protected T _create(SupplierClassBinding<T> binding) {
Supplier<T> supplier = justCreate(binding.getSupplierClass());
- T t = registerDisposableSupplierAndGet(supplier);
- if (Singleton.class.equals(binding.getScope())) {
- t = _addInstance(type, t, binding);
- } else if (_isPerThread(binding.getScope())) {
- _addThreadInstance(type, t, binding);
- }
+ T t = registerDisposableSupplierAndGet(supplier, instances);
+ t = addInstance(type, t, binding);
return t;
}
@Override
protected T _createAndStore(ClassBinding<T> binding) {
T result = justCreate(binding.getService());
- result = _addInstance(type, result, binding);
+ result = addInstance(type, result, binding);
return result;
}
@@ -966,7 +1027,7 @@
return NonInjectionManager.this.getInstance(actualTypeArgument);
}
}
- });
+ }, instances);
@Override
public Object get() {
@@ -989,13 +1050,16 @@
private final T instance;
private final Binding<?, ?> binding;
private final Annotation[] createdWithQualifiers;
+ private boolean destroyed = false;
- private InstanceContext(T instance, Binding<?, ?> binding, Annotation[] qualifiers) {
+ private InstanceContext(T instance, Binding<?, ?> binding, Annotation[] qualifiers, boolean destroyed) {
this.instance = instance;
this.binding = binding;
this.createdWithQualifiers = qualifiers;
+ this.destroyed = destroyed;
}
+
public Binding<?, ?> getBinding() {
return binding;
}
@@ -1004,6 +1068,13 @@
return instance;
}
+ public void destroy(NonInjectionManager nonInjectionManager) {
+ if (!destroyed) {
+ destroyed = true;
+ nonInjectionManager.preDestroy(instance);
+ }
+ }
+
@SuppressWarnings("unchecked")
static <T> List<T> toInstances(List<InstanceContext<?>> instances, Annotation[] qualifiers) {
return instances != null
@@ -1022,6 +1093,15 @@
: null;
}
+ private static List<InstanceContext<?>> merge(List<InstanceContext<?>> i1, List<InstanceContext<?>> i2) {
+ if (i1 == null) {
+ i1 = i2;
+ } else if (i2 != null) {
+ i1.addAll(i2);
+ }
+ return i1;
+ }
+
private boolean hasQualifiers(Annotation[] requested) {
if (requested != null) {
classLoop:
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java
index 258780d..b8b23b2 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.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
@@ -20,14 +20,20 @@
import org.glassfish.jersey.internal.util.LazyUid;
import org.glassfish.jersey.process.internal.RequestScope;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class NonInjectionRequestScope extends RequestScope {
+
+ private final NonInjectionManager nonInjectionManager;
+
+ public NonInjectionRequestScope(NonInjectionManager nonInjectionManager) {
+ this.nonInjectionManager = nonInjectionManager;
+ }
+
@Override
public org.glassfish.jersey.process.internal.RequestContext createContext() {
- return new Instance();
+ return new Instance(nonInjectionManager);
}
/**
@@ -35,6 +41,8 @@
*/
public static final class Instance implements org.glassfish.jersey.process.internal.RequestContext {
+ private final NonInjectionManager injectionManager;
+
private static final ExtendedLogger logger = new ExtendedLogger(Logger.getLogger(Instance.class.getName()), Level.FINEST);
/*
@@ -48,10 +56,11 @@
/**
* Holds the number of snapshots of this scope.
*/
- private final AtomicInteger referenceCounter;
+ private int referenceCounter;
- private Instance() {
- this.referenceCounter = new AtomicInteger(1);
+ private Instance(NonInjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ this.referenceCounter = 1;
}
/**
@@ -65,7 +74,7 @@
@Override
public NonInjectionRequestScope.Instance getReference() {
// TODO: replace counter with a phantom reference + reference queue-based solution
- referenceCounter.incrementAndGet();
+ referenceCounter++;
return this;
}
@@ -77,7 +86,9 @@
*/
@Override
public void release() {
- referenceCounter.decrementAndGet();
+ if (0 == --referenceCounter) {
+ injectionManager.disposeRequestScopedInstances();
+ }
}
@Override
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 f5a3409..630cb96 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2023 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
@@ -37,6 +37,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Supplier;
@@ -65,6 +66,7 @@
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.internal.util.collection.LRU;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.internal.util.collection.UnsafeValue;
import org.glassfish.jersey.internal.util.collection.Value;
@@ -113,7 +115,12 @@
private final boolean fixLengthStreaming;
private final boolean setMethodWorkaround;
private final boolean isRestrictedHeaderPropertySet;
- private LazyValue<SSLSocketFactory> sslSocketFactory;
+ private Value<SSLSocketFactory> sslSocketFactory;
+
+ // SSLContext#getSocketFactory not idempotent
+ // JDK KeepAliveCache keeps connections per Factory
+ // SSLContext set per request blows that -> keep factory in LRU
+ private final LRU<SSLContext, SSLSocketFactory> sslSocketFactoryCache = LRU.create();
private final ConnectorExtension<HttpURLConnection, IOException> connectorExtension
= new HttpUrlExpect100ContinueConnectorExtension();
@@ -142,6 +149,13 @@
this.fixLengthStreaming = fixLengthStreaming;
this.setMethodWorkaround = setMethodWorkaround;
+ this.sslSocketFactory = Values.lazy(new Value<SSLSocketFactory>() {
+ @Override
+ public SSLSocketFactory get() {
+ return client.getSslContext().getSocketFactory();
+ }
+ });
+
// check if sun.net.http.allowRestrictedHeaders system property has been set and log the result
// the property is being cached in the HttpURLConnection, so this is only informative - there might
// already be some connection(s), that existed before the property was set/changed.
@@ -155,7 +169,7 @@
);
}
- private static InputStream getInputStream(final HttpURLConnection uc) throws IOException {
+ private static InputStream getInputStream(final HttpURLConnection uc, final ClientRequest clientRequest) throws IOException {
return new InputStream() {
private final UnsafeValue<InputStream, IOException> in = Values.lazy(new UnsafeValue<InputStream, IOException>() {
@Override
@@ -190,6 +204,10 @@
if (closed) {
throw new IOException("Stream closed");
}
+ if (clientRequest.isCancelled()) {
+ close();
+ throw new IOException(new CancellationException());
+ }
}
@Override
@@ -311,7 +329,7 @@
if (DEFAULT_SSL_SOCKET_FACTORY.get() == suc.getSSLSocketFactory()) {
// indicates that the custom socket factory was not set
suc.setSSLSocketFactory(sslSocketFactory.get());
- }
+ }
}
}
@@ -337,22 +355,30 @@
}
}
- private void setSslContextFactory(Client client, ClientRequest request) {
+ protected void setSslContextFactory(Client client, ClientRequest request) {
final Supplier<SSLContext> supplier = request.resolveProperty(ClientProperties.SSL_CONTEXT_SUPPLIER, Supplier.class);
- sslSocketFactory = Values.lazy(new Value<SSLSocketFactory>() {
- @Override
- public SSLSocketFactory get() {
- final SSLContext ctx = supplier == null ? client.getSslContext() : supplier.get();
- return ctx.getSocketFactory();
- }
- });
+ if (supplier != null) {
+ sslSocketFactory = Values.lazy(new Value<SSLSocketFactory>() { // lazy for double-check locking if multiple requests
+ @Override
+ public SSLSocketFactory get() {
+ SSLContext sslContext = supplier.get();
+ SSLSocketFactory factory = sslSocketFactoryCache.getIfPresent(sslContext);
+ if (factory == null) {
+ factory = sslContext.getSocketFactory();
+ sslSocketFactoryCache.put(sslContext, factory);
+ }
+ return factory;
+ }
+ });
+ }
}
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).build();
final URI sniUri;
if (sniConfig.isSNIRequired()) {
sniUri = sniConfig.toIPRequestUri();
@@ -361,6 +387,10 @@
sniUri = request.getUri();
}
+ if (!DEFAULT_SSL_SOCKET_FACTORY.isInitialized() && "HTTPS".equalsIgnoreCase(sniUri.getScheme())) {
+ DEFAULT_SSL_SOCKET_FACTORY.get();
+ }
+
proxy.ifPresent(clientProxy -> ClientProxy.setBasicAuthorizationHeader(request.getHeaders(), proxy.get()));
uc = this.connectionFactory.getConnection(sniUri.toURL(), proxy.isPresent() ? proxy.get().proxy() : null);
uc.setDoInput(true);
@@ -448,7 +478,7 @@
);
try {
- InputStream inputStream = getInputStream(uc);
+ InputStream inputStream = getInputStream(uc, request);
responseContext.setEntityStream(inputStream);
} catch (IOException ioe) {
// allow at least a partial response in a ResponseProcessingException
diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
index 291ac98..8940d72 100644
--- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
+++ b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
@@ -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
@@ -50,7 +50,7 @@
Reverting to programmatically set default: [{1}]
negative.input.parameter="Input parameter {0} must not be negative1."
noninject.ambiguous.services=Ambiguous providing services ${0}.
-noninject.fallback=Falling back to injection-less client.
+noninject.fallback=Jersey-HK2 module is missing. Falling back to injection-less client. Injection may not be supported on the client.
noninject.no.constructor=No applicable constructor for ${0} found.
noninject.no.binding=No binding found for ${0}.
noninject.requestscope.created=RequestScope already created.
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-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java b/core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java
new file mode 100644
index 0000000..362bbe6
--- /dev/null
+++ b/core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client;
+
+import org.glassfish.jersey.client.internal.HttpUrlConnector;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+public class SSLSocketFactoryTest {
+ static final AtomicReference<SSLSocketFactory> factoryHolder = new AtomicReference<>();
+ static SSLSocketFactory defaultSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
+
+ // @Test
+ // Alternative test
+ // Check KeepAliveCache#get(URL url, Object obj)
+ public void testSingleConnection() throws InterruptedException, IOException {
+ Client client = ClientBuilder.newClient();
+
+ for (int i = 0; i < 3; i++) {
+ try (Response response = client.target("https://www.spiegel.de")
+ .request()
+ .get()) {
+
+ response.readEntity(String.class);
+ System.out.println(String.format("response = %s", response));
+ Thread.sleep(1000);
+ }
+ }
+
+ System.in.read();
+ }
+
+ @Test
+ public void testSslContextFactoryOnClientIsSameForConsecutiveRequests() throws IOException, URISyntaxException {
+ int firstRequestFactory, secondRequestFactory = 0;
+ Client client = ClientBuilder.newClient();
+ HttpUrlConnectorProvider.ConnectionFactory connectionFactory = (url) -> (HttpURLConnection) url.openConnection();
+ SSLSocketFactoryConnector connector = (SSLSocketFactoryConnector) new SSlSocketFactoryUrlConnectorProvider()
+ .createHttpUrlConnector(client, connectionFactory, 4096, true, false);
+ URL url = new URL("https://somewhere.whereever:8080");
+ URLConnection urlConnection = url.openConnection();
+
+ // First Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), new MapPropertiesDelegate()));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ firstRequestFactory = factoryHolder.get().hashCode();
+
+ // reset to the default socketFactory
+ ((HttpsURLConnection) urlConnection).setSSLSocketFactory(defaultSocketFactory);
+
+ // Second Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), new MapPropertiesDelegate()));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ secondRequestFactory = factoryHolder.get().hashCode();
+
+ MatcherAssert.assertThat(firstRequestFactory, Matchers.equalTo(secondRequestFactory));
+ }
+
+ @Test
+ public void testSslContextFactoryOnRequestIsSameForConsecutiveRequests() throws IOException, URISyntaxException {
+ SSLSocketFactory firstRequestFactory, secondRequestFactory = null;
+ Client client = ClientBuilder.newClient();
+ SSLContext sslContext = new SslContextClientBuilder().build();
+ HttpUrlConnectorProvider.ConnectionFactory connectionFactory = (url) -> (HttpURLConnection) url.openConnection();
+ SSLSocketFactoryConnector connector = (SSLSocketFactoryConnector) new SSlSocketFactoryUrlConnectorProvider()
+ .createHttpUrlConnector(client, connectionFactory, 4096, true, false);
+ URL url = new URL("https://somewhere.whereever:8080");
+ URLConnection urlConnection = url.openConnection();
+ PropertiesDelegate propertiesDelegate = new MapPropertiesDelegate();
+ propertiesDelegate.setProperty(ClientProperties.SSL_CONTEXT_SUPPLIER, (Supplier<SSLContext>) () -> sslContext);
+
+ // First Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), propertiesDelegate));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ firstRequestFactory = factoryHolder.get();
+
+ // reset to the default socketFactory
+ ((HttpsURLConnection) urlConnection).setSSLSocketFactory(defaultSocketFactory);
+
+ // Second Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), propertiesDelegate));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ secondRequestFactory = factoryHolder.get();
+
+ MatcherAssert.assertThat(firstRequestFactory, Matchers.equalTo(secondRequestFactory));
+ }
+
+ private static class SSLSocketFactoryConnector extends HttpUrlConnector {
+ public SSLSocketFactoryConnector(Client client, HttpUrlConnectorProvider.ConnectionFactory connectionFactory,
+ int chunkSize, boolean fixLengthStreaming, boolean setMethodWorkaround) {
+ super(client, connectionFactory, chunkSize, fixLengthStreaming, setMethodWorkaround);
+ }
+
+ @Override
+ protected void secureConnection(JerseyClient client, HttpURLConnection uc) {
+ super.secureConnection(client, uc);
+ if (HttpsURLConnection.class.isInstance(uc)) {
+ SSLSocketFactory factory = ((HttpsURLConnection) uc).getSSLSocketFactory();
+ factoryHolder.set(factory);
+ }
+ }
+
+ @Override
+ protected void setSslContextFactory(Client client, ClientRequest request) {
+ super.setSslContextFactory(client, request);
+ }
+ }
+
+ private static class SSlSocketFactoryUrlConnectorProvider extends HttpUrlConnectorProvider {
+ @Override
+ protected Connector createHttpUrlConnector(Client client, ConnectionFactory connectionFactory, int chunkSize,
+ boolean fixLengthStreaming, boolean setMethodWorkaround) {
+ return new SSLSocketFactoryConnector(
+ client,
+ connectionFactory,
+ chunkSize,
+ fixLengthStreaming,
+ setMethodWorkaround);
+ }
+ }
+}
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java
new file mode 100644
index 0000000..06dcdec
--- /dev/null
+++ b/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.http;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.http.HttpHeaders;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class SSLParamConfiguratorTest {
+ @Test
+ public void testNoHost() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(false));
+ }
+
+ @Test
+ public void testHostHeaderHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "yyy.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testPropertyOnClientHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testPropertyOnDelegateHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "zzz.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("zzz.com"));
+ }
+
+ @Test
+ public void testPropertyOnDelegateHasPrecedenceOverHost() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "zzz.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("zzz.com"));
+ }
+
+ @Test
+ public void testDisableSni() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "xxx.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(false));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("xxx.com"));
+ }
+
+ @Test
+ public void testLowerCasePropertyOnClientHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT), "yyy.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testUriAndHeadersAndConfig() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ Map<String, List<Object>> httpHeaders = new MultivaluedHashMap<>();
+ httpHeaders.put(HttpHeaders.HOST, Collections.singletonList("www.com"));
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder()
+ .uri(uri)
+ .headers(httpHeaders)
+ .configuration(client.getConfiguration())
+ .build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("www.com"));
+
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ configurator = SSLParamConfigurator.builder()
+ .uri(uri)
+ .headers(httpHeaders)
+ .configuration(client.getConfiguration())
+ .build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+}
diff --git a/core-common/pom.xml b/core-common/pom.xml
index 0d431f0..016395e 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -71,10 +71,10 @@
</resources>
<testResources>
- <testResource>
- <directory>${basedir}/src/test/resources</directory>
- <filtering>true</filtering>
- </testResource>
+ <testResource>
+ <directory>${basedir}/src/test/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
</testResources>
<plugins>
@@ -84,6 +84,8 @@
<version>${compiler.common.mvn.plugin.version}</version>
<inherited>false</inherited>
<configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
<compilerArguments>
<!-- Do not warn about using sun.misc.Unsafe -->
<XDignore.symbol.file />
@@ -213,13 +215,12 @@
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
-<!--
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-activation</artifactId>
<scope>provided</scope>
<optional>true</optional>
- </dependency> -->
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
@@ -260,21 +261,192 @@
<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}${path.separator}${project.basedir}/src/main/java/org/glassfish/jersey/innate/virtual" 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.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <inherited>true</inherited>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Multi-Release>true</Multi-Release>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <inherited>true</inherited>
+ <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>
+ <activation>
+ <jdk>[24,)</jdk>
+ </activation>
<properties>
- <surefire.security.argline />
+ <surefire.security.argline />
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>**/SecurityManagerConfiguredTest.java</exclude>
- <exclude>**/ReflectionHelperTest.java</exclude>
- </excludes>
- </configuration>
+ <executions>
+ <execution>
+ <id>default-test</id>
+ <configuration>
+ <excludes>
+ <exclude>**/SecurityManagerConfiguredTest.java</exclude>
+ <exclude>**/ReflectionHelperTest.java</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
@@ -299,6 +471,8 @@
<properties>
<surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/surefire.policy</surefire.security.argline>
+ <java21.build.outputDirectory>${project.build.directory}/classes-java21</java21.build.outputDirectory>
+ <java21.sourceDirectory>${project.basedir}/src/main/java21</java21.sourceDirectory>
<surefire.coverage.argline>
--add-reads org.glassfish.jersey.core.common=ALL-UNNAMED
--add-modules=ALL-MODULE-PATH
diff --git a/core-common/src/main/java/module-info.java b/core-common/src/main/java/module-info.java
index 3a3f1f5..a1017e3 100644
--- a/core-common/src/main/java/module-info.java
+++ b/core-common/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -53,7 +53,28 @@
exports org.glassfish.jersey.uri;
exports org.glassfish.jersey.uri.internal;
- exports org.glassfish.jersey.innate.spi to org.glassfish.jersey.media.multipart;
+
+ exports org.glassfish.jersey.innate to org.glassfish.jersey.container.grizzly2.http,
+ org.glassfish.jersey.container.servlet.core,
+ org.glassfish.jersey.container.jetty.http,
+ org.glassfish.jersey.netty.connector,
+ org.glassfish.jersey.ext.mp.rest.client;
+ exports org.glassfish.jersey.innate.virtual to org.glassfish.jersey.container.grizzly2.http,
+ org.glassfish.jersey.container.jetty.http,
+ org.glassfish.jersey.netty.connector,
+ org.glassfish.jersey.ext.mp.rest.client;
+
+ opens org.glassfish.jersey.innate.virtual to org.glassfish.jersey.container.grizzly2.http,
+ org.glassfish.jersey.container.jetty.http;
+ opens org.glassfish.jersey.innate to org.glassfish.jersey.container.servlet.core;
+
+ exports org.glassfish.jersey.innate.io to org.glassfish.jersey.core.server,
+ org.glassfish.jersey.container.servlet.core,
+ org.glassfish.jersey.apache5.connector,
+ org.glassfish.jersey.apache.connector;
+ exports org.glassfish.jersey.innate.spi to org.glassfish.jersey.core.client,
+ org.glassfish.jersey.media.multipart;
+ exports org.glassfish.jersey.innate.inject.spi to org.glassfish.jersey.inject.hk2;
opens org.glassfish.jersey.innate.spi to org.glassfish.jersey.media.multipart;
opens org.glassfish.jersey.internal;
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java
similarity index 63%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java
index 0fdbe9d..6ef17b9 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.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
@@ -14,7 +14,20 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
+
+package org.glassfish.jersey;
+
+import jakarta.ws.rs.core.Application;
+
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Implementation of this interface is capable of returning {@link Application}.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+public interface ApplicationSupplier {
+ /**
+ * Get Application.
+ *
+ * @return Application.
+ */
+ Application getApplication();
+
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
index e71e5e1..308ff94 100644
--- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
+++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.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
@@ -71,7 +71,7 @@
/**
* If {@code true} then disable feature auto discovery globally on client/server.
* <p>
- * By default auto discovery is automatically enabled. The value of this property may be overridden by the client/server
+ * By default, auto discovery is automatically enabled. The value of this property may be overridden by the client/server
* variant of this property.
* <p>
* The default value is {@code false}.
@@ -98,10 +98,55 @@
*/
public static final String FEATURE_AUTO_DISCOVERY_DISABLE_SERVER = "jersey.config.server.disableAutoDiscovery";
+
+ /**
+ * If {@code true} then disable configuration of Json Binding (JSR-367) feature.
+ * <p>
+ * By default, Json Binding is automatically enabled. The value of this property may be overridden by the client/server
+ * variant of this property.
+ * <p>
+ * The default value is {@code false}.
+ * </p>
+ * <p>
+ * The name of the configuration property is <tt>{@value}</tt>.
+ * </p>
+ * @since 2.45
+ */
+ public static final String JSON_BINDING_FEATURE_DISABLE = "jersey.config.disableJsonBinding";
+
+ /**
+ * Client-specific version of {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE}.
+ *
+ * If present, it overrides the generic one for the client environment.
+ * @since 2.45
+ */
+ public static final String JSON_BINDING_FEATURE_DISABLE_CLIENT = "jersey.config.client.disableJsonBinding";
+
+ /**
+ * Server-specific version of {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE}.
+ *
+ * If present, it overrides the generic one for the server environment.
+ * @since 2.45
+ */
+ public static final String JSON_BINDING_FEATURE_DISABLE_SERVER = "jersey.config.server.disableJsonBinding";
+
+ /**
+ * Disables configuration of Json Binding (JSR-367) feature for {@link jakarta.ws.rs.core.Application} subclasses whose
+ * package names are specified as a value. The value is comma-separated string defining prefixes of the application
+ * package names.
+ * <p>
+ * By default, Json Binding is automatically enabled.
+ * <p>
+ * The name of the configuration property is <tt>{@value}</tt>.
+ * </p>
+ * @since 2.45
+ */
+ public static final String JSON_BINDING_FEATURE_DISABLE_APPLICATION = "jersey.config.application.disableJsonBinding";
+
/**
* If {@code true} then disable configuration of Json Processing (JSR-353) feature.
* <p>
- * By default Json Processing is automatically enabled. The value of this property may be overridden by the client/server
+ * By default, Json Processing is automatically enabled. The value of this property may be overridden by the client/server
* variant of this property.
* <p>
* The default value is {@code false}.
@@ -131,7 +176,7 @@
/**
* If {@code true} then disable META-INF/services lookup globally on client/server.
* <p>
- * By default Jersey looks up SPI implementations described by META-INF/services/* files.
+ * By default, Jersey looks up SPI implementations described by META-INF/services/* files.
* Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}.
* </p>
* <p>
@@ -164,7 +209,7 @@
/**
* If {@code true} then disable configuration of MOXy Json feature.
* <p>
- * By default MOXy Json is automatically enabled. The value of this property may be overridden by the client/server
+ * By default, MOXy Json is automatically enabled. The value of this property may be overridden by the client/server
* variant of this property.
* <p>
* The default value is {@code false}.
@@ -321,6 +366,30 @@
public static final String PARAM_CONVERTERS_THROW_IAE = "jersey.config.paramconverters.throw.iae";
/**
+ * <p>
+ * Defines the {@link java.util.concurrent.ThreadFactory} to be used by internal default Executor Services.
+ * </p>
+ * <p>
+ * The default is {@link java.util.concurrent.Executors#defaultThreadFactory()} on platform threads and
+ * {@code Thread.ofVirtual().factory()} on virtual threads.
+ * </p>
+ * @since 3.1.7
+ */
+ public static String THREAD_FACTORY = "jersey.config.threads.factory";
+
+ /**
+ * <p>
+ * Defines whether the virtual threads should be used by Jersey on JDK 21+ when not using an exact number
+ * of threads by {@code FixedThreadPool}.
+ * </p>
+ * <p>
+ * The default is {@code false} for this version of Jersey.
+ * </p>
+ * @since 3.1.7
+ */
+ public static String USE_VIRTUAL_THREADS = "jersey.config.threads.use.virtual";
+
+ /**
* Prevent instantiation.
*/
private CommonProperties() {
diff --git a/core-common/src/main/java/org/glassfish/jersey/SslConfigurator.java b/core-common/src/main/java/org/glassfish/jersey/SslConfigurator.java
index b3befea..2bef140 100644
--- a/core-common/src/main/java/org/glassfish/jersey/SslConfigurator.java
+++ b/core-common/src/main/java/org/glassfish/jersey/SslConfigurator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
import java.nio.file.Files;
import java.security.AccessController;
import java.security.KeyManagementException;
@@ -31,6 +32,7 @@
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
+import java.util.Objects;
import java.util.Properties;
import java.util.logging.Logger;
@@ -241,6 +243,9 @@
private String trustStoreFile;
private String keyStoreFile;
+ private URL trustStoreUrl;
+ private URL keyStoreUrl;
+
private byte[] trustStoreBytes;
private byte[] keyStoreBytes;
@@ -321,6 +326,8 @@
this.keyPass = that.keyPass;
this.trustStoreFile = that.trustStoreFile;
this.keyStoreFile = that.keyStoreFile;
+ this.keyStoreUrl = that.keyStoreUrl;
+ this.trustStoreUrl = that.trustStoreUrl;
this.trustStoreBytes = that.trustStoreBytes;
this.keyStoreBytes = that.keyStoreBytes;
this.trustManagerFactoryAlgorithm = that.trustManagerFactoryAlgorithm;
@@ -441,8 +448,9 @@
/**
* Set the <em>trust</em> store file name.
* <p>
- * Setting a trust store instance resets any {@link #trustStore(java.security.KeyStore) trust store instance}
- * or {@link #trustStoreBytes(byte[]) trust store payload} value previously set.
+ * Setting a trust store instance resets any {@link #trustStore(java.security.KeyStore) trust store instance},
+ * {@link #trustStoreBytes(byte[]) trust store payload} or {@link #trustStoreUrl(URL) trust store url}
+ * value previously set.
* </p>
*
* @param fileName {@link java.io.File file} name of the <em>trust</em> store.
@@ -451,6 +459,26 @@
public SslConfigurator trustStoreFile(String fileName) {
this.trustStoreFile = fileName;
this.trustStoreBytes = null;
+ this.trustStoreUrl = null;
+ this.trustStore = null;
+ return this;
+ }
+
+ /**
+ * Set the <em>trust</em> store file url.
+ * <p>
+ * Setting a trust store instance resets any {@link #trustStore(java.security.KeyStore) trust store instance},
+ * {@link #trustStoreBytes(byte[]) trust store payload} or {@link #trustStoreUrl(URL) trust store url}
+ * value previously set.
+ * </p>
+ *
+ * @param url {@link java.net.URL url} link of the <em>trust</em> store.
+ * @return updated SSL configurator instance.
+ */
+ public SslConfigurator trustStoreUrl(URL url) {
+ this.trustStoreFile = null;
+ this.trustStoreBytes = null;
+ this.trustStoreUrl = url;
this.trustStore = null;
return this;
}
@@ -458,8 +486,9 @@
/**
* Set the <em>trust</em> store payload as byte array.
* <p>
- * Setting a trust store instance resets any {@link #trustStoreFile(String) trust store file}
- * or {@link #trustStore(java.security.KeyStore) trust store instance} value previously set.
+ * Setting a trust store instance resets any {@link #trustStoreFile(String) trust store file},
+ * {@link #trustStore(java.security.KeyStore) trust store instance} or {@link #trustStoreUrl(URL) trust store url}
+ * value previously set.
* </p>
*
* @param payload <em>trust</em> store payload.
@@ -468,6 +497,7 @@
public SslConfigurator trustStoreBytes(byte[] payload) {
this.trustStoreBytes = payload.clone();
this.trustStoreFile = null;
+ this.trustStoreUrl = null;
this.trustStore = null;
return this;
}
@@ -475,8 +505,8 @@
/**
* Set the <em>key</em> store file name.
* <p>
- * Setting a key store instance resets any {@link #keyStore(java.security.KeyStore) key store instance}
- * or {@link #keyStoreBytes(byte[]) key store payload} value previously set.
+ * Setting a key store instance resets any {@link #keyStore(java.security.KeyStore) key store instance},
+ * {@link #keyStoreBytes(byte[]) key store payload} or {@link #keyStoreUrl(URL) key store url} value previously set.
* </p>
*
* @param fileName {@link java.io.File file} name of the <em>key</em> store.
@@ -484,6 +514,26 @@
*/
public SslConfigurator keyStoreFile(String fileName) {
this.keyStoreFile = fileName;
+ this.keyStoreUrl = null;
+ this.keyStoreBytes = null;
+ this.keyStore = null;
+ return this;
+ }
+
+ /**
+ * Set the <em>key</em> store url.
+ * <p>
+ * Setting a key store instance resets any {@link #keyStore(java.security.KeyStore) key store instance},
+ * {@link #keyStoreBytes(byte[]) key store payload} or {@link #keyStoreFile(String) key store file}
+ * value previously set.
+ * </p>
+ *
+ * @param url {@link java.net.URL url} of the <em>key</em> store.
+ * @return updated SSL configurator instance.
+ */
+ public SslConfigurator keyStoreUrl(URL url) {
+ this.keyStoreFile = null;
+ this.keyStoreUrl = url;
this.keyStoreBytes = null;
this.keyStore = null;
return this;
@@ -492,8 +542,9 @@
/**
* Set the <em>key</em> store payload as byte array.
* <p>
- * Setting a key store instance resets any {@link #keyStoreFile(String) key store file}
- * or {@link #keyStore(java.security.KeyStore) key store instance} value previously set.
+ * Setting a key store instance resets any {@link #keyStoreFile(String) key store file},
+ * {@link #keyStore(java.security.KeyStore) key store instance} or {@link #keyStoreUrl(URL) key store url}
+ * value previously set.
* </p>
*
* @param payload <em>key</em> store payload.
@@ -501,6 +552,7 @@
*/
public SslConfigurator keyStoreBytes(byte[] payload) {
this.keyStoreBytes = payload.clone();
+ this.keyStoreUrl = null;
this.keyStoreFile = null;
this.keyStore = null;
return this;
@@ -573,8 +625,8 @@
/**
* Set the <em>key</em> store instance.
* <p>
- * Setting a key store instance resets any {@link #keyStoreFile(String) key store file}
- * or {@link #keyStoreBytes(byte[]) key store payload} value previously set.
+ * Setting a key store instance resets any {@link #keyStoreFile(String) key store file},
+ * {@link #keyStoreBytes(byte[]) key store payload} or {@link #keyStoreUrl(URL) key store url} value previously set.
* </p>
*
* @param keyStore <em>key</em> store instance.
@@ -584,15 +636,12 @@
this.keyStore = keyStore;
this.keyStoreFile = null;
this.keyStoreBytes = null;
+ this.keyStoreUrl = null;
return this;
}
/**
* Get the <em>trust</em> store instance.
- * <p>
- * Setting a trust store instance resets any {@link #trustStoreFile(String) trust store file}
- * or {@link #trustStoreBytes(byte[]) trust store payload} value previously set.
- * </p>
*
* @return <em>trust</em> store instance or {@code null} if not explicitly set.
*/
@@ -602,12 +651,16 @@
/**
* Set the <em>trust</em> store instance.
- *
+ * <p>
+ * Setting a trust store instance resets any {@link #trustStoreFile(String) trust store file},
+ * {@link #trustStoreBytes(byte[]) trust store payload} or {@link #trustStoreUrl(URL) trust store url} value previously set.
+ * </p>
* @param trustStore <em>trust</em> store instance.
* @return updated SSL configurator instance.
*/
public SslConfigurator trustStore(KeyStore trustStore) {
this.trustStore = trustStore;
+ this.trustStoreUrl = null;
this.trustStoreFile = null;
this.trustStoreBytes = null;
return this;
@@ -623,7 +676,7 @@
KeyManagerFactory keyManagerFactory = null;
KeyStore _keyStore = keyStore;
- if (_keyStore == null && (keyStoreBytes != null || keyStoreFile != null)) {
+ if (_keyStore == null && (keyStoreBytes != null || keyStoreFile != null || keyStoreUrl != null)) {
try {
if (keyStoreProvider != null) {
_keyStore = KeyStore.getInstance(
@@ -635,6 +688,8 @@
try {
if (keyStoreBytes != null) {
keyStoreInputStream = new ByteArrayInputStream(keyStoreBytes);
+ } else if (keyStoreUrl != null) {
+ keyStoreInputStream = keyStoreUrl.openStream();
} else if (!keyStoreFile.equals("NONE")) {
keyStoreInputStream = Files.newInputStream(new File(keyStoreFile).toPath());
}
@@ -697,7 +752,7 @@
}
KeyStore _trustStore = trustStore;
- if (_trustStore == null && (trustStoreBytes != null || trustStoreFile != null)) {
+ if (_trustStore == null && (trustStoreBytes != null || trustStoreFile != null || trustStoreUrl != null)) {
try {
if (trustStoreProvider != null) {
_trustStore = KeyStore.getInstance(
@@ -710,6 +765,8 @@
try {
if (trustStoreBytes != null) {
trustStoreInputStream = new ByteArrayInputStream(trustStoreBytes);
+ } else if (trustStoreUrl != null) {
+ trustStoreInputStream = trustStoreUrl.openStream();
} else if (!trustStoreFile.equals("NONE")) {
trustStoreInputStream = Files.newInputStream(new File(trustStoreFile).toPath());
}
@@ -808,6 +865,9 @@
trustStoreFile = props.getProperty(TRUST_STORE_FILE);
keyStoreFile = props.getProperty(KEY_STORE_FILE);
+ keyStoreUrl = null;
+ trustStoreUrl = null;
+
trustStoreBytes = null;
keyStoreBytes = null;
@@ -857,6 +917,9 @@
trustStoreFile = AccessController.doPrivileged(PropertiesHelper.getSystemProperty(TRUST_STORE_FILE));
keyStoreFile = AccessController.doPrivileged(PropertiesHelper.getSystemProperty(KEY_STORE_FILE));
+ trustStoreUrl = null;
+ keyStoreUrl = null;
+
trustStoreBytes = null;
keyStoreBytes = null;
@@ -876,91 +939,35 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
-
SslConfigurator that = (SslConfigurator) o;
-
- if (keyManagerFactoryAlgorithm != null
- ? !keyManagerFactoryAlgorithm.equals(that.keyManagerFactoryAlgorithm) : that.keyManagerFactoryAlgorithm != null) {
- return false;
- }
- if (keyManagerFactoryProvider != null
- ? !keyManagerFactoryProvider.equals(that.keyManagerFactoryProvider) : that.keyManagerFactoryProvider != null) {
- return false;
- }
- if (!Arrays.equals(keyPass, that.keyPass)) {
- return false;
- }
- if (keyStore != null ? !keyStore.equals(that.keyStore) : that.keyStore != null) {
- return false;
- }
- if (!Arrays.equals(keyStoreBytes, that.keyStoreBytes)) {
- return false;
- }
- if (keyStoreFile != null ? !keyStoreFile.equals(that.keyStoreFile) : that.keyStoreFile != null) {
- return false;
- }
- if (!Arrays.equals(keyStorePass, that.keyStorePass)) {
- return false;
- }
- if (keyStoreProvider != null ? !keyStoreProvider.equals(that.keyStoreProvider) : that.keyStoreProvider != null) {
- return false;
- }
- if (keyStoreType != null ? !keyStoreType.equals(that.keyStoreType) : that.keyStoreType != null) {
- return false;
- }
- if (securityProtocol != null ? !securityProtocol.equals(that.securityProtocol) : that.securityProtocol != null) {
- return false;
- }
- if (trustManagerFactoryAlgorithm != null ? !trustManagerFactoryAlgorithm.equals(that.trustManagerFactoryAlgorithm)
- : that.trustManagerFactoryAlgorithm != null) {
- return false;
- }
- if (trustManagerFactoryProvider != null ? !trustManagerFactoryProvider.equals(that.trustManagerFactoryProvider)
- : that.trustManagerFactoryProvider != null) {
- return false;
- }
- if (trustStore != null ? !trustStore.equals(that.trustStore) : that.trustStore != null) {
- return false;
- }
- if (!Arrays.equals(trustStoreBytes, that.trustStoreBytes)) {
- return false;
- }
- if (trustStoreFile != null ? !trustStoreFile.equals(that.trustStoreFile) : that.trustStoreFile != null) {
- return false;
- }
- if (!Arrays.equals(trustStorePass, that.trustStorePass)) {
- return false;
- }
- if (trustStoreProvider != null ? !trustStoreProvider.equals(that.trustStoreProvider) : that.trustStoreProvider != null) {
- return false;
- }
- if (trustStoreType != null ? !trustStoreType.equals(that.trustStoreType) : that.trustStoreType != null) {
- return false;
- }
-
- return true;
+ return Objects.equals(keyStore, that.keyStore)
+ && Objects.equals(trustStore, that.trustStore)
+ && Objects.equals(trustStoreProvider, that.trustStoreProvider)
+ && Objects.equals(keyStoreProvider, that.keyStoreProvider)
+ && Objects.equals(trustStoreType, that.trustStoreType)
+ && Objects.equals(keyStoreType, that.keyStoreType)
+ && Arrays.equals(trustStorePass, that.trustStorePass)
+ && Arrays.equals(keyStorePass, that.keyStorePass)
+ && Arrays.equals(keyPass, that.keyPass)
+ && Objects.equals(trustStoreFile, that.trustStoreFile)
+ && Objects.equals(keyStoreFile, that.keyStoreFile)
+ && Objects.equals(trustStoreUrl, that.trustStoreUrl)
+ && Objects.equals(keyStoreUrl, that.keyStoreUrl)
+ && Arrays.equals(trustStoreBytes, that.trustStoreBytes)
+ && Arrays.equals(keyStoreBytes, that.keyStoreBytes)
+ && Objects.equals(trustManagerFactoryAlgorithm, that.trustManagerFactoryAlgorithm)
+ && Objects.equals(keyManagerFactoryAlgorithm, that.keyManagerFactoryAlgorithm)
+ && Objects.equals(trustManagerFactoryProvider, that.trustManagerFactoryProvider)
+ && Objects.equals(keyManagerFactoryProvider, that.keyManagerFactoryProvider)
+ && Objects.equals(securityProtocol, that.securityProtocol);
}
@Override
public int hashCode() {
- int result = keyStore != null ? keyStore.hashCode() : 0;
- result = 31 * result + (trustStore != null ? trustStore.hashCode() : 0);
- result = 31 * result + (trustStoreProvider != null ? trustStoreProvider.hashCode() : 0);
- result = 31 * result + (keyStoreProvider != null ? keyStoreProvider.hashCode() : 0);
- result = 31 * result + (trustStoreType != null ? trustStoreType.hashCode() : 0);
- result = 31 * result + (keyStoreType != null ? keyStoreType.hashCode() : 0);
- result = 31 * result + (trustStorePass != null ? Arrays.hashCode(trustStorePass) : 0);
- result = 31 * result + (keyStorePass != null ? Arrays.hashCode(keyStorePass) : 0);
- result = 31 * result + (keyPass != null ? Arrays.hashCode(keyPass) : 0);
- result = 31 * result + (trustStoreFile != null ? trustStoreFile.hashCode() : 0);
- result = 31 * result + (keyStoreFile != null ? keyStoreFile.hashCode() : 0);
- result = 31 * result + (trustStoreBytes != null ? Arrays.hashCode(trustStoreBytes) : 0);
- result = 31 * result + (keyStoreBytes != null ? Arrays.hashCode(keyStoreBytes) : 0);
- result = 31 * result + (trustManagerFactoryAlgorithm != null ? trustManagerFactoryAlgorithm.hashCode() : 0);
- result = 31 * result + (keyManagerFactoryAlgorithm != null ? keyManagerFactoryAlgorithm.hashCode() : 0);
- result = 31 * result + (trustManagerFactoryProvider != null ? trustManagerFactoryProvider.hashCode() : 0);
- result = 31 * result + (keyManagerFactoryProvider != null ? keyManagerFactoryProvider.hashCode() : 0);
- result = 31 * result + (securityProtocol != null ? securityProtocol.hashCode() : 0);
+ int result = Objects.hash(keyStore, trustStore, trustStoreProvider, keyStoreProvider, trustStoreType, keyStoreType,
+ trustStoreFile, keyStoreFile, trustStoreUrl, keyStoreUrl, trustManagerFactoryAlgorithm,
+ keyManagerFactoryAlgorithm, trustManagerFactoryProvider, keyManagerFactoryProvider, securityProtocol,
+ trustStorePass, keyStorePass, keyPass, trustStoreBytes, keyStoreBytes);
return result;
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/VirtualThreadUtil.java b/core-common/src/main/java/org/glassfish/jersey/innate/VirtualThreadUtil.java
new file mode 100644
index 0000000..3511d8e
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/VirtualThreadUtil.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.innate;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
+
+import jakarta.ws.rs.core.Configuration;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Factory class to provide JDK specific implementation of bits related to the virtual thread support.
+ */
+public final class VirtualThreadUtil {
+
+ private static final boolean USE_VIRTUAL_THREADS_BY_DEFAULT = false;
+
+ /**
+ * Do not instantiate.
+ */
+ private VirtualThreadUtil() {
+ throw new IllegalStateException();
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a configuration property.
+ * @param config the {@link Configuration}
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors withConfig(Configuration config) {
+ return withConfig(config, USE_VIRTUAL_THREADS_BY_DEFAULT);
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a configuration property.
+ * @param config the {@link Configuration}
+ * @param useVirtualByDefault the default use if not said otherwise by property
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors withConfig(Configuration config, boolean useVirtualByDefault) {
+ ThreadFactory tfThreadFactory = null;
+ boolean useVirtualThreads = useVirtualThreads(config, useVirtualByDefault);
+
+ if (config != null) {
+ Object threadFactory = config.getProperty(CommonProperties.THREAD_FACTORY);
+ if (threadFactory != null && ThreadFactory.class.isInstance(threadFactory)) {
+ tfThreadFactory = (ThreadFactory) threadFactory;
+ }
+ }
+
+ return tfThreadFactory == null
+ ? VirtualThreadSupport.allowVirtual(useVirtualThreads)
+ : VirtualThreadSupport.allowVirtual(useVirtualThreads, tfThreadFactory);
+ }
+
+ /**
+ * Check configuration if the use of the virtual threads is expected or return the default value if not.
+ * @param config the {@link Configuration}
+ * @param useByDefault the default expectation
+ * @return the expected
+ */
+ private static boolean useVirtualThreads(Configuration config, boolean useByDefault) {
+ boolean bUseVirtualThreads = useByDefault;
+ if (config != null) {
+ Object useVirtualThread = config.getProperty(CommonProperties.USE_VIRTUAL_THREADS);
+ if (useVirtualThread != null && Boolean.class.isInstance(useVirtualThread)) {
+ bUseVirtualThreads = (boolean) useVirtualThread;
+ }
+ if (useVirtualThread != null && String.class.isInstance(useVirtualThread)) {
+ bUseVirtualThreads = Boolean.parseBoolean(useVirtualThread.toString());
+ }
+ }
+ return bUseVirtualThreads;
+ }
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.java
similarity index 72%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.java
index 0fdbe9d..b276f3c 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/inject/package-info.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
@@ -15,6 +15,7 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * 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.test.jetty11.http2;
+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/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.java
similarity index 72%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.java
index 0fdbe9d..5ad36dd 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/inject/spi/package-info.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
@@ -15,6 +15,7 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * 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.test.jetty11.http2;
+package org.glassfish.jersey.innate.inject.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
new file mode 100644
index 0000000..abcee6b
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Generic wrapper template for InputStream.
+ */
+public abstract class InputStreamWrapper extends InputStream {
+
+ /**
+ * Return the wrapped stream
+ * @return
+ */
+ protected abstract InputStream getWrapped();
+
+ /**
+ * Get wrapped stream that can throw {@link IOException}
+ * @return the wrapped InputStream.
+ * @throws IOException
+ */
+ protected InputStream getWrappedIOE() throws IOException {
+ return getWrapped();
+ }
+
+ @Override
+ public int read() throws IOException {
+ return getWrappedIOE().read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return getWrappedIOE().read(b);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return getWrappedIOE().read(b, off, len);
+ }
+
+ @Override
+ public byte[] readAllBytes() throws IOException {
+ return getWrappedIOE().readAllBytes();
+ }
+
+ @Override
+ public int readNBytes(byte[] b, int off, int len) throws IOException {
+ return getWrappedIOE().readNBytes(b, off, len);
+ }
+
+ @Override
+ public long transferTo(OutputStream out) throws IOException {
+ return getWrappedIOE().transferTo(out);
+ }
+
+
+ @Override
+ public long skip(long n) throws IOException {
+ return getWrappedIOE().skip(n);
+ }
+
+ @Override
+ public int available() throws IOException {
+ return getWrappedIOE().available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ getWrappedIOE().close();
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ getWrapped().mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ getWrappedIOE().reset();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return getWrapped().markSupported();
+ }
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java
similarity index 73%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java
index 0fdbe9d..e569f79 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.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
@@ -15,6 +15,7 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Jersey innate io related packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.innate.io;
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/innate/spi/MessageBodyWorkersSettable.java b/core-common/src/main/java/org/glassfish/jersey/innate/spi/MessageBodyWorkersSettable.java
new file mode 100644
index 0000000..09c751e
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/spi/MessageBodyWorkersSettable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate.spi;
+
+import org.glassfish.jersey.message.MessageBodyWorkers;
+
+/**
+ * Entity type that expects the {@link MessageBodyWorkers} to be set for converting the entity to another types.
+ */
+public interface MessageBodyWorkersSettable {
+
+ /**
+ * Set message body workers used to transform an entity stream into particular Java type.
+ *
+ * @param messageBodyWorkers message body workers.
+ */
+ public void setMessageBodyWorkers(final MessageBodyWorkers messageBodyWorkers);
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/virtual/LoomishExecutors.java b/core-common/src/main/java/org/glassfish/jersey/innate/virtual/LoomishExecutors.java
new file mode 100644
index 0000000..9065746
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/virtual/LoomishExecutors.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.virtual;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * {@link Executors} facade to support virtual threads.
+ */
+public interface LoomishExecutors {
+ /**
+ * Creates a thread pool that creates new threads as needed and uses virtual threads if available.
+ * @return the newly created thread pool
+ */
+ ExecutorService newCachedThreadPool();
+
+ /**
+ * Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue
+ * and uses virtual threads if available
+ * @param nThreads – the number of threads in the pool
+ * @return the newly created thread pool
+ */
+ ExecutorService newFixedThreadPool(int nThreads);
+
+ /**
+ * Returns thread factory used to create new threads
+ * @return thread factory used to create new threads
+ * @see Executors#defaultThreadFactory()
+ */
+ ThreadFactory getThreadFactory();
+
+ /**
+ * Return true if the virtual thread use is requested.
+ * @return whether the virtual thread use is requested.
+ */
+ boolean isVirtual();
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/virtual/package-info.java
similarity index 62%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/innate/virtual/package-info.java
index 0fdbe9d..c56f91b 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/virtual/package-info.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
@@ -15,6 +15,9 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Jersey innate packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
+ * This virtual package should contain only classes that do not have dependencies on Jersey, or the REST API to be buildable with
+ * ant for multi-release.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.innate.virtual;
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java b/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
index cb7545f..77ab1e1 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/OsgiRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -37,7 +37,9 @@
import java.util.ResourceBundle;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
@@ -79,6 +81,7 @@
private final Map<Long, Map<String, Callable<List<Class<?>>>>> factories =
new HashMap<Long, Map<String, Callable<List<Class<?>>>>>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ private static final Lock INSTANCE_LOCK = new ReentrantLock();
private static OsgiRegistry instance;
@@ -90,16 +93,21 @@
*
* @return an {@code OsgiRegistry} instance.
*/
- public static synchronized OsgiRegistry getInstance() {
- if (instance == null) {
- final ClassLoader classLoader = AccessController
- .doPrivileged(ReflectionHelper.getClassLoaderPA(ReflectionHelper.class));
- if (classLoader instanceof BundleReference) {
- final BundleContext context = FrameworkUtil.getBundle(OsgiRegistry.class).getBundleContext();
- if (context != null) { // context could be still null if the current bundle has not been started
- instance = new OsgiRegistry(context);
+ public static OsgiRegistry getInstance() {
+ INSTANCE_LOCK.lock();
+ try {
+ if (instance == null) {
+ final ClassLoader classLoader = AccessController
+ .doPrivileged(ReflectionHelper.getClassLoaderPA(ReflectionHelper.class));
+ if (classLoader instanceof BundleReference) {
+ final BundleContext context = FrameworkUtil.getBundle(OsgiRegistry.class).getBundleContext();
+ if (context != null) { // context could be still null if the current bundle has not been started
+ instance = new OsgiRegistry(context);
+ }
}
}
+ } finally {
+ INSTANCE_LOCK.unlock();
}
return instance;
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java b/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
index 46184d8..03d15d3 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/ServiceFinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -33,6 +33,8 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -797,17 +799,20 @@
public abstract static class ServiceIteratorProvider {
private static volatile ServiceIteratorProvider sip;
- private static final Object sipLock = new Object();
+ private static final Lock sipLock = new ReentrantLock();
private static ServiceIteratorProvider getInstance() {
// TODO: check the following is a good practice: Double-check idiom for lazy initialization of fields.
ServiceIteratorProvider result = sip;
if (result == null) { // First check (no locking)
- synchronized (sipLock) {
+ sipLock.lock();
+ try {
result = sip;
if (result == null) { // Second check (with locking)
sip = result = new DefaultServiceIteratorProvider();
}
+ } finally {
+ sipLock.unlock();
}
}
return result;
@@ -819,8 +824,11 @@
final ReflectPermission rp = new ReflectPermission("suppressAccessChecks");
security.checkPermission(rp);
}
- synchronized (sipLock) {
+ sipLock.lock();
+ try {
ServiceIteratorProvider.sip = sip;
+ } finally {
+ sipLock.unlock();
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
index 4d9606b..a42a860 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/JerseySystemPropertiesConfigurationModel.java
@@ -1,5 +1,5 @@
/*
- * 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
@@ -29,9 +29,11 @@
"org.glassfish.jersey.servlet.ServletProperties",
"org.glassfish.jersey.message.MessageProperties",
"org.glassfish.jersey.apache.connector.ApacheClientProperties",
+ "org.glassfish.jersey.apache5.connector.Apache5ClientProperties",
"org.glassfish.jersey.helidon.connector.HelidonClientProperties",
"org.glassfish.jersey.jdk.connector.JdkConnectorProperties",
"org.glassfish.jersey.jetty.connector.JettyClientProperties",
+ "org.glassfish.jersey.jnh.connector.JavaNetHttpClientProperties",
"org.glassfish.jersey.netty.connector.NettyClientProperties",
"org.glassfish.jersey.media.multipart.MultiPartProperties",
"org.glassfish.jersey.server.oauth1.OAuth1ServerProperties");
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
index 5798695..aafb278 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
@@ -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.
* Copyright (c) 2018 Payara Foundation and/or its affiliates.
*
* This program and the accompanying materials are made available under the
@@ -125,7 +125,7 @@
@Singleton
public static class StringConstructor extends ParamConverterCompliance implements ParamConverterProvider {
- private StringConstructor(boolean canReturnNull) {
+ protected StringConstructor(boolean canReturnNull) {
super(canReturnNull);
}
@@ -154,7 +154,7 @@
@Singleton
public static class TypeValueOf extends ParamConverterCompliance implements ParamConverterProvider {
- private TypeValueOf(boolean canReturnNull) {
+ protected TypeValueOf(boolean canReturnNull) {
super(canReturnNull);
}
@@ -182,7 +182,7 @@
@Singleton
public static class TypeFromString extends ParamConverterCompliance implements ParamConverterProvider {
- private TypeFromString(boolean canReturnNull) {
+ protected TypeFromString(boolean canReturnNull) {
super(canReturnNull);
}
@@ -210,7 +210,7 @@
@Singleton
public static class TypeFromStringEnum extends TypeFromString {
- private TypeFromStringEnum(boolean canReturnNull) {
+ protected TypeFromStringEnum(boolean canReturnNull) {
super(canReturnNull);
}
@@ -225,7 +225,7 @@
@Singleton
public static class CharacterProvider extends ParamConverterCompliance implements ParamConverterProvider {
- private CharacterProvider(boolean canReturnNull) {
+ protected CharacterProvider(boolean canReturnNull) {
super(canReturnNull);
}
@@ -270,7 +270,7 @@
@Singleton
public static class DateProvider extends ParamConverterCompliance implements ParamConverterProvider {
- private DateProvider(boolean canReturnNull) {
+ protected DateProvider(boolean canReturnNull) {
super(canReturnNull);
}
@@ -346,7 +346,7 @@
// Delegates to this provider when the type of Optional is extracted.
private final InjectionManager manager;
- public OptionalCustomProvider(InjectionManager manager, boolean canReturnNull) {
+ protected OptionalCustomProvider(InjectionManager manager, boolean canReturnNull) {
super(canReturnNull);
this.manager = manager;
}
@@ -402,6 +402,8 @@
@Singleton
public static class OptionalProvider implements ParamConverterProvider {
+ protected OptionalProvider() {}
+
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
final Optionals optionals = Optionals.getOptional(rawType);
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/internal/util/PropertiesHelper.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java
index 5500e54..97dee37 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.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
@@ -390,6 +390,27 @@
}
/**
+ * Converts the property value to {@code boolean} and checks it is {@code true} or empty.
+ * Returns {@code true} if the value is {@code true} or empty but not {@code null}.
+ *
+ * <p>
+ * The rationale behind this is that system property {@code -Dprop=true} is the same as {@code -Dprop}.
+ * The property {@code -Dprop=false} behaves as if the {@code -Dprop} is not set at all.
+ * </p>
+ *
+ * @param value property value.
+ * @return {@code boolean} property value or {@code true} if the property value is not set or {@code false} if the property
+ * is otherwise not convertible.
+ */
+ public static boolean isPropertyOrNotSet(final Object value) {
+ if (value instanceof Boolean) {
+ return Boolean.class.cast(value);
+ } else {
+ return value != null && ("".equals(value.toString()) || Boolean.parseBoolean(value.toString()));
+ }
+ }
+
+ /**
* Faster replacement of {@code RuntimeType#name().toLowerCase(Locale.ROOT)}
* @param runtimeType The runtime type to lower case
* @return the lower-cased variant of the {@link RuntimeType}.
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
index 4761644..5c3a747 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Values.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,6 +16,9 @@
package org.glassfish.jersey.internal.util.collection;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
/**
* A collection of {@link Value Value provider} factory & utility methods.
*
@@ -297,25 +300,28 @@
private static class LazyValueImpl<T> implements LazyValue<T> {
- private final Object lock;
+ private final Lock lock;
private final Value<T> delegate;
private volatile Value<T> value;
public LazyValueImpl(final Value<T> delegate) {
this.delegate = delegate;
- this.lock = new Object();
+ this.lock = new ReentrantLock();
}
@Override
public T get() {
Value<T> result = value;
if (result == null) {
- synchronized (lock) {
+ lock.lock();
+ try {
result = value;
if (result == null) {
value = result = Values.of(delegate.get());
}
+ } finally {
+ lock.unlock();
}
}
return result.get();
@@ -380,21 +386,22 @@
private static class LazyUnsafeValueImpl<T, E extends Throwable> implements LazyUnsafeValue<T, E> {
- private final Object lock;
+ private final Lock lock;
private final UnsafeValue<T, E> delegate;
private volatile UnsafeValue<T, E> value;
public LazyUnsafeValueImpl(final UnsafeValue<T, E> delegate) {
this.delegate = delegate;
- this.lock = new Object();
+ this.lock = new ReentrantLock();
}
@Override
public T get() throws E {
UnsafeValue<T, E> result = value;
if (result == null) {
- synchronized (lock) {
+ lock.lock();
+ try {
result = value;
//noinspection ConstantConditions
if (result == null) {
@@ -406,6 +413,8 @@
}
value = result;
}
+ } finally {
+ lock.unlock();
}
}
return result.get();
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
index 32e2640..4765056 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2019 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
@@ -24,13 +24,12 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import static org.glassfish.jersey.internal.guava.Preconditions.checkNotNull;
-
/**
* Collections utils, which provide transforming views for {@link List} and {@link Map}.
*
@@ -197,8 +196,8 @@
* @return union view of given sets.
*/
public static <E> Set<E> setUnionView(final Set<? extends E> set1, final Set<? extends E> set2) {
- checkNotNull(set1, "set1");
- checkNotNull(set2, "set2");
+ Objects.requireNonNull(set1, "set1");
+ Objects.requireNonNull(set2, "set2");
return new AbstractSet<E>() {
@Override
@@ -220,18 +219,19 @@
}
/**
- * Create a view of a difference of provided sets.
+ * Create a view of a difference of provided sets, i.e. the diff filters out from the first set the items included
+ * in the second set.
* <p>
* View is updated whenever any of the provided set changes.
*
* @param set1 first set.
* @param set2 second set.
* @param <E> set item type.
- * @return union view of given sets.
+ * @return view that is a difference of given sets.
*/
public static <E> Set<E> setDiffView(final Set<? extends E> set1, final Set<? extends E> set2) {
- checkNotNull(set1, "set1");
- checkNotNull(set2, "set2");
+ Objects.requireNonNull(set1, "set1");
+ Objects.requireNonNull(set2, "set2");
return new AbstractSet<E>() {
@Override
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/io/package-info.java
similarity index 78%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to core-common/src/main/java/org/glassfish/jersey/io/package-info.java
index 0fdbe9d..f913ae6 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/io/package-info.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
@@ -15,6 +15,6 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Common Jersey core io classes.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.io;
diff --git a/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java b/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java
new file mode 100644
index 0000000..12aa714
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.io.spi;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A marker interface that the stream provided to Jersey can implement,
+ * noting that the stream does not need to call {@link #flush()} prior to {@link #close()}.
+ * That way, {@link #flush()} method is not called twice.
+ *
+ * <p>
+ * Usable by {@link javax.ws.rs.client.ClientRequestContext#setEntityStream(OutputStream)}.
+ * Usable by {@link javax.ws.rs.container.ContainerResponseContext#setEntityStream(OutputStream)}.
+ * </p>
+ *
+ * <p>
+ * This marker interface can be useful for the customer OutputStream to know the {@code flush} did not come from
+ * Jersey before close. By default, when the entity stream is to be closed by Jersey, {@code flush} is called first.
+ * </p>
+ */
+public interface FlushedCloseable extends Flushable, Closeable {
+ /**
+ * Flushes this stream by writing any buffered output to the underlying stream.
+ * Then closes this stream and releases any system resources associated
+ * with it. If the stream is already closed then invoking this
+ * method has no effect.
+ *
+ * <p> As noted in {@link AutoCloseable#close()}, cases where the
+ * close may fail require careful attention. It is strongly advised
+ * to relinquish the underlying resources and to internally
+ * <em>mark</em> the {@code Closeable} as closed, prior to throwing
+ * the {@code IOException}.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException;
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.java
similarity index 78%
rename from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
rename to core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.java
index 0fdbe9d..7a70945 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.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
@@ -15,6 +15,6 @@
*/
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Common Jersey core io SPI classes.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.io.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
index f7e2673..466eaaa 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/AbstractMessageReaderWriterProvider.java
@@ -46,7 +46,7 @@
*
* @deprecated use {@code StandardCharsets.UTF_8} instead.
*/
- @Deprecated
+ @Deprecated(forRemoval = true)
public static final Charset UTF8 = StandardCharsets.UTF_8;
/**
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
index 39f74fb..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, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -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,11 +59,13 @@
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.
*/
private static final OutboundMessageContext.StreamProvider NULL_STREAM_PROVIDER =
- contentLength -> new NullOutputStream();
+ contentLength -> OutputStream.nullOutputStream();
/**
* Default size of the buffer which will be used if no user defined size is specified.
*/
@@ -170,7 +173,7 @@
Preconditions.checkState(streamProvider != null, STREAM_PROVIDER_NULL);
adaptedOutput = streamProvider.getOutputStream(currentSize);
if (adaptedOutput == null) {
- adaptedOutput = new NullOutputStream();
+ adaptedOutput = OutputStream.nullOutputStream();
}
directWrite = true;
@@ -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/java/org/glassfish/jersey/message/internal/CookiesParser.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
index bcd7e5f..14a008d 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2021 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
@@ -168,7 +168,7 @@
cookie.sameSite = NewCookie.SameSite.valueOf(value.toUpperCase());
} else if (param.startsWith("expires")) {
try {
- cookie.expiry = HttpDateFormat.readDate(value + ", " + bites[++i]);
+ cookie.expiry = HttpDateFormat.readDate(value + ", " + bites[++i].trim());
} catch (ParseException e) {
LOGGER.log(Level.FINE, LocalizationMessages.ERROR_NEWCOOKIE_EXPIRES(value), e);
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
index 09e7553..8417fb5 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/DateProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -43,7 +43,7 @@
@Override
public String toString(final Date header) {
throwIllegalArgumentExceptionIfNull(header, LocalizationMessages.DATE_IS_NULL());
- return HttpDateFormat.getPreferredDateFormat().format(header);
+ return HttpDateFormat.getPreferredDateFormatter().format(header);
}
@Override
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java
index f94d5fd..2610e17 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,7 @@
import jakarta.ws.rs.ProcessingException;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.LocalizationMessages;
/**
@@ -33,7 +34,7 @@
*
* @author Marek Potociar
*/
-public class EntityInputStream extends InputStream {
+public class EntityInputStream extends InputStreamWrapper {
private InputStream input;
private boolean closed = false;
@@ -64,40 +65,6 @@
this.input = input;
}
- @Override
- public int read() throws IOException {
- return input.read();
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return input.read(b);
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- return input.read(b, off, len);
- }
-
- @Override
- public long skip(long n) throws IOException {
- return input.skip(n);
- }
-
- @Override
- public int available() throws IOException {
- return input.available();
- }
-
- @Override
- public void mark(int readLimit) {
- input.mark(readLimit);
- }
-
- @Override
- public boolean markSupported() {
- return input.markSupported();
- }
/**
* {@inheritDoc}
@@ -232,4 +199,9 @@
public final void setWrappedStream(InputStream wrapped) {
input = wrapped;
}
+
+ @Override
+ protected InputStream getWrapped() {
+ return input;
+ }
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
index 75479e6..9cf2abf 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpDateFormat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,12 +18,18 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Queue;
import java.util.TimeZone;
+import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Helper class for HTTP specified date formats.
@@ -33,6 +39,46 @@
*/
public final class HttpDateFormat {
+ private static final boolean USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER = true;
+
+ /**
+ * <p>
+ * A minimum formatter for converting java {@link Date} and {@link LocalDateTime} to {@code String} and vice-versa.
+ * </p>
+ * <p>
+ * Works as a facade for implementation backed by {@link SimpleDateFormat} and {@link DateTimeFormatter}.
+ * </p>
+ */
+ public static interface HttpDateFormatter {
+ /**
+ *
+ * @param date
+ * @return
+ */
+ Date toDate(String date);
+
+ /**
+ *
+ * @param date
+ * @return
+ */
+ LocalDateTime toDateTime(String date);
+ /**
+ * Formats a {@link Date} into a date-time string.
+ *
+ * @param date the time value to be formatted into a date-time string.
+ * @return the formatted date-time string.
+ */
+ String format(Date date);
+ /**
+ * Formats a {@link LocalDateTime} into a date-time string.
+ *
+ * @param dateTime the time value to be formatted into a date-time string.
+ * @return the formatted date-time string.
+ */
+ String format(LocalDateTime dateTime);
+ }
+
private HttpDateFormat() {
}
/**
@@ -50,39 +96,40 @@
private static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");
- private static final ThreadLocal<List<SimpleDateFormat>> dateFormats = new ThreadLocal<List<SimpleDateFormat>>() {
+ private static final List<HttpDateFormatter> dateFormats = createDateFormats();
+ private static final Queue<List<HttpDateFormatter>> simpleDateFormats = new ConcurrentLinkedQueue<>();
- @Override
- protected synchronized List<SimpleDateFormat> initialValue() {
- return createDateFormats();
- }
- };
-
- private static List<SimpleDateFormat> createDateFormats() {
- final SimpleDateFormat[] formats = new SimpleDateFormat[]{
- new SimpleDateFormat(RFC1123_DATE_FORMAT_PATTERN, Locale.US),
- new SimpleDateFormat(RFC1036_DATE_FORMAT_PATTERN, Locale.US),
- new SimpleDateFormat(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US)
+ private static List<HttpDateFormatter> createDateFormats() {
+ final HttpDateFormatter[] formats = new HttpDateFormatter[]{
+ new HttpDateFormatterFromDateTimeFormatter(
+ DateTimeFormatter.ofPattern(RFC1123_DATE_FORMAT_PATTERN, Locale.US).withZone(GMT_TIME_ZONE.toZoneId())),
+ new HttpDateFormatterFromDateTimeFormatter(
+ DateTimeFormatter.ofPattern(RFC1123_DATE_FORMAT_PATTERN.replace("zzz", "ZZZ"), Locale.US)
+ .withZone(GMT_TIME_ZONE.toZoneId())),
+ new HttpDateFormatterFromDateTimeFormatter(
+ DateTimeFormatter.ofPattern(RFC1036_DATE_FORMAT_PATTERN, Locale.US).withZone(GMT_TIME_ZONE.toZoneId())),
+ new HttpDateFormatterFromDateTimeFormatter(
+ DateTimeFormatter.ofPattern(RFC1036_DATE_FORMAT_PATTERN.replace("zzz", "ZZZ"), Locale.US)
+ .withZone(GMT_TIME_ZONE.toZoneId())),
+ new HttpDateFormatterFromDateTimeFormatter(
+ DateTimeFormatter.ofPattern(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US)
+ .withZone(GMT_TIME_ZONE.toZoneId()))
};
- formats[0].setTimeZone(GMT_TIME_ZONE);
- formats[1].setTimeZone(GMT_TIME_ZONE);
- formats[2].setTimeZone(GMT_TIME_ZONE);
return Collections.unmodifiableList(Arrays.asList(formats));
}
- /**
- * Return an unmodifiable list of HTTP specified date formats to use for
- * parsing or formatting {@link Date}.
- * <p>
- * The list of date formats are scoped to the current thread and may be
- * used without requiring to synchronize access to the instances when
- * parsing or formatting.
- *
- * @return the list of data formats.
- */
- private static List<SimpleDateFormat> getDateFormats() {
- return dateFormats.get();
+ private static List<HttpDateFormatter> createSimpleDateFormats() {
+ final HttpDateFormatterFromSimpleDateTimeFormat[] formats = new HttpDateFormatterFromSimpleDateTimeFormat[]{
+ new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(RFC1123_DATE_FORMAT_PATTERN, Locale.US)),
+ new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(RFC1036_DATE_FORMAT_PATTERN, Locale.US)),
+ new HttpDateFormatterFromSimpleDateTimeFormat(new SimpleDateFormat(ANSI_C_ASCTIME_DATE_FORMAT_PATTERN, Locale.US))
+ };
+ formats[0].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+ formats[1].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+ formats[2].simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+
+ return Collections.unmodifiableList(Arrays.asList(formats));
}
/**
@@ -94,9 +141,44 @@
*
* @return the preferred of data format.
*/
+ public static HttpDateFormatter getPreferredDateFormatter() {
+ if (USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER) {
+ List<HttpDateFormatter> list = simpleDateFormats.poll();
+ if (list == null) {
+ list = createSimpleDateFormats();
+ }
+ // returns clone because calling SDF.parse(...) can change time zone
+ final SimpleDateFormat sdf = (SimpleDateFormat)
+ ((HttpDateFormatterFromSimpleDateTimeFormat) list.get(0)).simpleDateFormat.clone();
+ simpleDateFormats.add(list);
+ return new HttpDateFormatterFromSimpleDateTimeFormat(sdf);
+ } else {
+ return dateFormats.get(0);
+ }
+ }
+
+ /**
+ * Get the preferred HTTP specified date format (RFC 1123).
+ * <p>
+ * The date format is scoped to the current thread and may be
+ * used without requiring to synchronize access to the instance when
+ * parsing or formatting.
+ *
+ * @return the preferred of data format.
+ * @deprecated Use getPreferredDateFormatter instead
+ */
+ // Unused in Jersey
+ @Deprecated(forRemoval = true)
public static SimpleDateFormat getPreferredDateFormat() {
+ List<HttpDateFormatter> list = simpleDateFormats.poll();
+ if (list == null) {
+ list = createSimpleDateFormats();
+ }
// returns clone because calling SDF.parse(...) can change time zone
- return (SimpleDateFormat) dateFormats.get().get(0).clone();
+ final SimpleDateFormat sdf = (SimpleDateFormat)
+ ((HttpDateFormatterFromSimpleDateTimeFormat) list.get(0)).simpleDateFormat.clone();
+ simpleDateFormats.add(list);
+ return sdf;
}
/**
@@ -108,18 +190,106 @@
* @throws java.text.ParseException in case the date string cannot be parsed.
*/
public static Date readDate(final String date) throws ParseException {
- ParseException pe = null;
- for (final SimpleDateFormat f : HttpDateFormat.getDateFormats()) {
+ return USE_SIMPLE_DATE_FORMAT_OVER_DATE_TIME_FORMATTER
+ ? readDateSDF(date)
+ : readDateDTF(date);
+ }
+
+ private static Date readDateDTF(final String date) throws ParseException {
+ final List<HttpDateFormatter> list = dateFormats;
+ return readDate(date, list);
+ }
+
+ private static Date readDateSDF(final String date) throws ParseException {
+ List<HttpDateFormatter> list = simpleDateFormats.poll();
+ if (list == null) {
+ list = createSimpleDateFormats();
+ }
+ final Date ret = readDate(date, list);
+ simpleDateFormats.add(list);
+ return ret;
+ }
+
+ private static Date readDate(final String date, List<HttpDateFormatter> formatters) throws ParseException {
+ Exception pe = null;
+ for (final HttpDateFormatter f : formatters) {
try {
- Date result = f.parse(date);
- // parse can change time zone -> set it back to GMT
- f.setTimeZone(GMT_TIME_ZONE);
- return result;
- } catch (final ParseException e) {
+ return f.toDate(date);
+ } catch (final Exception e) {
pe = (pe == null) ? e : pe;
}
}
- throw pe;
+ throw ParseException.class.isInstance(pe) ? (ParseException) pe
+ : new ParseException(pe.getMessage(),
+ DateTimeParseException.class.isInstance(pe) ? ((DateTimeParseException) pe).getErrorIndex() : 0);
+ }
+
+ /**
+ * Warning! DateTimeFormatter is incompatible with SimpleDateFormat for two digits year, since SimpleDateFormat uses
+ * 80 years before now and 20 years after, whereas DateTimeFormatter uses years starting with 2000.
+ */
+ private static class HttpDateFormatterFromDateTimeFormatter implements HttpDateFormatter {
+ private final DateTimeFormatter dateTimeFormatter;
+
+ private HttpDateFormatterFromDateTimeFormatter(DateTimeFormatter dateTimeFormatter) {
+ this.dateTimeFormatter = dateTimeFormatter;
+ }
+
+ @Override
+ public Date toDate(String date) {
+ return new Date(Instant.from(dateTimeFormatter.parse(date)).toEpochMilli());
+ }
+
+ @Override
+ public LocalDateTime toDateTime(String date) {
+ return Instant.from(dateTimeFormatter.parse(date)).atZone(GMT_TIME_ZONE.toZoneId()).toLocalDateTime();
+ }
+
+ @Override
+ public String format(Date date) {
+ return dateTimeFormatter.format(date.toInstant());
+ }
+
+ @Override
+ public String format(LocalDateTime dateTime) {
+ return dateTimeFormatter.format(dateTime);
+ }
+ }
+
+ private static class HttpDateFormatterFromSimpleDateTimeFormat implements HttpDateFormatter {
+ private final SimpleDateFormat simpleDateFormat;
+
+ private HttpDateFormatterFromSimpleDateTimeFormat(SimpleDateFormat simpleDateFormat) {
+ this.simpleDateFormat = simpleDateFormat;
+ }
+
+ @Override
+ public Date toDate(String date) {
+ final Date result;
+ try {
+ result = simpleDateFormat.parse(date);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ // parse can change time zone -> set it back to GMT
+ simpleDateFormat.setTimeZone(GMT_TIME_ZONE);
+ return result;
+ }
+
+ @Override
+ public LocalDateTime toDateTime(String date) {
+ return Instant.from(toDate(date).toInstant()).atZone(GMT_TIME_ZONE.toZoneId()).toLocalDateTime();
+ }
+
+ @Override
+ public String format(Date date) {
+ return simpleDateFormat.format(date);
+ }
+
+ @Override
+ public String format(LocalDateTime dateTime) {
+ return simpleDateFormat.format(Date.from(dateTime.atZone(GMT_TIME_ZONE.toZoneId()).toInstant()));
+ }
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
index fe5a249..62df83f 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/HttpHeaderReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,6 +28,8 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.MediaType;
@@ -622,6 +624,7 @@
private abstract static class ListReader<T> {
private final LRU<String, List<T>> LIST_CACHE = LRU.create();
+ private final Lock lock = new ReentrantLock();
protected final ListElementCreator<T> creator;
protected ListReader(ListElementCreator<T> creator) {
@@ -639,7 +642,8 @@
List<T> list = LIST_CACHE.getIfPresent(header);
if (list == null) {
- synchronized (LIST_CACHE) {
+ lock.lock();
+ try {
list = LIST_CACHE.getIfPresent(header);
if (list == null) {
HttpHeaderReader reader = new HttpHeaderReaderImpl(header);
@@ -655,6 +659,8 @@
}
LIST_CACHE.put(header, list);
}
+ } finally {
+ lock.unlock();
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
index 9eb4a40..8f31f74 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.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
@@ -23,17 +23,13 @@
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
-import java.net.URI;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@@ -41,21 +37,16 @@
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Cookie;
-import jakarta.ws.rs.core.EntityTag;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Link;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.ext.ReaderInterceptor;
-import jakarta.ws.rs.ext.RuntimeDelegate;
import javax.xml.transform.Source;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.PropertiesDelegate;
-import org.glassfish.jersey.internal.RuntimeDelegateDecorator;
import org.glassfish.jersey.internal.util.collection.GuardianStringKeyMultivaluedMap;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.internal.util.collection.Value;
@@ -67,7 +58,7 @@
*
* @author Marek Potociar
*/
-public abstract class InboundMessageContext {
+public abstract class InboundMessageContext extends MessageHeaderMethods {
private static final InputStream EMPTY = new InputStream() {
@@ -100,7 +91,6 @@
private final boolean translateNce;
private MessageBodyWorkers workers;
private final Configuration configuration;
- private final RuntimeDelegate runtimeDelegateDecorator;
private LazyValue<MediaType> contentTypeCache;
private LazyValue<List<AcceptableMediaType>> acceptTypeCache;
@@ -166,11 +156,11 @@
* as required by JAX-RS specification on the server side.
*/
public InboundMessageContext(Configuration configuration, boolean translateNce) {
+ super(configuration);
this.headers = new GuardianStringKeyMultivaluedMap<>(HeaderUtils.createInbound());
this.entityContent = new EntityContent();
this.translateNce = translateNce;
this.configuration = configuration;
- runtimeDelegateDecorator = RuntimeDelegateDecorator.configured(configuration);
contentTypeCache = contentTypeCache();
acceptTypeCache = acceptTypeCache();
@@ -319,42 +309,9 @@
return buffer.toString();
}
- /**
- * Get a single typed header value.
- *
- * @param name header name.
- * @param converter from string conversion function. Is expected to throw {@link ProcessingException}
- * if conversion fails.
- * @param convertNull if {@code true} this method calls the provided converter even for {@code null}. Otherwise this
- * method returns the {@code null} without calling the converter.
- * @return value of the header, or (possibly converted) {@code null} if not present.
- */
- private <T> T singleHeader(String name, Function<String, T> converter, boolean convertNull) {
- final List<String> values = this.headers.get(name);
-
- if (values == null || values.isEmpty()) {
- return convertNull ? converter.apply(null) : null;
- }
- if (values.size() > 1) {
- throw new HeaderValueException(LocalizationMessages.TOO_MANY_HEADER_VALUES(name, values.toString()),
- HeaderValueException.Context.INBOUND);
- }
-
- Object value = values.get(0);
- if (value == null) {
- return convertNull ? converter.apply(null) : null;
- }
-
- try {
- return converter.apply(HeaderUtils.asString(value, runtimeDelegateDecorator));
- } catch (ProcessingException ex) {
- throw exception(name, value, ex);
- }
- }
-
- private static HeaderValueException exception(final String headerName, Object headerValue, Exception e) {
- return new HeaderValueException(LocalizationMessages.UNABLE_TO_PARSE_HEADER_VALUE(headerName, headerValue), e,
- HeaderValueException.Context.INBOUND);
+ @Override
+ public HeaderValueException.Context getHeaderValueExceptionContext() {
+ return HeaderValueException.Context.INBOUND;
}
/**
@@ -367,24 +324,6 @@
}
/**
- * Get message date.
- *
- * @return the message date, otherwise {@code null} if not present.
- */
- public Date getDate() {
- return singleHeader(HttpHeaders.DATE, new Function<String, Date>() {
- @Override
- public Date apply(String input) {
- try {
- return HttpHeaderReader.readDate(input);
- } catch (ParseException ex) {
- throw new ProcessingException(ex);
- }
- }
- }, false);
- }
-
- /**
* Get If-Match header.
*
* @return the If-Match header value, otherwise {@code null} if not present.
@@ -419,42 +358,6 @@
}
/**
- * Get the language of the entity.
- *
- * @return the language of the entity or {@code null} if not specified.
- */
- public Locale getLanguage() {
- return singleHeader(HttpHeaders.CONTENT_LANGUAGE, new Function<String, Locale>() {
- @Override
- public Locale apply(String input) {
- try {
- return new LanguageTag(input).getAsLocale();
- } catch (ParseException e) {
- throw new ProcessingException(e);
- }
- }
- }, false);
- }
-
- /**
- * Get Content-Length value.
- *
- * @return Content-Length as integer if present and valid number. In other cases returns -1.
- */
- public int getLength() {
- return singleHeader(HttpHeaders.CONTENT_LENGTH, new Function<String, Integer>() {
- @Override
- public Integer apply(String input) {
- try {
- return (input != null && !input.isEmpty()) ? Integer.parseInt(input) : -1;
- } catch (NumberFormatException ex) {
- throw new ProcessingException(ex);
- }
- }
- }, true);
- }
-
- /**
* Get the media type of the entity.
*
* @return the media type or {@code null} if not specified (e.g. there's no
@@ -569,120 +472,6 @@
}
/**
- * Get any cookies that accompanied the request.
- *
- * @return a read-only map of cookie name (String) to {@link jakarta.ws.rs.core.Cookie}.
- */
- public Map<String, Cookie> getRequestCookies() {
- List<String> cookies = this.headers.get(HttpHeaders.COOKIE);
- if (cookies == null || cookies.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Map<String, Cookie> result = new HashMap<String, Cookie>();
- for (String cookie : cookies) {
- if (cookie != null) {
- result.putAll(HttpHeaderReader.readCookies(cookie));
- }
- }
- return result;
- }
-
- /**
- * Get the allowed HTTP methods from the Allow HTTP header.
- *
- * @return the allowed HTTP methods, all methods will returned as upper case
- * strings.
- */
- public Set<String> getAllowedMethods() {
- final String allowed = getHeaderString(HttpHeaders.ALLOW);
- if (allowed == null || allowed.isEmpty()) {
- return Collections.emptySet();
- }
- try {
- return new HashSet<String>(HttpHeaderReader.readStringList(allowed.toUpperCase(Locale.ROOT)));
- } catch (java.text.ParseException e) {
- throw exception(HttpHeaders.ALLOW, allowed, e);
- }
- }
-
- /**
- * Get any new cookies set on the response message.
- *
- * @return a read-only map of cookie name (String) to a {@link jakarta.ws.rs.core.NewCookie new cookie}.
- */
- public Map<String, NewCookie> getResponseCookies() {
- List<String> cookies = this.headers.get(HttpHeaders.SET_COOKIE);
- if (cookies == null || cookies.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Map<String, NewCookie> result = new HashMap<String, NewCookie>();
- for (String cookie : cookies) {
- if (cookie != null) {
- NewCookie newCookie = HttpHeaderReader.readNewCookie(cookie);
- String cookieName = newCookie.getName();
- if (result.containsKey(cookieName)) {
- result.put(cookieName, HeaderUtils.getPreferredCookie(result.get(cookieName), newCookie));
- } else {
- result.put(cookieName, newCookie);
- }
- }
- }
- return result;
- }
-
- /**
- * Get the entity tag.
- *
- * @return the entity tag, otherwise {@code null} if not present.
- */
- public EntityTag getEntityTag() {
- return singleHeader(HttpHeaders.ETAG, new Function<String, EntityTag>() {
- @Override
- public EntityTag apply(String value) {
- return EntityTag.valueOf(value);
- }
- }, false);
- }
-
- /**
- * Get the last modified date.
- *
- * @return the last modified date, otherwise {@code null} if not present.
- */
- public Date getLastModified() {
- return singleHeader(HttpHeaders.LAST_MODIFIED, new Function<String, Date>() {
- @Override
- public Date apply(String input) {
- try {
- return HttpHeaderReader.readDate(input);
- } catch (ParseException e) {
- throw new ProcessingException(e);
- }
- }
- }, false);
- }
-
- /**
- * Get the location.
- *
- * @return the location URI, otherwise {@code null} if not present.
- */
- public URI getLocation() {
- return singleHeader(HttpHeaders.LOCATION, new Function<String, URI>() {
- @Override
- public URI apply(String value) {
- try {
- return URI.create(value);
- } catch (IllegalArgumentException ex) {
- throw new ProcessingException(ex);
- }
- }
- }, false);
- }
-
- /**
* Get the links attached to the message as header.
*
* @return links, may return empty {@link java.util.Set} if no links are present. Never
@@ -726,57 +515,6 @@
}
}
- /**
- * Check if link for relation exists.
- *
- * @param relation link relation.
- * @return {@code true} if the for the relation link exists, {@code false}
- * otherwise.
- */
- public boolean hasLink(String relation) {
- for (Link link : getLinks()) {
- List<String> relations = LinkProvider.getLinkRelations(link.getRel());
-
- if (relations != null && relations.contains(relation)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the link for the relation.
- *
- * @param relation link relation.
- * @return the link for the relation, otherwise {@code null} if not present.
- */
- public Link getLink(String relation) {
- for (Link link : getLinks()) {
- List<String> relations = LinkProvider.getLinkRelations(link.getRel());
- if (relations != null && relations.contains(relation)) {
- return link;
- }
- }
- return null;
- }
-
- /**
- * Convenience method that returns a {@link jakarta.ws.rs.core.Link.Builder Link.Builder}
- * for the relation.
- *
- * @param relation link relation.
- * @return the link builder for the relation, otherwise {@code null} if not
- * present.
- */
- public Link.Builder getLinkBuilder(String relation) {
- Link link = getLink(relation);
- if (link == null) {
- return null;
- }
-
- return Link.fromLink(link);
- }
-
// Message entity
/**
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
index c07dcbf..6bf66cb 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InputStreamProvider.java
@@ -78,10 +78,8 @@
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException {
- try {
+ try (t) {
ReaderWriter.writeTo(t, entityStream);
- } finally {
- t.close();
}
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageHeaderMethods.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageHeaderMethods.java
new file mode 100644
index 0000000..cd23505
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageHeaderMethods.java
@@ -0,0 +1,461 @@
+/*
+ * 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.message.internal;
+
+import org.glassfish.jersey.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.RuntimeDelegateDecorator;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Cookie;
+import jakarta.ws.rs.core.EntityTag;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Link;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.ext.RuntimeDelegate;
+import java.net.URI;
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * Common header methods for outbound and inbound messages.
+ */
+public abstract class MessageHeaderMethods {
+ protected RuntimeDelegate runtimeDelegateDecorator;
+
+ protected MessageHeaderMethods(Configuration configuration) {
+ this.runtimeDelegateDecorator = RuntimeDelegateDecorator.configured(configuration);
+ }
+
+ protected MessageHeaderMethods(MessageHeaderMethods other) {
+ this.runtimeDelegateDecorator = other.runtimeDelegateDecorator;
+ }
+
+ /**
+ * Get a message header as a single string value.
+ *
+ * Each single non-string header value is converted to String using a {@code RuntimeDelegate.HeaderDelegate} if one
+ * is available via {@code RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value
+ * class or using its {@code toString} method if a header delegate is not available.
+ *
+ * @param name the message header.
+ * @return the message header value. If the message header is not present then {@code null} is returned. If the message
+ * header is present but has no value then the empty string is returned. If the message header is present more than once
+ * then the values of joined together and separated by a ',' character.
+ */
+ public abstract String getHeaderString(String name);
+
+ /**
+ * Get the mutable message headers multivalued map.
+ *
+ * @return mutable multivalued map of message headers.
+ */
+ public abstract MultivaluedMap<String, ?> getHeaders();
+
+ /**
+ * Return {@link HeaderValueException.Context} type of the message context.
+ * @return {@link HeaderValueException.Context} type of the message context.
+ */
+ protected abstract HeaderValueException.Context getHeaderValueExceptionContext();
+
+ /**
+ * Get the links attached to the message as header.
+ *
+ * @return links, may return empty {@link java.util.Set} if no links are present. Never
+ * returns {@code null}.
+ */
+ public abstract Set<Link> getLinks();
+
+ /**
+ * Checks whether a header with a specific name and value (or item of the token-separated value list) exists.
+ *
+ * Each single non-string header value is converted to String using a {@code RuntimeDelegate.HeaderDelegate} if one
+ * is available via {@code RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value
+ * class or using its {@code toString} method if a header delegate is not available.
+ *
+ * <p>
+ * For example: {@code containsHeaderString("cache-control", ",", "no-store"::equalsIgnoreCase)} will return {@code true} if
+ * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value
+ * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform}
+ * (missing comma), or the value {@code no - store} (whitespace within value).
+ *
+ * @param name the message header.
+ * @param valueSeparatorRegex Separates the header value into single values. {@code null} does not split.
+ * @param valuePredicate value must fulfil this predicate.
+ * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value
+ * matching the predicate, or having at least one whitespace-trimmed single value in a token-separated list of single values.
+ */
+ public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate<String> valuePredicate) {
+ final String header = getHeaderString(name);
+ if (header == null) {
+ return false;
+ }
+ final String[] split = header.split(valueSeparatorRegex);
+ for (String s : split) {
+ if (valuePredicate.test(s.trim())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether a header with a specific name and value (or item of the comma-separated value list) exists.
+ *
+ * Each single non-string header value is converted to String using a {@code RuntimeDelegate.HeaderDelegate} if one
+ * is available via {@code RuntimeDelegate#createHeaderDelegate(java.lang.Class)} for the header value
+ * class or using its {@code toString} method if a header delegate is not available.
+ *
+ * <p>
+ * For example: {@code containsHeaderString("cache-control", "no-store"::equalsIgnoreCase)} will return {@code true} if
+ * a {@code Cache-Control} header exists that has the value {@code no-store}, the value {@code No-Store} or the value
+ * {@code Max-Age, NO-STORE, no-transform}, but {@code false} when it has the value {@code no-store;no-transform}
+ * (missing comma), or the value {@code no - store} (whitespace within value).
+ *
+ * @param name the message header.
+ * @param valuePredicate value must fulfil this predicate.
+ * @return {@code true} if and only if a header with the given name exists, having either a whitespace-trimmed value
+ * matching the predicate, or having at least one whitespace-trimmed single value in a comma-separated list of single values.
+ */
+ public boolean containsHeaderString(String name, Predicate<String> valuePredicate) {
+ return containsHeaderString(name, ",", valuePredicate);
+ }
+
+ /**
+ * Get the allowed HTTP methods from the Allow HTTP header.
+ *
+ * @return the allowed HTTP methods, all methods will returned as upper case
+ * strings.
+ */
+ public Set<String> getAllowedMethods() {
+ final String allowed = getHeaderString(HttpHeaders.ALLOW);
+ if (allowed == null || allowed.isEmpty()) {
+ return Collections.emptySet();
+ }
+ try {
+ return new HashSet<String>(HttpHeaderReader.readStringList(allowed.toUpperCase(Locale.ROOT)));
+ } catch (java.text.ParseException e) {
+ throw exception(HttpHeaders.ALLOW, allowed, e);
+ }
+ }
+
+ /**
+ * Get message date.
+ *
+ * @return the message date, otherwise {@code null} if not present.
+ */
+ public Date getDate() {
+ return singleHeader(HttpHeaders.DATE, Date.class, input -> {
+ try {
+ return HttpHeaderReader.readDate(input);
+ } catch (ParseException e) {
+ throw new ProcessingException(e);
+ }
+ }, false);
+ }
+
+ /**
+ * Get the entity tag.
+ *
+ * @return the entity tag, otherwise {@code null} if not present.
+ */
+ public EntityTag getEntityTag() {
+ return singleHeader(HttpHeaders.ETAG, EntityTag.class, new Function<String, EntityTag>() {
+ @Override
+ public EntityTag apply(String value) {
+ try {
+ return value == null ? null : EntityTag.valueOf(value);
+ } catch (IllegalArgumentException ex) {
+ throw new ProcessingException(ex);
+ }
+ }
+ }, false);
+ }
+
+ /**
+ * Get the language of the entity.
+ *
+ * @return the language of the entity or {@code null} if not specified
+ */
+ public Locale getLanguage() {
+ return singleHeader(HttpHeaders.CONTENT_LANGUAGE, Locale.class, input -> {
+ try {
+ return new LanguageTag(input).getAsLocale();
+ } catch (ParseException e) {
+ throw new ProcessingException(e);
+ }
+ }, false);
+ }
+
+ /**
+ * Get the last modified date.
+ *
+ * @return the last modified date, otherwise {@code null} if not present.
+ */
+ public Date getLastModified() {
+ return singleHeader(HttpHeaders.LAST_MODIFIED, Date.class, new Function<String, Date>() {
+ @Override
+ public Date apply(String input) {
+ try {
+ return HttpHeaderReader.readDate(input);
+ } catch (ParseException e) {
+ throw new ProcessingException(e);
+ }
+ }
+ }, false);
+ }
+
+ /**
+ * Get Content-Length value.
+ * <p>
+ * <B>Note</B>: {@link #getLengthLong() getLengthLong()}
+ * should be preferred over this method, since it returns a {@code long}
+ * instead and is therefore more portable.</P>
+ *
+ * @return Content-Length as a postive integer if present and valid number, {@code -1} if negative number.
+ * @throws ProcessingException when {@link Integer#parseInt(String)} (String)} throws {@link NumberFormatException}.
+ */
+ public int getLength() {
+ return singleHeader(HttpHeaders.CONTENT_LENGTH, Integer.class, input -> {
+ try {
+ if (input != null && !input.isEmpty()) {
+ int i = Integer.parseInt(input);
+ if (i >= 0) {
+ return i;
+ }
+ }
+ return -1;
+
+ } catch (NumberFormatException ex) {
+ throw new ProcessingException(ex);
+ }
+ }, true);
+ }
+
+ /**
+ * Get Content-Length value.
+ *
+ * @return Content-Length as a positive long if present and valid number, {@code -1} if negative number.
+ * @throws ProcessingException when {@link Long#parseLong(String)} throws {@link NumberFormatException}.
+ */
+ public long getLengthLong() {
+ return singleHeader(HttpHeaders.CONTENT_LENGTH, Long.class, input -> {
+ try {
+ if (input != null && !input.isEmpty()) {
+ long l = Long.parseLong(input);
+ if (l >= 0) {
+ return l;
+ }
+ }
+ return -1L;
+ } catch (NumberFormatException ex) {
+ throw new ProcessingException(ex);
+ }
+ }, true);
+ }
+
+ /**
+ * Get the link for the relation.
+ *
+ * @param relation link relation.
+ * @return the link for the relation, otherwise {@code null} if not present.
+ */
+ public Link getLink(String relation) {
+ for (Link link : getLinks()) {
+ List<String> relations = LinkProvider.getLinkRelations(link.getRel());
+ if (relations != null && relations.contains(relation)) {
+ return link;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Convenience method that returns a {@link jakarta.ws.rs.core.Link.Builder Link.Builder}
+ * for the relation.
+ *
+ * @param relation link relation.
+ * @return the link builder for the relation, otherwise {@code null} if not
+ * present.
+ */
+ public Link.Builder getLinkBuilder(String relation) {
+ Link link = getLink(relation);
+ if (link == null) {
+ return null;
+ }
+
+ return Link.fromLink(link);
+ }
+
+ /**
+ * Get the location.
+ *
+ * @return the location URI, otherwise {@code null} if not present.
+ */
+ public URI getLocation() {
+ return singleHeader(HttpHeaders.LOCATION, URI.class, value -> {
+ try {
+ return value == null ? null : URI.create(value);
+ } catch (IllegalArgumentException ex) {
+ throw new ProcessingException(ex);
+ }
+ }, false);
+ }
+
+ /**
+ * Get any cookies that accompanied the message.
+ *
+ * @return a read-only map of cookie name (String) to {@link jakarta.ws.rs.core.Cookie}.
+ */
+ public Map<String, Cookie> getRequestCookies() {
+ @SuppressWarnings("unchecked")
+ final List<Object> cookies = (List<Object>) getHeaders().get(HttpHeaders.COOKIE);
+ if (cookies == null || cookies.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, Cookie> result = new HashMap<String, Cookie>();
+ for (String cookie : toStringList(cookies)) {
+ if (cookie != null) {
+ result.putAll(HttpHeaderReader.readCookies(cookie));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get any new cookies set on the message.
+ *
+ * @return a read-only map of cookie name (String) to a {@link jakarta.ws.rs.core.NewCookie new cookie}.
+ */
+ public Map<String, NewCookie> getResponseCookies() {
+ @SuppressWarnings("unchecked")
+ List<Object> cookies = (List<Object>) getHeaders().get(HttpHeaders.SET_COOKIE);
+ if (cookies == null || cookies.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, NewCookie> result = new HashMap<String, NewCookie>();
+ for (String cookie : toStringList(cookies)) {
+ if (cookie != null) {
+ NewCookie newCookie = HttpHeaderReader.readNewCookie(cookie);
+ String cookieName = newCookie.getName();
+ if (result.containsKey(cookieName)) {
+ result.put(cookieName, HeaderUtils.getPreferredCookie(result.get(cookieName), newCookie));
+ } else {
+ result.put(cookieName, newCookie);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Check if link for relation exists.
+ *
+ * @param relation link relation.
+ * @return {@code true} if the for the relation link exists, {@code false}
+ * otherwise.
+ */
+ public boolean hasLink(String relation) {
+ for (Link link : getLinks()) {
+ List<String> relations = LinkProvider.getLinkRelations(link.getRel());
+
+ if (relations != null && relations.contains(relation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get a single typed header value.
+ *
+ * @param <T> header value type.
+ * @param name header name.
+ * @param valueType header value class.
+ * @param converter from string conversion function. Is expected to throw {@link ProcessingException}
+ * if conversion fails.
+ * @param convertNull if {@code true} this method calls the provided converter even for {@code null}. Otherwise this
+ * method returns the {@code null} without calling the converter.
+ * @return value of the header, or (possibly converted) {@code null} if not present.
+ */
+ protected <T> T singleHeader(String name, Class<T> valueType, Function<String, T> converter, boolean convertNull) {
+ @SuppressWarnings("unchecked")
+ final List<Object> values = (List<Object>) getHeaders().get(name);
+
+ if (values == null || values.isEmpty()) {
+ return convertNull ? converter.apply(null) : null;
+ }
+ if (values.size() > 1) {
+ throw new HeaderValueException(
+ LocalizationMessages.TOO_MANY_HEADER_VALUES(name, values.toString()),
+ getHeaderValueExceptionContext());
+ }
+
+ Object value = values.get(0);
+ if (value == null) {
+ return convertNull ? converter.apply(null) : null;
+ }
+
+ if (HeaderValueException.Context.OUTBOUND == getHeaderValueExceptionContext() && valueType.isInstance(value)) {
+ return valueType.cast(value);
+ } else {
+ try {
+ return converter.apply(HeaderUtils.asString(value, runtimeDelegateDecorator));
+ } catch (ProcessingException ex) {
+ throw exception(name, value, ex);
+ }
+ }
+ }
+
+ /**
+ * Get a single typed header value for Inbound messages
+ *
+ * @param <T> header value type.
+ * @param name header name.
+ * @param converter from string conversion function. Is expected to throw {@link ProcessingException}
+ * if conversion fails.
+ * @param convertNull if {@code true} this method calls the provided converter even for {@code null}. Otherwise this
+ * method returns the {@code null} without calling the converter.
+ * @return value of the header, or (possibly converted) {@code null} if not present.
+ */
+ protected <T> T singleHeader(String name, Function<String, T> converter, boolean convertNull) {
+ return singleHeader(name, null, converter, convertNull);
+ }
+
+ protected HeaderValueException exception(final String headerName, Object headerValue, Exception e) {
+ return new HeaderValueException(LocalizationMessages.UNABLE_TO_PARSE_HEADER_VALUE(headerName, headerValue), e,
+ getHeaderValueExceptionContext());
+ }
+
+ private List<String> toStringList(List list) {
+ return getHeaderValueExceptionContext() == HeaderValueException.Context.OUTBOUND
+ ? HeaderUtils.asStringList(list, runtimeDelegateDecorator)
+ : (List<String>) list;
+ }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
index fa1117a..307f54f 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -92,6 +92,7 @@
bindSingletonWorker(ByteArrayProvider.class);
// bindSingletonWorker(DataSourceProvider.class);
bindSingletonWorker(FileProvider.class);
+ bindSingletonWorker(PathProvider.class);
bindSingletonWorker(FormMultivaluedMapProvider.class);
bindSingletonWorker(FormProvider.class);
bindSingletonWorker(InputStreamProvider.class);
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
index 8615aeb..08fbf5a 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 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
@@ -81,7 +81,7 @@
}
if (cookie.getExpiry() != null) {
b.append(";Expires=");
- b.append(HttpDateFormat.getPreferredDateFormat().format(cookie.getExpiry()));
+ b.append(HttpDateFormat.getPreferredDateFormatter().format(cookie.getExpiry()));
}
return b.toString();
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
index 26d3f14..ae41378 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NullOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,22 +18,17 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Objects;
import org.glassfish.jersey.internal.LocalizationMessages;
/**
- * A {@code "dev/null"} output stream - an output stream implementation that discards all the
- * data written to it. This implementation is not thread-safe.
- *
- * Note that once a null output stream instance is {@link #close() closed}, any subsequent attempts
- * to write the data to the closed stream result in an {@link java.io.IOException} being thrown.
- *
- * @author Miroslav Fuksa
- * @author Marek Potociar
+ * Since JDK 11 is replaced by {@link OutputStream#nullOutputStream()}
*/
+@Deprecated(since = "3.1.7", forRemoval = true)
public class NullOutputStream extends OutputStream {
- private boolean isClosed;
+ private volatile boolean isClosed;
@Override
public void write(int b) throws IOException {
@@ -43,11 +38,7 @@
@Override
public void write(byte[] b, int off, int len) throws IOException {
checkClosed();
- if (b == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- }
+ Objects.checkFromIndexSize(off, len, b.length);
}
@Override
@@ -65,4 +56,4 @@
public void close() throws IOException {
isClosed = true;
}
-}
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java
index 4db8b21..87fc281 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundJaxrsResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,6 +26,8 @@
import java.util.Date;
import java.util.HashSet;
import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -200,7 +202,12 @@
@Override
public void close() throws ProcessingException {
closed = true;
- context.close();
+ try {
+ context.close();
+ } catch (Exception e) {
+ // Just log the exception
+ Logger.getLogger(OutboundJaxrsResponse.class.getName()).log(Level.FINE, e.getMessage(), e);
+ }
if (buffered) {
// release buffer
context.setEntity(null);
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java
index d33acc3..ceb1540 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.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
@@ -18,52 +18,41 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.io.UncheckedIOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
-import java.net.URI;
-import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import java.util.stream.Collectors;
-import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Cookie;
-import jakarta.ws.rs.core.EntityTag;
import jakarta.ws.rs.core.GenericEntity;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Link;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.NewCookie;
-import jakarta.ws.rs.ext.RuntimeDelegate;
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.internal.RuntimeDelegateDecorator;
-import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.internal.util.collection.GuardianStringKeyMultivaluedMap;
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.io.spi.FlushedCloseable;
/**
* Base outbound message context implementation.
*
* @author Marek Potociar
*/
-public class OutboundMessageContext {
+public class OutboundMessageContext extends MessageHeaderMethods {
private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0];
private static final List<MediaType> WILDCARD_ACCEPTABLE_TYPE_SINGLETON_LIST =
Collections.<MediaType>singletonList(MediaTypes.WILDCARD_ACCEPTABLE_TYPE);
@@ -71,7 +60,6 @@
private final GuardianStringKeyMultivaluedMap<Object> headers;
private final CommittingOutputStream committingOutputStream;
private Configuration configuration;
- private RuntimeDelegate runtimeDelegateDecorator;
private LazyValue<MediaType> mediaTypeCache;
private Object entity;
@@ -107,11 +95,11 @@
* @param configuration the client/server {@link Configuration}. If {@code null}, the default behaviour is expected.
*/
public OutboundMessageContext(Configuration configuration) {
+ super(configuration);
this.configuration = configuration;
this.headers = new GuardianStringKeyMultivaluedMap<>(HeaderUtils.createOutbound());
this.committingOutputStream = new CommittingOutputStream();
this.entityStream = committingOutputStream;
- this.runtimeDelegateDecorator = RuntimeDelegateDecorator.configured(configuration);
this.mediaTypeCache = mediaTypeCache();
headers.setGuard(HttpHeaders.CONTENT_TYPE);
@@ -124,6 +112,7 @@
* @param original the original outbound message context.
*/
public OutboundMessageContext(OutboundMessageContext original) {
+ super(original);
this.headers = new GuardianStringKeyMultivaluedMap<>(HeaderUtils.createOutbound());
this.headers.setGuard(HttpHeaders.CONTENT_TYPE);
this.headers.putAll(original.headers);
@@ -134,7 +123,6 @@
this.entityType = original.entityType;
this.entityAnnotations = original.entityAnnotations;
this.configuration = original.configuration;
- this.runtimeDelegateDecorator = original.runtimeDelegateDecorator;
this.mediaTypeCache = mediaTypeCache();
}
@@ -190,49 +178,9 @@
return HeaderUtils.asHeaderString(headers.get(name), runtimeDelegateDecorator);
}
- /**
- * Get a single typed header value.
- *
- * @param <T> header value type.
- * @param name header name.
- * @param valueType header value class.
- * @param converter from string conversion function. Is expected to throw {@link ProcessingException}
- * if conversion fails.
- * @param convertNull if {@code true} this method calls the provided converter even for {@code null}. Otherwise this
- * method returns the {@code null} without calling the converter.
- * @return value of the header, or (possibly converted) {@code null} if not present.
- */
- private <T> T singleHeader(String name, Class<T> valueType, Function<String, T> converter, boolean convertNull) {
- final List<Object> values = headers.get(name);
-
- if (values == null || values.isEmpty()) {
- return convertNull ? converter.apply(null) : null;
- }
- if (values.size() > 1) {
- throw new HeaderValueException(
- LocalizationMessages.TOO_MANY_HEADER_VALUES(name, values.toString()),
- HeaderValueException.Context.OUTBOUND);
- }
-
- Object value = values.get(0);
- if (value == null) {
- return convertNull ? converter.apply(null) : null;
- }
-
- if (valueType.isInstance(value)) {
- return valueType.cast(value);
- } else {
- try {
- return converter.apply(HeaderUtils.asString(value, runtimeDelegateDecorator));
- } catch (ProcessingException ex) {
- throw exception(name, value, ex);
- }
- }
- }
-
- private static HeaderValueException exception(final String headerName, Object headerValue, Exception e) {
- return new HeaderValueException(LocalizationMessages.UNABLE_TO_PARSE_HEADER_VALUE(headerName, headerValue), e,
- HeaderValueException.Context.OUTBOUND);
+ @Override
+ public HeaderValueException.Context getHeaderValueExceptionContext() {
+ return HeaderValueException.Context.OUTBOUND;
}
/**
@@ -245,36 +193,6 @@
}
/**
- * Get message date.
- *
- * @return the message date, otherwise {@code null} if not present.
- */
- public Date getDate() {
- return singleHeader(HttpHeaders.DATE, Date.class, input -> {
- try {
- return HttpHeaderReader.readDate(input);
- } catch (ParseException e) {
- throw new ProcessingException(e);
- }
- }, false);
- }
-
- /**
- * Get the language of the entity.
- *
- * @return the language of the entity or {@code null} if not specified
- */
- public Locale getLanguage() {
- return singleHeader(HttpHeaders.CONTENT_LANGUAGE, Locale.class, input -> {
- try {
- return new LanguageTag(input).getAsLocale();
- } catch (ParseException e) {
- throw new ProcessingException(e);
- }
- }, false);
- }
-
- /**
* Get the media type of the entity.
*
* @return the media type or {@code null} if not specified (e.g. there's no
@@ -378,174 +296,6 @@
}
/**
- * Get any cookies that accompanied the message.
- *
- * @return a read-only map of cookie name (String) to {@link jakarta.ws.rs.core.Cookie}.
- */
- public Map<String, Cookie> getRequestCookies() {
- final List<Object> cookies = headers.get(HttpHeaders.COOKIE);
- if (cookies == null || cookies.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Map<String, Cookie> result = new HashMap<String, Cookie>();
- for (String cookie : HeaderUtils.asStringList(cookies, runtimeDelegateDecorator)) {
- if (cookie != null) {
- result.putAll(HttpHeaderReader.readCookies(cookie));
- }
- }
- return result;
- }
-
- /**
- * Get the allowed HTTP methods from the Allow HTTP header.
- *
- * @return the allowed HTTP methods, all methods will returned as upper case
- * strings.
- */
- public Set<String> getAllowedMethods() {
- final String allowed = getHeaderString(HttpHeaders.ALLOW);
- if (allowed == null || allowed.isEmpty()) {
- return Collections.emptySet();
- }
- try {
- return new HashSet<String>(HttpHeaderReader.readStringList(allowed));
- } catch (java.text.ParseException e) {
- throw exception(HttpHeaders.ALLOW, allowed, e);
- }
- }
-
- /**
- * Get Content-Length value.
- * <p>
- * <B>Note</B>: {@link #getLengthLong() getLengthLong()}
- * should be preferred over this method, since it returns a {@code long}
- * instead and is therefore more portable.</P>
- *
- * @return Content-Length as a postive integer if present and valid number, {@code -1} if negative number.
- * @throws ProcessingException when {@link Integer#parseInt(String)} (String)} throws {@link NumberFormatException}.
- */
- public int getLength() {
-
- return singleHeader(HttpHeaders.CONTENT_LENGTH, Integer.class, input -> {
- try {
- if (input != null && !input.isEmpty()) {
- int i = Integer.parseInt(input);
- if (i >= 0) {
- return i;
- }
- }
- return -1;
-
- } catch (NumberFormatException ex) {
- throw new ProcessingException(ex);
- }
- }, true);
- }
-
- /**
- * Get Content-Length value.
- *
- * @return Content-Length as a positive long if present and valid number, {@code -1} if negative number.
- * @throws ProcessingException when {@link Long#parseLong(String)} throws {@link NumberFormatException}.
- */
- public long getLengthLong() {
- return singleHeader(HttpHeaders.CONTENT_LENGTH, Long.class, input -> {
- try {
- if (input != null && !input.isEmpty()) {
- long l = Long.parseLong(input);
- if (l >= 0) {
- return l;
- }
- }
- return -1L;
- } catch (NumberFormatException ex) {
- throw new ProcessingException(ex);
- }
- }, true);
- }
-
- /**
- * Get any new cookies set on the message message.
- *
- * @return a read-only map of cookie name (String) to a {@link jakarta.ws.rs.core.NewCookie new cookie}.
- */
- public Map<String, NewCookie> getResponseCookies() {
- List<Object> cookies = headers.get(HttpHeaders.SET_COOKIE);
- if (cookies == null || cookies.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Map<String, NewCookie> result = new HashMap<String, NewCookie>();
- for (String cookie : HeaderUtils.asStringList(cookies, runtimeDelegateDecorator)) {
- if (cookie != null) {
- NewCookie newCookie = HttpHeaderReader.readNewCookie(cookie);
- String cookieName = newCookie.getName();
- if (result.containsKey(cookieName)) {
- result.put(cookieName, HeaderUtils.getPreferredCookie(result.get(cookieName), newCookie));
- } else {
- result.put(cookieName, newCookie);
- }
- }
- }
- return result;
- }
-
- /**
- * Get the entity tag.
- *
- * @return the entity tag, otherwise {@code null} if not present.
- */
- public EntityTag getEntityTag() {
- return singleHeader(HttpHeaders.ETAG, EntityTag.class, new Function<String, EntityTag>() {
- @Override
- public EntityTag apply(String value) {
- try {
- return value == null ? null : EntityTag.valueOf(value);
- } catch (IllegalArgumentException ex) {
- throw new ProcessingException(ex);
- }
- }
- }, false);
- }
-
- /**
- * Get the last modified date.
- *
- * @return the last modified date, otherwise {@code null} if not present.
- */
- public Date getLastModified() {
- return singleHeader(HttpHeaders.LAST_MODIFIED, Date.class, new Function<String, Date>() {
- @Override
- public Date apply(String input) {
- try {
- return HttpHeaderReader.readDate(input);
- } catch (ParseException e) {
- throw new ProcessingException(e);
- }
- }
- }, false);
- }
-
- /**
- * Get the location.
- *
- * @return the location URI, otherwise {@code null} if not present.
- */
- public URI getLocation() {
- return singleHeader(HttpHeaders.LOCATION, URI.class, new Function<String, URI>() {
- @Override
- public URI apply(String value) {
- try {
- return value == null ? null : URI.create(value);
- } catch (IllegalArgumentException ex) {
- throw new ProcessingException(ex);
- }
- }
- }, false);
- }
-
- /**
* Get the links attached to the message as header.
*
* @return links, may return empty {@link java.util.Set} if no links are present. Never
@@ -583,56 +333,6 @@
return Collections.unmodifiableSet(result);
}
- /**
- * Check if link for relation exists.
- *
- * @param relation link relation.
- * @return {@code true} if the for the relation link exists, {@code false}
- * otherwise.
- */
- public boolean hasLink(String relation) {
- for (Link link : getLinks()) {
- List<String> relations = LinkProvider.getLinkRelations(link.getRel());
- if (relations != null && relations.contains(relation)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the link for the relation.
- *
- * @param relation link relation.
- * @return the link for the relation, otherwise {@code null} if not present.
- */
- public Link getLink(String relation) {
- for (Link link : getLinks()) {
- List<String> relations = LinkProvider.getLinkRelations(link.getRel());
- if (relations != null && relations.contains(relation)) {
- return link;
- }
- }
- return null;
- }
-
- /**
- * Convenience method that returns a {@link jakarta.ws.rs.core.Link.Builder Link.Builder}
- * for the relation.
- *
- * @param relation link relation.
- * @return the link builder for the relation, otherwise {@code null} if not
- * present.
- */
- public Link.Builder getLinkBuilder(String relation) {
- Link link = getLink(relation);
- if (link == null) {
- return null;
- }
-
- return Link.fromLink(link);
- }
-
// Message entity
/**
@@ -856,19 +556,18 @@
/**
* Closes the context. Flushes and closes the entity stream.
+ * @throws UncheckedIOException if IO errors
*/
public void close() {
if (hasEntity()) {
try {
final OutputStream es = getEntityStream();
- es.flush();
+ if (!FlushedCloseable.class.isInstance(es)) {
+ es.flush();
+ }
es.close();
} catch (IOException e) {
- // Happens when the client closed connection before receiving the full response.
- // This is OK and not interesting in vast majority of the cases
- // hence the log level set to FINE to make sure it does not flood the log unnecessarily
- // (especially for clients disconnecting from SSE listening, which is very common).
- Logger.getLogger(OutboundMessageContext.class.getName()).log(Level.FINE, e.getMessage(), e);
+ throw new UncheckedIOException(e);
} finally {
// In case some of the output stream wrapper does not delegate close() call we
// close the root stream manually to make sure it commits the data.
@@ -876,8 +575,7 @@
try {
committingOutputStream.close();
} catch (IOException e) {
- // Just log the exception
- Logger.getLogger(OutboundMessageContext.class.getName()).log(Level.FINE, e.getMessage(), e);
+ throw new UncheckedIOException(e);
}
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
new file mode 100644
index 0000000..461a4f8
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/PathProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Markus KARG and others.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.message.internal;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static jakarta.ws.rs.core.MediaType.WILDCARD;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+import jakarta.inject.Singleton;
+
+/**
+ * Provider for marshalling/un-marshalling of {@code application/octet-stream}
+ * entity type to/from a {@link Path} instance.
+ *
+ * @author Markus KARG
+ */
+@Produces({APPLICATION_OCTET_STREAM, WILDCARD})
+@Consumes({APPLICATION_OCTET_STREAM, WILDCARD})
+@Singleton
+public final class PathProvider extends AbstractMessageReaderWriterProvider<Path> {
+
+ @Override
+ public final boolean isReadable(final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return Path.class == type;
+ }
+
+ @Override
+ public final Path readFrom(final Class<Path> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, String> httpHeaders,
+ final InputStream entityStream) throws IOException {
+ final var path = Utils.createTempFile().toPath();
+ Files.copy(entityStream, path, StandardCopyOption.REPLACE_EXISTING);
+ return path;
+ }
+
+ @Override
+ public final boolean isWriteable(final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType) {
+ return Path.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public final void writeTo(final Path t,
+ final Class<?> type,
+ final Type genericType,
+ final Annotation[] annotations,
+ final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders,
+ final OutputStream entityStream) throws IOException {
+ Files.copy(t, entityStream);
+ }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
index 91738c1..20a01d6 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,8 @@
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -38,6 +40,7 @@
import jakarta.ws.rs.ext.ReaderInterceptor;
import jakarta.ws.rs.ext.ReaderInterceptorContext;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -248,10 +251,11 @@
* {@link jakarta.ws.rs.ext.MessageBodyReader}s should not close the given {@link java.io.InputStream stream}. This input
* stream makes sure that the stream is not closed even if MBR tries to do it.
*/
- private static class UnCloseableInputStream extends InputStream {
+ private static class UnCloseableInputStream extends InputStreamWrapper {
private final InputStream original;
private final MessageBodyReader reader;
+ private final Lock markLock = new ReentrantLock();
private UnCloseableInputStream(final InputStream original, final MessageBodyReader reader) {
this.original = original;
@@ -259,43 +263,8 @@
}
@Override
- public int read() throws IOException {
- return original.read();
- }
-
- @Override
- public int read(final byte[] b) throws IOException {
- return original.read(b);
- }
-
- @Override
- public int read(final byte[] b, final int off, final int len) throws IOException {
- return original.read(b, off, len);
- }
-
- @Override
- public long skip(final long l) throws IOException {
- return original.skip(l);
- }
-
- @Override
- public int available() throws IOException {
- return original.available();
- }
-
- @Override
- public synchronized void mark(final int i) {
- original.mark(i);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- original.reset();
- }
-
- @Override
- public boolean markSupported() {
- return original.markSupported();
+ protected InputStream getWrapped() {
+ return original;
}
@Override
@@ -304,10 +273,6 @@
LOGGER.log(Level.FINE, LocalizationMessages.MBR_TRYING_TO_CLOSE_STREAM(reader.getClass()));
}
}
-
- private InputStream unwrap() {
- return original;
- }
}
/**
@@ -320,7 +285,7 @@
*/
public static InputStream closeableInputStream(InputStream inputStream) {
if (inputStream instanceof UnCloseableInputStream) {
- return ((UnCloseableInputStream) inputStream).unwrap();
+ return ((UnCloseableInputStream) inputStream).getWrapped();
} else {
return inputStream;
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
index 018c9f0..ae8e7d8 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
@@ -43,7 +43,7 @@
* A utility class for reading and writing using byte and character streams.
* <p>
* If a byte or character array is utilized then the size of the array
- * is by default the value of {@value org.glassfish.jersey.message.MessageProperties#IO_DEFAULT_BUFFER_SIZE}.
+ * is by default decided by the JRE.
* This value can be set using the system property
* {@value org.glassfish.jersey.message.MessageProperties#IO_BUFFER_SIZE}.
*
@@ -57,14 +57,19 @@
*
* @deprecated use {@code StandardCharsets.UTF_8} instead
*/
- @Deprecated
+ @Deprecated(forRemoval = true)
public static final Charset UTF8 = StandardCharsets.UTF_8;
/**
* The buffer size for arrays of byte and character.
*/
public static final int BUFFER_SIZE = getBufferSize();
- private static int getBufferSize() {
+ /**
+ * Whether {@linkplain BUFFER_SIZE} is to be ignored in favor of JRE's own decision.
+ */
+ public static final boolean AUTOSIZE_BUFFER = getAutosizeBuffer();
+
+ private static int getIOBufferSize() {
// TODO should we unify this buffer size and CommittingOutputStream buffer size (controlled by CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER)?
final String value = AccessController.doPrivileged(PropertiesHelper.getSystemProperty(MessageProperties.IO_BUFFER_SIZE));
if (value != null) {
@@ -78,11 +83,20 @@
LOGGER.log(Level.CONFIG,
"Value of " + MessageProperties.IO_BUFFER_SIZE
+ " property is not a valid positive integer [" + value + "]."
- + " Reverting to default [" + MessageProperties.IO_DEFAULT_BUFFER_SIZE + "].",
+ + " Reverting to default [at JRE's discretion].",
e);
}
}
- return MessageProperties.IO_DEFAULT_BUFFER_SIZE;
+ return -1;
+ }
+
+ private static int getBufferSize() {
+ final int ioBufferSize = getIOBufferSize();
+ return ioBufferSize == -1 ? MessageProperties.IO_DEFAULT_BUFFER_SIZE : ioBufferSize;
+ }
+
+ private static boolean getAutosizeBuffer() {
+ return getIOBufferSize() == -1;
}
/**
@@ -93,6 +107,11 @@
* @throws IOException if there is an error reading or writing bytes.
*/
public static void writeTo(InputStream in, OutputStream out) throws IOException {
+ if (AUTOSIZE_BUFFER) {
+ in.transferTo(out);
+ return;
+ }
+
int read;
final byte[] data = new byte[BUFFER_SIZE];
while ((read = in.read(data)) != -1) {
@@ -108,6 +127,11 @@
* @throws IOException if there is an error reading or writing characters.
*/
public static void writeTo(Reader in, Writer out) throws IOException {
+ if (AUTOSIZE_BUFFER) {
+ in.transferTo(out);
+ return;
+ }
+
int read;
final char[] data = new char[BUFFER_SIZE];
while ((read = in.read(data)) != -1) {
diff --git a/core-common/src/main/java/org/glassfish/jersey/model/Parameter.java b/core-common/src/main/java/org/glassfish/jersey/model/Parameter.java
index 4f7af42..4183568 100644
--- a/core-common/src/main/java/org/glassfish/jersey/model/Parameter.java
+++ b/core-common/src/main/java/org/glassfish/jersey/model/Parameter.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
@@ -446,14 +446,20 @@
parameterClass);
}
-
private static String getValue(Annotation a) {
try {
- Method m = a.annotationType().getMethod("value");
- if (m.getReturnType() != String.class) {
- return null;
+ Method[] methods = a.annotationType().getMethods();
+ for (Method method : methods) {
+ if ("value".equals(method.getName())) {
+ if (method.getReturnType() != String.class) {
+ return null;
+ } else {
+ return (String) method.invoke(a);
+ }
+ }
}
- return (String) m.invoke(a);
+ LOGGER.log(Level.FINER, () ->
+ String.format("Unable to get the %s annotation value property", a.getClass().getName()));
} catch (Exception ex) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER,
diff --git a/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java b/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
index ced41cd..4d92447 100644
--- a/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
+++ b/core-common/src/main/java/org/glassfish/jersey/process/internal/RequestScope.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -244,6 +244,7 @@
*/
protected void release(RequestContext context) {
context.release();
+ currentRequestContext.remove();
}
/**
diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/AbstractThreadPoolProvider.java b/core-common/src/main/java/org/glassfish/jersey/spi/AbstractThreadPoolProvider.java
index 27cf449..79ac262 100644
--- a/core-common/src/main/java/org/glassfish/jersey/spi/AbstractThreadPoolProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/spi/AbstractThreadPoolProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019 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
@@ -29,6 +29,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.guava.ThreadFactoryBuilder;
import org.glassfish.jersey.internal.util.ExtendedLogger;
@@ -37,6 +38,8 @@
import org.glassfish.jersey.internal.util.collection.Values;
import org.glassfish.jersey.process.JerseyProcessingUncaughtExceptionHandler;
+import jakarta.ws.rs.core.Configuration;
+
/**
* Abstract thread pool executor provider.
* <p>
@@ -69,9 +72,7 @@
private final String name;
private final AtomicBoolean closed = new AtomicBoolean(false);
- private final LazyValue<E> lazyExecutorServiceProvider =
- Values.lazy((Value<E>) () -> createExecutor(getCorePoolSize(), createThreadFactory(), getRejectedExecutionHandler()));
-
+ private final LazyValue<E> lazyExecutorServiceProvider;
/**
* Inheritance constructor.
*
@@ -79,7 +80,20 @@
* provided thread pool executor.
*/
protected AbstractThreadPoolProvider(final String name) {
+ this(name, null);
+ }
+
+ /**
+ * Inheritance constructor.
+ *
+ * @param name name of the provided thread pool executor. Will be used in the names of threads created & used by the
+ * provided thread pool executor.
+ * @param configuration {@link Configuration} properties.
+ */
+ protected AbstractThreadPoolProvider(final String name, Configuration configuration) {
this.name = name;
+ lazyExecutorServiceProvider = Values.lazy((Value<E>) () ->
+ createExecutor(getCorePoolSize(), createThreadFactory(configuration), getRejectedExecutionHandler()));
}
/**
@@ -208,9 +222,10 @@
return null;
}
- private ThreadFactory createThreadFactory() {
+ private ThreadFactory createThreadFactory(Configuration configuration) {
final ThreadFactoryBuilder factoryBuilder = new ThreadFactoryBuilder()
.setNameFormat(name + "-%d")
+ .setThreadFactory(VirtualThreadUtil.withConfig(configuration).getThreadFactory())
.setUncaughtExceptionHandler(new JerseyProcessingUncaughtExceptionHandler());
final ThreadFactory backingThreadFactory = getBackingThreadFactory();
diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/ScheduledThreadPoolExecutorProvider.java b/core-common/src/main/java/org/glassfish/jersey/spi/ScheduledThreadPoolExecutorProvider.java
index e805b23..348db2b 100644
--- a/core-common/src/main/java/org/glassfish/jersey/spi/ScheduledThreadPoolExecutorProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/spi/ScheduledThreadPoolExecutorProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 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
@@ -23,6 +23,7 @@
import java.util.concurrent.ThreadFactory;
import jakarta.annotation.PreDestroy;
+import jakarta.ws.rs.core.Configuration;
/**
* Default implementation of the Jersey {@link org.glassfish.jersey.spi.ScheduledExecutorServiceProvider
@@ -66,6 +67,17 @@
super(name);
}
+ /**
+ * Create a new instance of the scheduled thread pool executor provider.
+ *
+ * @param name provider name. The name will be used to name the threads created & used by the
+ * provisioned scheduled thread pool executor.
+ * @@param configuration {@link Configuration} properties.
+ */
+ public ScheduledThreadPoolExecutorProvider(final String name, Configuration configuration) {
+ super(name, configuration);
+ }
+
@Override
public ScheduledExecutorService getExecutorService() {
return super.getExecutor();
diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/ThreadPoolExecutorProvider.java b/core-common/src/main/java/org/glassfish/jersey/spi/ThreadPoolExecutorProvider.java
index 09e0770..df3dd09 100644
--- a/core-common/src/main/java/org/glassfish/jersey/spi/ThreadPoolExecutorProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/spi/ThreadPoolExecutorProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 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
@@ -26,6 +26,7 @@
import java.util.concurrent.TimeUnit;
import jakarta.annotation.PreDestroy;
+import jakarta.ws.rs.core.Configuration;
/**
* Default implementation of the Jersey {@link org.glassfish.jersey.spi.ExecutorServiceProvider executor service provider SPI}.
@@ -61,6 +62,17 @@
super(name);
}
+ /**
+ * Create a new instance of the thread pool executor provider.
+ *
+ * @param name provider name. The name will be used to name the threads created & used by the
+ * provisioned thread pool executor.
+ * @param configuration {@link Configuration} properties.
+ */
+ public ThreadPoolExecutorProvider(final String name, Configuration configuration) {
+ super(name, configuration);
+ }
+
@Override
public ExecutorService getExecutorService() {
return super.getExecutor();
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..867a65b
--- /dev/null
+++ b/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+ private static final LoomishExecutors NON_VIRTUAL = new NonLoomishExecutors(Executors.defaultThreadFactory());
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a permission to use virtual threads.
+ * @param allow whether to allow virtual threads.
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors allowVirtual(boolean allow) {
+ return NON_VIRTUAL;
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a permission to use virtual threads.
+ * @param allow whether to allow virtual threads.
+ * @param threadFactory the thread factory to be used by a the {@link ExecutorService}.
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors allowVirtual(boolean allow, ThreadFactory threadFactory) {
+ return new NonLoomishExecutors(threadFactory);
+ }
+
+ private static final class NonLoomishExecutors implements LoomishExecutors {
+ private final ThreadFactory threadFactory;
+
+ private NonLoomishExecutors(ThreadFactory threadFactory) {
+ this.threadFactory = threadFactory;
+ }
+
+ @Override
+ public ExecutorService newCachedThreadPool() {
+ return Executors.newCachedThreadPool();
+ }
+
+ @Override
+ public ExecutorService newFixedThreadPool(int nThreads) {
+ return Executors.newFixedThreadPool(nThreads);
+ }
+
+ @Override
+ public ThreadFactory getThreadFactory() {
+ return threadFactory;
+ }
+
+ @Override
+ public boolean isVirtual() {
+ 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..0e7d695
--- /dev/null
+++ b/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,123 @@
+/*
+ * 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;
+
+import org.glassfish.jersey.innate.virtual.LoomishExecutors;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+ private static final LoomishExecutors VIRTUAL_THREADS = new Java21LoomishExecutors(Thread.ofVirtual().factory());
+ private static final LoomishExecutors NON_VIRTUAL_THREADS = new NonLoomishExecutors(Executors.defaultThreadFactory());
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a permission to use virtual threads.
+ * @param allow whether to allow virtual threads.
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors allowVirtual(boolean allow) {
+ return allow ? VIRTUAL_THREADS : NON_VIRTUAL_THREADS;
+ }
+
+ /**
+ * Return an instance of {@link LoomishExecutors} based on a permission to use virtual threads.
+ * @param allow whether to allow virtual threads.
+ * @param threadFactory the thread factory to be used by a the {@link ExecutorService}.
+ * @return the {@link LoomishExecutors} instance.
+ */
+ public static LoomishExecutors allowVirtual(boolean allow, ThreadFactory threadFactory) {
+ return allow ? new Java21LoomishExecutors(threadFactory) : new NonLoomishExecutors(threadFactory);
+ }
+
+ private static class NonLoomishExecutors implements LoomishExecutors {
+ private final ThreadFactory threadFactory;
+
+ private NonLoomishExecutors(ThreadFactory threadFactory) {
+ this.threadFactory = threadFactory;
+ }
+
+ @Override
+ public ExecutorService newCachedThreadPool() {
+ return Executors.newCachedThreadPool(getThreadFactory());
+ }
+
+ @Override
+ public ExecutorService newFixedThreadPool(int nThreads) {
+ return Executors.newFixedThreadPool(nThreads, getThreadFactory());
+ }
+
+ @Override
+ public ThreadFactory getThreadFactory() {
+ return threadFactory;
+ }
+
+ @Override
+ public boolean isVirtual() {
+ return false;
+ }
+ }
+
+ private static class Java21LoomishExecutors implements LoomishExecutors {
+ private final ThreadFactory threadFactory;
+
+ private Java21LoomishExecutors(ThreadFactory threadFactory) {
+ this.threadFactory = threadFactory;
+ }
+
+ @Override
+ public ExecutorService newCachedThreadPool() {
+ return Executors.newThreadPerTaskExecutor(getThreadFactory());
+ }
+
+ @Override
+ public ExecutorService newFixedThreadPool(int nThreads) {
+ ThreadFactory threadFactory = this == VIRTUAL_THREADS ? Executors.defaultThreadFactory() : getThreadFactory();
+ return Executors.newFixedThreadPool(nThreads, threadFactory);
+ }
+
+ @Override
+ public ThreadFactory getThreadFactory() {
+ return threadFactory;
+ }
+
+ @Override
+ public boolean isVirtual() {
+ return true;
+ }
+ }
+}
diff --git a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
index ef2ae4d..184402f 100644
--- a/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
+++ b/core-common/src/main/resources/META-INF/native-image/org.glassfish.jersey.core/jersey-common/reflect-config.json
@@ -58,6 +58,12 @@
"allDeclaredConstructors":true
},
{
+ "name":"org.glassfish.jersey.message.internal.PathProvider",
+ "allDeclaredFields":true,
+ "allDeclaredMethods":true,
+ "allDeclaredConstructors":true
+ },
+ {
"name":"org.glassfish.jersey.message.internal.FormMultivaluedMapProvider",
"allDeclaredFields":true,
"allDeclaredMethods":true,
diff --git a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
index 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/internal/config/ExternalPropertiesConfigurationFactoryTest.java b/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java
index 6f1f7b1..ff3e9ef 100644
--- a/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java
+++ b/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java
@@ -1,5 +1,5 @@
/*
- * 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
@@ -30,11 +30,14 @@
public class ExternalPropertiesConfigurationFactoryTest {
+ private static boolean isSecurityManager;
+
/**
* Predefine some properties to be read from config
*/
@BeforeAll
public static void setUp() {
+ isSecurityManager = System.getSecurityManager() != null;
System.setProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.TRUE.toString());
System.setProperty("jersey.config.server.provider.scanning.recursive", "PASSED");
@@ -53,7 +56,11 @@
public void readSystemPropertiesTest() {
final Object result =
readExternalPropertiesMap().get("jersey.config.server.provider.scanning.recursive");
- Assertions.assertNull(result);
+ if (isSecurityManager) {
+ Assertions.assertNull(result);
+ } else {
+ Assertions.assertEquals("PASSED", result);
+ }
Assertions.assertEquals(Boolean.TRUE,
getConfig().isProperty(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE));
Assertions.assertEquals(Boolean.TRUE,
@@ -81,8 +88,11 @@
inputProperties.put("org.jersey.microprofile.config.added", "ADDED");
getConfig().mergeProperties(inputProperties);
final Object result = readExternalPropertiesMap().get("jersey.config.server.provider.scanning.recursive");
- Assertions.assertNull(result);
- Assertions.assertNull(readExternalPropertiesMap().get("org.jersey.microprofile.config.added"));
+ final Object resultAdded = readExternalPropertiesMap().get("org.jersey.microprofile.config.added");
+ if (isSecurityManager) {
+ Assertions.assertNull(result);
+ Assertions.assertNull(resultAdded);
+ }
}
}
diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java
index 67df369..237e749 100644
--- a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java
+++ b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.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
@@ -199,4 +199,15 @@
}
+ @Test
+ public void isPropertyOrNotSetTest() {
+ assertEquals(false, PropertiesHelper.isPropertyOrNotSet((Boolean) null));
+ assertEquals(true, PropertiesHelper.isPropertyOrNotSet(Boolean.TRUE));
+ assertEquals(false, PropertiesHelper.isPropertyOrNotSet(Boolean.FALSE));
+ assertEquals(false, PropertiesHelper.isPropertyOrNotSet((String) null));
+ assertEquals(true, PropertiesHelper.isPropertyOrNotSet(""));
+ assertEquals(false, PropertiesHelper.isPropertyOrNotSet("treu")); // false for non-boolean values
+ assertEquals(true, PropertiesHelper.isPropertyOrNotSet("TRUE"));
+ assertEquals(false, PropertiesHelper.isPropertyOrNotSet("false"));
+ }
}
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/pom.xml b/core-server/pom.xml
index 15f63b7..af9617f 100644
--- a/core-server/pom.xml
+++ b/core-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -237,7 +237,13 @@
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-vfs</artifactId>
- <version>3.2.6.Final</version>
+ <version>${jboss.vfs.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>${jboss.logging.version}</version>
<scope>test</scope>
</dependency>
@@ -259,6 +265,9 @@
<profiles>
<profile>
<id>securityOff</id>
+ <activation>
+ <jdk>[24,)</jdk>
+ </activation>
<properties>
<surefire.security.argline />
</properties>
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
index d1f86a6..23ea980 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java
@@ -144,7 +144,7 @@
// Write type_index and reserve space for num_element_value_pairs.
annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
return new AnnotationWriter(
- symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
+ symbolTable, /* useNamedValues= */ true, annotation, previousAnnotation);
}
/**
@@ -179,7 +179,7 @@
// Write type_index and reserve space for num_element_value_pairs.
typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
return new AnnotationWriter(
- symbolTable, /* useNamedValues = */ true, typeAnnotation, previousAnnotation);
+ symbolTable, /* useNamedValues= */ true, typeAnnotation, previousAnnotation);
}
// -----------------------------------------------------------------------------------------------
@@ -284,7 +284,7 @@
}
// Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
- return new AnnotationWriter(symbolTable, /* useNamedValues = */ true, annotation, null);
+ return new AnnotationWriter(symbolTable, /* useNamedValues= */ true, annotation, null);
}
@Override
@@ -303,7 +303,7 @@
// visit the array elements. Its num_element_value_pairs will correspond to the number of array
// elements and will be stored in what is in fact num_values.
annotation.put12('[', 0);
- return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
+ return new AnnotationWriter(symbolTable, /* useNamedValues= */ false, annotation, null);
}
@Override
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java
index f63fc71..1fe6dbf 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java
@@ -44,11 +44,11 @@
public final String type;
/**
- * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
- * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
- * included.
+ * The raw content of this attribute, as returned by {@link
+ * #write(ClassWriter,byte[],int,int,int)}. The 6 header bytes of the attribute
+ * (attribute_name_index and attribute_length) are <i>not</i> included.
*/
- private byte[] content;
+ private ByteVector cachedContent;
/**
* The next attribute in this attribute list (Attribute instances can be linked via this field to
@@ -93,7 +93,9 @@
*
* @return the labels corresponding to this attribute, or {@literal null} if this attribute is not
* a Code attribute that contains labels.
+ * @deprecated no longer used by ASM.
*/
+ @Deprecated
protected Label[] getLabels() {
return new Label[0];
}
@@ -115,7 +117,9 @@
* attribute header bytes (attribute_name_index and attribute_length) are not taken into
* account here.
* @param labels the labels of the method's code, or {@literal null} if the attribute to be read
- * is not a Code attribute.
+ * is not a Code attribute. Labels defined in the attribute must be created and added to this
+ * array, if not already present, by calling the {@link #readLabel} method (do not create
+ * {@link Label} instances directly).
* @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
*/
protected Attribute read(
@@ -126,16 +130,99 @@
final int codeAttributeOffset,
final Label[] labels) {
Attribute attribute = new Attribute(type);
- attribute.content = new byte[length];
- System.arraycopy(classReader.classFileBuffer, offset, attribute.content, 0, length);
+ attribute.cachedContent = new ByteVector(classReader.readBytes(offset, length));
return attribute;
}
/**
+ * Reads an attribute with the same {@link #type} as the given attribute. This method returns a
+ * new {@link Attribute} object, corresponding to the 'length' bytes starting at 'offset', in the
+ * given ClassReader.
+ *
+ * @param attribute The attribute prototype that is used for reading.
+ * @param classReader the class that contains the attribute to be read.
+ * @param offset index of the first byte of the attribute's content in {@link ClassReader}. The 6
+ * attribute header bytes (attribute_name_index and attribute_length) are not taken into
+ * account here.
+ * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
+ * @param charBuffer the buffer to be used to call the ClassReader methods requiring a
+ * 'charBuffer' parameter.
+ * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
+ * in {@link ClassReader}, or -1 if the attribute to be read is not a Code attribute. The 6
+ * attribute header bytes (attribute_name_index and attribute_length) are not taken into
+ * account here.
+ * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
+ * is not a Code attribute. Labels defined in the attribute are added to this array, if not
+ * already present.
+ * @return a new {@link Attribute} object corresponding to the specified bytes.
+ */
+ public static Attribute read(
+ final Attribute attribute,
+ final ClassReader classReader,
+ final int offset,
+ final int length,
+ final char[] charBuffer,
+ final int codeAttributeOffset,
+ final Label[] labels) {
+ return attribute.read(classReader, offset, length, charBuffer, codeAttributeOffset, labels);
+ }
+
+ /**
+ * Returns the label corresponding to the given bytecode offset by calling {@link
+ * ClassReader#readLabel}. This creates and adds the label to the given array if it is not already
+ * present. Note that this created label may be a {@link Label} subclass instance, if the given
+ * ClassReader overrides {@link ClassReader#readLabel}. Hence {@link #read(ClassReader, int, int,
+ * char[], int, Label[])} must not manually create {@link Label} instances.
+ *
+ * @param bytecodeOffset a bytecode offset in a method.
+ * @param labels the already created labels, indexed by their offset. If a label already exists
+ * for bytecodeOffset this method does not create a new one. Otherwise it stores the new label
+ * in this array.
+ * @return a label for the given bytecode offset.
+ */
+ public static Label readLabel(
+ final ClassReader classReader, final int bytecodeOffset, final Label[] labels) {
+ return classReader.readLabel(bytecodeOffset, labels);
+ }
+
+ /**
+ * Calls {@link #write(ClassWriter,byte[],int,int,int)} if it has not already been called and
+ * returns its result or its (cached) previous result.
+ *
+ * @param classWriter the class to which this attribute must be added. This parameter can be used
+ * to add the items that corresponds to this attribute to the constant pool of this class.
+ * @param code the bytecode of the method corresponding to this Code attribute, or {@literal null}
+ * if this attribute is not a Code attribute. Corresponds to the 'code' field of the Code
+ * attribute.
+ * @param codeLength the length of the bytecode of the method corresponding to this code
+ * attribute, or 0 if this attribute is not a Code attribute. Corresponds to the 'code_length'
+ * field of the Code attribute.
+ * @param maxStack the maximum stack size of the method corresponding to this Code attribute, or
+ * -1 if this attribute is not a Code attribute.
+ * @param maxLocals the maximum number of local variables of the method corresponding to this code
+ * attribute, or -1 if this attribute is not a Code attribute.
+ * @return the byte array form of this attribute.
+ */
+ private ByteVector maybeWrite(
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ if (cachedContent == null) {
+ cachedContent = write(classWriter, code, codeLength, maxStack, maxLocals);
+ }
+ return cachedContent;
+ }
+
+ /**
* Returns the byte array form of the content of this attribute. The 6 header bytes
* (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
* ByteVector.
*
+ * <p>This method is only invoked once to compute the binary form of this attribute. Subsequent
+ * changes to the attribute after it was written for the first time will not be considered.
+ *
* @param classWriter the class to which this attribute must be added. This parameter can be used
* to add the items that corresponds to this attribute to the constant pool of this class.
* @param code the bytecode of the method corresponding to this Code attribute, or {@literal null}
@@ -156,7 +243,39 @@
final int codeLength,
final int maxStack,
final int maxLocals) {
- return new ByteVector(content);
+ return cachedContent;
+ }
+
+ /**
+ * Returns the byte array form of the content of the given attribute. The 6 header bytes
+ * (attribute_name_index and attribute_length) are <i>not</i> added in the returned byte array.
+ *
+ * @param attribute The attribute that should be written.
+ * @param classWriter the class to which this attribute must be added. This parameter can be used
+ * to add the items that corresponds to this attribute to the constant pool of this class.
+ * @param code the bytecode of the method corresponding to this Code attribute, or {@literal null}
+ * if this attribute is not a Code attribute. Corresponds to the 'code' field of the Code
+ * attribute.
+ * @param codeLength the length of the bytecode of the method corresponding to this code
+ * attribute, or 0 if this attribute is not a Code attribute. Corresponds to the 'code_length'
+ * field of the Code attribute.
+ * @param maxStack the maximum stack size of the method corresponding to this Code attribute, or
+ * -1 if this attribute is not a Code attribute.
+ * @param maxLocals the maximum number of local variables of the method corresponding to this code
+ * attribute, or -1 if this attribute is not a Code attribute.
+ * @return the byte array form of this attribute.
+ */
+ public static byte[] write(
+ final Attribute attribute,
+ final ClassWriter classWriter,
+ final byte[] code,
+ final int codeLength,
+ final int maxStack,
+ final int maxLocals) {
+ ByteVector content = attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals);
+ byte[] result = new byte[content.length];
+ System.arraycopy(content.data, 0, result, 0, content.length);
+ return result;
}
/**
@@ -221,7 +340,7 @@
Attribute attribute = this;
while (attribute != null) {
symbolTable.addConstantUtf8(attribute.type);
- size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
+ size += 6 + attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals).length;
attribute = attribute.nextAttribute;
}
return size;
@@ -308,7 +427,7 @@
Attribute attribute = this;
while (attribute != null) {
ByteVector attributeContent =
- attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
+ attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals);
// Put attribute_name_index and attribute_length.
output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
output.putByteArray(attributeContent.data, 0, attributeContent.length);
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
index 820a3b8..f5d846a 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java
@@ -177,7 +177,7 @@
final byte[] classFileBuffer,
final int classFileOffset,
final int classFileLength) { // NOPMD(UnusedFormalParameter) used for backward compatibility.
- this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);
+ this(classFileBuffer, classFileOffset, /* checkClassVersion= */ true);
}
/**
@@ -195,7 +195,7 @@
this.b = classFileBuffer;
// Check the class' major_version. This field is after the magic and minor_version fields, which
// use 4 and 2 bytes respectively.
- if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V22) {
+ if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V24) {
throw new IllegalArgumentException(
"Unsupported class file major version " + readShort(classFileOffset + 6));
}
@@ -607,9 +607,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+ classVisitor.visitAnnotation(annotationDescriptor, /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -625,9 +625,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+ classVisitor.visitAnnotation(annotationDescriptor, /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -649,9 +649,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -673,9 +673,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -967,9 +967,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+ recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -985,9 +985,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+ recordComponentVisitor.visitAnnotation(annotationDescriptor, /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1009,9 +1009,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1033,9 +1033,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1151,9 +1151,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+ fieldVisitor.visitAnnotation(annotationDescriptor, /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1169,9 +1169,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+ fieldVisitor.visitAnnotation(annotationDescriptor, /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1193,9 +1193,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1217,9 +1217,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1412,9 +1412,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
+ methodVisitor.visitAnnotation(annotationDescriptor, /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1430,9 +1430,9 @@
// Parse num_element_value_pairs and element_value_pairs and visit these values.
currentAnnotationOffset =
readElementValues(
- methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
+ methodVisitor.visitAnnotation(annotationDescriptor, /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1454,9 +1454,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1478,9 +1478,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -1488,16 +1488,13 @@
// Visit the RuntimeVisibleParameterAnnotations attribute.
if (runtimeVisibleParameterAnnotationsOffset != 0) {
readParameterAnnotations(
- methodVisitor, context, runtimeVisibleParameterAnnotationsOffset, /* visible = */ true);
+ methodVisitor, context, runtimeVisibleParameterAnnotationsOffset, /* visible= */ true);
}
// Visit the RuntimeInvisibleParameterAnnotations attribute.
if (runtimeInvisibleParameterAnnotationsOffset != 0) {
readParameterAnnotations(
- methodVisitor,
- context,
- runtimeInvisibleParameterAnnotationsOffset,
- /* visible = */ false);
+ methodVisitor, context, runtimeInvisibleParameterAnnotationsOffset, /* visible= */ false);
}
// Visit the non standard attributes.
@@ -1926,7 +1923,7 @@
}
} else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
visibleTypeAnnotationOffsets =
- readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ true);
+ readTypeAnnotations(methodVisitor, context, currentOffset, /* visible= */ true);
// Here we do not extract the labels corresponding to the attribute content. This would
// require a full parsing of the attribute, which would need to be repeated when parsing
// the bytecode instructions (see below). Instead, the content of the attribute is read one
@@ -1935,7 +1932,7 @@
// time. This assumes that type annotations are ordered by increasing bytecode offset.
} else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
invisibleTypeAnnotationOffsets =
- readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ false);
+ readTypeAnnotations(methodVisitor, context, currentOffset, /* visible= */ false);
// Same comment as above for the RuntimeVisibleTypeAnnotations attribute.
} else if (Constants.STACK_MAP_TABLE.equals(attributeName)) {
if ((context.parsingOptions & SKIP_FRAMES) == 0) {
@@ -2517,9 +2514,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
currentVisibleTypeAnnotationBytecodeOffset =
@@ -2545,9 +2542,9 @@
context.currentTypeAnnotationTarget,
context.currentTypeAnnotationTargetPath,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentAnnotationOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
currentInvisibleTypeAnnotationBytecodeOffset =
@@ -2618,9 +2615,9 @@
context.currentLocalVariableAnnotationRangeEnds,
context.currentLocalVariableAnnotationRangeIndices,
annotationDescriptor,
- /* visible = */ true),
+ /* visible= */ true),
currentOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -2646,9 +2643,9 @@
context.currentLocalVariableAnnotationRangeEnds,
context.currentLocalVariableAnnotationRangeIndices,
annotationDescriptor,
- /* visible = */ false),
+ /* visible= */ false),
currentOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -2821,7 +2818,7 @@
methodVisitor.visitTryCatchAnnotation(
targetType & 0xFFFFFF00, path, annotationDescriptor, visible),
currentOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
} else {
// We don't want to visit the other target_type annotations, so we just skip them (which
@@ -2832,7 +2829,7 @@
// with a null AnnotationVisitor).
currentOffset =
readElementValues(
- /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
+ /* annotationVisitor= */ null, currentOffset, /* named= */ true, charBuffer);
}
}
return typeAnnotationsOffsets;
@@ -2972,7 +2969,7 @@
readElementValues(
methodVisitor.visitParameterAnnotation(i, annotationDescriptor, visible),
currentOffset,
- /* named = */ true,
+ /* named= */ true,
charBuffer);
}
}
@@ -3042,9 +3039,9 @@
case 'e': // enum_const_value
return currentOffset + 5;
case '@': // annotation_value
- return readElementValues(null, currentOffset + 3, /* named = */ true, charBuffer);
+ return readElementValues(null, currentOffset + 3, /* named= */ true, charBuffer);
case '[': // array_value
- return readElementValues(null, currentOffset + 1, /* named = */ false, charBuffer);
+ return readElementValues(null, currentOffset + 1, /* named= */ false, charBuffer);
default:
return currentOffset + 3;
}
@@ -3112,7 +3109,7 @@
return readElementValues(
annotationVisitor.visitArray(elementName),
currentOffset - 2,
- /* named = */ false,
+ /* named= */ false,
charBuffer);
}
switch (classFileBuffer[currentOffset] & 0xFF) {
@@ -3189,7 +3186,7 @@
readElementValues(
annotationVisitor.visitArray(elementName),
currentOffset - 2,
- /* named = */ false,
+ /* named= */ false,
charBuffer);
break;
}
@@ -3601,6 +3598,20 @@
}
/**
+ * Reads several bytes in this {@link ClassReader}. <i>This method is intended for {@link
+ * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
+ *
+ * @param offset the start offset of the bytes to be read in this {@link ClassReader}.
+ * @param length the number of bytes to read.
+ * @return the read bytes.
+ */
+ public byte[] readBytes(final int offset, final int length) {
+ byte[] result = new byte[length];
+ System.arraycopy(classFileBuffer, offset, result, 0, length);
+ return result;
+ }
+
+ /**
* Reads an unsigned short value in this {@link ClassReader}. <i>This method is intended for
* {@link Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
*
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
index 7588188..fa16ac9 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java
@@ -264,13 +264,7 @@
super(/* latest api = */ Opcodes.ASM9);
this.flags = flags;
symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader);
- if ((flags & COMPUTE_FRAMES) != 0) {
- compute = MethodWriter.COMPUTE_ALL_FRAMES;
- } else if ((flags & COMPUTE_MAXS) != 0) {
- compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL;
- } else {
- compute = MethodWriter.COMPUTE_NOTHING;
- }
+ setFlags(flags);
}
// -----------------------------------------------------------------------------------------------
@@ -774,7 +768,7 @@
lastRecordComponent = null;
firstAttribute = null;
compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING;
- new ClassReader(classFile, 0, /* checkClassVersion = */ false)
+ new ClassReader(classFile, 0, /* checkClassVersion= */ false)
.accept(
this,
attributes,
@@ -1020,6 +1014,28 @@
return symbolTable.addConstantNameAndType(name, descriptor);
}
+ /**
+ * Changes the computation strategy of method properties like max stack size, max number of local
+ * variables, and frames.
+ *
+ * <p><b>WARNING</b>: {@link #setFlags(int)} method changes the behavior of new method visitors
+ * returned from {@link #visitMethod(int, String, String, String, String[])}. The behavior will be
+ * changed only after the next method visitor is returned. All the previously returned method
+ * visitors keep their previous behavior.
+ *
+ * @param flags option flags that can be used to modify the default behavior of this class. Must
+ * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}.
+ */
+ public final void setFlags(final int flags) {
+ if ((flags & ClassWriter.COMPUTE_FRAMES) != 0) {
+ compute = MethodWriter.COMPUTE_ALL_FRAMES;
+ } else if ((flags & ClassWriter.COMPUTE_MAXS) != 0) {
+ compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL;
+ } else {
+ compute = MethodWriter.COMPUTE_NOTHING;
+ }
+ }
+
// -----------------------------------------------------------------------------------------------
// Default method to compute common super classes when computing stack map frames
// -----------------------------------------------------------------------------------------------
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
index 9e7b98c..1c79ca7 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Constants.java
@@ -215,7 +215,7 @@
}
if (minorVersion != 0xFFFF) {
throw new IllegalStateException(
- "ASM9_EXPERIMENTAL can only be used by classes compiled with --enable-preview");
+ "ASM10_EXPERIMENTAL can only be used by classes compiled with --enable-preview");
}
}
}
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
index c8a482b..e2f2c92 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java
@@ -34,15 +34,16 @@
* visitTypeAnnotation} | {@code visitAttribute} )* [ {@code visitCode} ( {@code visitFrame} |
* {@code visit<i>X</i>Insn} | {@code visitLabel} | {@code visitInsnAnnotation} | {@code
* visitTryCatchBlock} | {@code visitTryCatchAnnotation} | {@code visitLocalVariable} | {@code
- * visitLocalVariableAnnotation} | {@code visitLineNumber} )* {@code visitMaxs} ] {@code visitEnd}.
- * In addition, the {@code visit<i>X</i>Insn} and {@code visitLabel} methods must be called in the
- * sequential order of the bytecode instructions of the visited code, {@code visitInsnAnnotation}
- * must be called <i>after</i> the annotated instruction, {@code visitTryCatchBlock} must be called
- * <i>before</i> the labels passed as arguments have been visited, {@code
- * visitTryCatchBlockAnnotation} must be called <i>after</i> the corresponding try catch block has
- * been visited, and the {@code visitLocalVariable}, {@code visitLocalVariableAnnotation} and {@code
- * visitLineNumber} methods must be called <i>after</i> the labels passed as arguments have been
- * visited.
+ * visitLocalVariableAnnotation} | {@code visitLineNumber} | {@code visitAttribute} )* {@code
+ * visitMaxs} ] {@code visitEnd}. In addition, the {@code visit<i>X</i>Insn} and {@code visitLabel}
+ * methods must be called in the sequential order of the bytecode instructions of the visited code,
+ * {@code visitInsnAnnotation} must be called <i>after</i> the annotated instruction, {@code
+ * visitTryCatchBlock} must be called <i>before</i> the labels passed as arguments have been
+ * visited, {@code visitTryCatchBlockAnnotation} must be called <i>after</i> the corresponding try
+ * catch block has been visited, and the {@code visitLocalVariable}, {@code
+ * visitLocalVariableAnnotation} and {@code visitLineNumber} methods must be called <i>after</i> the
+ * labels passed as arguments have been visited. Finally, the {@code visitAttribute} method must be
+ * called before {@code visitCode} for non-code attributes, and after it for code attributes.
*
* @author Eric Bruneton
*/
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
index 918bd71..b49f443 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java
@@ -651,7 +651,7 @@
@Override
public AnnotationVisitor visitAnnotationDefault() {
defaultValue = new ByteVector();
- return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, defaultValue, null);
+ return new AnnotationWriter(symbolTable, /* useNamedValues= */ false, defaultValue, null);
}
@Override
@@ -1519,14 +1519,14 @@
return lastCodeRuntimeVisibleTypeAnnotation =
new AnnotationWriter(
symbolTable,
- /* useNamedValues = */ true,
+ /* useNamedValues= */ true,
typeAnnotation,
lastCodeRuntimeVisibleTypeAnnotation);
} else {
return lastCodeRuntimeInvisibleTypeAnnotation =
new AnnotationWriter(
symbolTable,
- /* useNamedValues = */ true,
+ /* useNamedValues= */ true,
typeAnnotation,
lastCodeRuntimeInvisibleTypeAnnotation);
}
@@ -1642,7 +1642,7 @@
code.data[endOffset] = (byte) Opcodes.ATHROW;
// Emit a frame for this unreachable block, with no local and a Throwable on the stack
// (so that the ATHROW could consume this Throwable if it were reachable).
- int frameIndex = visitFrameStart(startOffset, /* numLocal = */ 0, /* numStack = */ 1);
+ int frameIndex = visitFrameStart(startOffset, /* numLocal= */ 0, /* numStack= */ 1);
currentFrame[frameIndex] =
Frame.getAbstractTypeFromInternalName(symbolTable, "java/lang/Throwable");
visitFrameEnd();
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
index 4256afa..eeb3df7 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java
@@ -288,6 +288,8 @@
int V20 = 0 << 16 | 64;
int V21 = 0 << 16 | 65;
int V22 = 0 << 16 | 66;
+ int V23 = 0 << 16 | 67;
+ int V24 = 0 << 16 | 68;
/**
* Version flag indicating that the class is using 'preview' features.
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Symbol.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Symbol.java
index f161884..34f3653 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Symbol.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/Symbol.java
@@ -178,7 +178,9 @@
* <li>the symbol's value for {@link #CONSTANT_INTEGER_TAG},{@link #CONSTANT_FLOAT_TAG}, {@link
* #CONSTANT_LONG_TAG}, {@link #CONSTANT_DOUBLE_TAG},
* <li>the CONSTANT_MethodHandle_info reference_kind field value for {@link
- * #CONSTANT_METHOD_HANDLE_TAG} symbols,
+ * #CONSTANT_METHOD_HANDLE_TAG} symbols (or this value left shifted by 8 bits for
+ * reference_kind values larger than or equal to H_INVOKEVIRTUAL and if the method owner is
+ * an interface),
* <li>the CONSTANT_InvokeDynamic_info bootstrap_method_attr_index field value for {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
* <li>the offset of a bootstrap method in the BootstrapMethods boostrap_methods array, for
diff --git a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
index dc601a1..e5e16be 100644
--- a/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
+++ b/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/SymbolTable.java
@@ -221,7 +221,9 @@
classReader.readByte(itemOffset),
classReader.readClass(memberRefItemOffset, charBuffer),
classReader.readUTF8(nameAndTypeItemOffset, charBuffer),
- classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer));
+ classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer),
+ classReader.readByte(memberRefItemOffset - 1)
+ == Symbol.CONSTANT_INTERFACE_METHODREF_TAG);
break;
case Symbol.CONSTANT_DYNAMIC_TAG:
case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
@@ -830,14 +832,15 @@
final String descriptor,
final boolean isInterface) {
final int tag = Symbol.CONSTANT_METHOD_HANDLE_TAG;
+ final int data = getConstantMethodHandleSymbolData(referenceKind, isInterface);
// Note that we don't need to include isInterface in the hash computation, because it is
// redundant with owner (we can't have the same owner with different isInterface values).
- int hashCode = hash(tag, owner, name, descriptor, referenceKind);
+ int hashCode = hash(tag, owner, name, descriptor, data);
Entry entry = get(hashCode);
while (entry != null) {
if (entry.tag == tag
&& entry.hashCode == hashCode
- && entry.data == referenceKind
+ && entry.data == data
&& entry.owner.equals(owner)
&& entry.name.equals(name)
&& entry.value.equals(descriptor)) {
@@ -851,8 +854,7 @@
constantPool.put112(
tag, referenceKind, addConstantMethodref(owner, name, descriptor, isInterface).index);
}
- return put(
- new Entry(constantPoolCount++, tag, owner, name, descriptor, referenceKind, hashCode));
+ return put(new Entry(constantPoolCount++, tag, owner, name, descriptor, data, hashCode));
}
/**
@@ -866,16 +868,36 @@
* @param owner the internal name of a class of interface.
* @param name a field or method name.
* @param descriptor a field or method descriptor.
+ * @param isInterface whether owner is an interface or not.
*/
private void addConstantMethodHandle(
final int index,
final int referenceKind,
final String owner,
final String name,
- final String descriptor) {
+ final String descriptor,
+ final boolean isInterface) {
final int tag = Symbol.CONSTANT_METHOD_HANDLE_TAG;
- int hashCode = hash(tag, owner, name, descriptor, referenceKind);
- add(new Entry(index, tag, owner, name, descriptor, referenceKind, hashCode));
+ final int data = getConstantMethodHandleSymbolData(referenceKind, isInterface);
+ int hashCode = hash(tag, owner, name, descriptor, data);
+ add(new Entry(index, tag, owner, name, descriptor, data, hashCode));
+ }
+
+ /**
+ * Returns the {@link Symbol#data} field for a CONSTANT_MethodHandle_info Symbol.
+ *
+ * @param referenceKind one of {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link
+ * Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
+ * Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
+ * Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param isInterface whether owner is an interface or not.
+ */
+ private static int getConstantMethodHandleSymbolData(
+ final int referenceKind, final boolean isInterface) {
+ if (referenceKind > Opcodes.H_PUTSTATIC && isInterface) {
+ return referenceKind << 8;
+ }
+ return referenceKind;
}
/**
@@ -1414,23 +1436,23 @@
}
Entry(final int index, final int tag, final String value, final int hashCode) {
- super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0);
+ super(index, tag, /* owner= */ null, /* name= */ null, value, /* data= */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final String value, final long data, final int hashCode) {
- super(index, tag, /* owner = */ null, /* name = */ null, value, data);
+ super(index, tag, /* owner= */ null, /* name= */ null, value, data);
this.hashCode = hashCode;
}
Entry(
final int index, final int tag, final String name, final String value, final int hashCode) {
- super(index, tag, /* owner = */ null, name, value, /* data = */ 0);
+ super(index, tag, /* owner= */ null, name, value, /* data= */ 0);
this.hashCode = hashCode;
}
Entry(final int index, final int tag, final long data, final int hashCode) {
- super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data);
+ super(index, tag, /* owner= */ null, /* name= */ null, /* value= */ null, data);
this.hashCode = hashCode;
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
index 7d75df1..730d1ce 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018 Payara Foundation and/or its affiliates.
*
* This program and the accompanying materials are made available under the
@@ -66,7 +66,6 @@
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.glassfish.jersey.message.internal.MessageBodyFactory;
import org.glassfish.jersey.message.internal.MessagingBinders;
-import org.glassfish.jersey.message.internal.NullOutputStream;
import org.glassfish.jersey.model.internal.ComponentBag;
import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
import org.glassfish.jersey.model.internal.RankedComparator;
@@ -586,7 +585,7 @@
* @return response future.
*/
public Future<ContainerResponse> apply(final ContainerRequest requestContext) {
- return apply(requestContext, new NullOutputStream());
+ return apply(requestContext, OutputStream.nullOutputStream());
}
/**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java b/core-server/src/main/java/org/glassfish/jersey/server/ChunkedOutput.java
index 2ce0542..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
@@ -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
@@ -26,6 +26,8 @@
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import jakarta.ws.rs.container.ConnectionCallback;
import jakarta.ws.rs.core.GenericType;
@@ -51,10 +53,10 @@
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 Object lock = new Object();
+ private final Lock lock = new ReentrantLock();
// the following flushing and touchingEntityStream variables are used in a synchronized block exclusively
private boolean flushing = false;
@@ -70,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();
+ }
}
/**
@@ -86,6 +135,7 @@
public ChunkedOutput(final Type chunkType) {
super(chunkType);
this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
+ queue = new LinkedBlockingDeque<>();
}
/**
@@ -101,6 +151,7 @@
} else {
this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
}
+ queue = new LinkedBlockingDeque<>();
}
/**
@@ -118,6 +169,7 @@
}
this.asyncContext = asyncContextProvider == null ? null : asyncContextProvider.get();
+ queue = new LinkedBlockingDeque<>();
}
/**
@@ -135,6 +187,7 @@
} else {
this.chunkDelimiter = ZERO_LENGTH_DELIMITER;
}
+ queue = new LinkedBlockingDeque<>();
}
/**
@@ -149,6 +202,7 @@
} else {
this.chunkDelimiter = chunkDelimiter.getBytes();
}
+ queue = new LinkedBlockingDeque<>();
}
/**
@@ -165,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);
}
/**
@@ -179,7 +253,12 @@
}
if (chunk != null) {
- queue.add(chunk);
+ try {
+ queue.put(chunk);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IOException(e);
+ }
}
flushQueue();
@@ -202,7 +281,8 @@
boolean shouldClose;
T t;
- synchronized (lock) {
+ lock.lock();
+ try {
if (flushing) {
// if another thread is already flushing the queue, we don't have to do anything
return null;
@@ -220,13 +300,15 @@
// and they don't have to bother
flushing = true;
}
+ } finally {
+ lock.unlock();
}
while (t != null) {
try {
- synchronized (lock) {
- touchingEntityStream = true;
- }
+ lock.lock();
+ touchingEntityStream = true;
+ lock.unlock();
final OutputStream origStream = responseContext.getEntityStream();
final OutputStream writtenStream = requestContext.getWorkers().writeTo(
@@ -265,14 +347,15 @@
}
throw mpe;
} finally {
- synchronized (lock) {
- touchingEntityStream = false;
- }
+ lock.lock();
+ touchingEntityStream = false;
+ lock.unlock();
}
t = queue.poll();
if (t == null) {
- synchronized (lock) {
+ lock.lock();
+ try {
// queue seems empty
// check again in the synchronized block before clearing the flushing flag
// first remember the closed flag (this has to be before polling the queue,
@@ -290,6 +373,8 @@
flushing = shouldClose;
break;
}
+ } finally {
+ lock.unlock();
}
}
}
@@ -303,18 +388,20 @@
onClose(e);
} finally {
if (closed) {
+ lock.lock();
try {
- synchronized (lock) {
- if (!touchingEntityStream) {
- responseContext.close();
- } // else the next thread will close responseContext
- }
+ if (!touchingEntityStream) {
+ responseContext.close();
+ } // else the next thread will close responseContext
} catch (final Exception e) {
// if no exception remembered before, remember this one
// otherwise the previously remembered exception (from catch clause) takes precedence
ex = ex == null ? e : ex;
+ } finally {
+ lock.unlock();
}
+
requestScopeContext.release();
// rethrow remembered exception (if any)
@@ -341,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.
*
@@ -353,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")
@@ -399,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/ContainerResponse.java b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
index bd7f7a3..a44e60e 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.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
@@ -26,6 +26,8 @@
import java.net.URI;
import java.util.Date;
import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.Map;
import java.util.Set;
@@ -400,9 +402,14 @@
public void close() {
if (!closed) {
closed = true;
- messageContext.close();
- requestContext.getResponseWriter().commit();
- requestContext.setWorkers(null);
+ try {
+ messageContext.close();
+ requestContext.setWorkers(null);
+ requestContext.getResponseWriter().commit();
+ } catch (Exception e) {
+ Logger.getLogger(ContainerResponse.class.getName()).log(Level.FINE, e.getMessage(), e);
+ requestContext.getResponseWriter().failure(e);
+ }
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
index ae39a68..6fc7a2a 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
@@ -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
@@ -39,6 +39,7 @@
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Feature;
+import org.glassfish.jersey.ApplicationSupplier;
import org.glassfish.jersey.internal.Errors;
import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory;
import org.glassfish.jersey.internal.inject.Binder;
@@ -70,7 +71,7 @@
* @author Michal Gajdos
* @author Marek Potociar
*/
-public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig {
+public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig, ApplicationSupplier {
private static final Logger LOGGER = Logger.getLogger(ResourceConfig.class.getName());
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
index 77974f1..d620958 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021 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
@@ -21,13 +21,14 @@
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.InstanceBinding;
import org.glassfish.jersey.model.internal.ComponentBag;
-import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer;
import org.glassfish.jersey.process.internal.AbstractExecutorProvidersConfigurator;
import org.glassfish.jersey.spi.ExecutorServiceProvider;
import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
import org.glassfish.jersey.spi.ScheduledThreadPoolExecutorProvider;
import org.glassfish.jersey.spi.ThreadPoolExecutorProvider;
+import jakarta.ws.rs.core.Configuration;
+
/**
* Configurator which initializes and register {@link org.glassfish.jersey.spi.ExecutorServiceProvider} and
* {@link org.glassfish.jersey.spi.ScheduledExecutorServiceProvider}.
@@ -43,7 +44,7 @@
ComponentBag componentBag = runtimeConfig.getComponentBag();
// TODO: Do we need to register DEFAULT Executor and ScheduledExecutor to InjectionManager?
- ScheduledExecutorServiceProvider defaultScheduledExecutorProvider = new DefaultBackgroundSchedulerProvider();
+ ScheduledExecutorServiceProvider defaultScheduledExecutorProvider = new DefaultBackgroundSchedulerProvider(runtimeConfig);
InstanceBinding<ScheduledExecutorServiceProvider> schedulerBinding = Bindings
.service(defaultScheduledExecutorProvider)
.to(ScheduledExecutorServiceProvider.class)
@@ -67,8 +68,8 @@
@BackgroundScheduler
private static class DefaultBackgroundSchedulerProvider extends ScheduledThreadPoolExecutorProvider {
- public DefaultBackgroundSchedulerProvider() {
- super("jersey-background-task-scheduler");
+ public DefaultBackgroundSchedulerProvider(Configuration configuration) {
+ super("jersey-background-task-scheduler", configuration);
}
@Override
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
index 5d8a3ad..3ef8565 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
@@ -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
@@ -304,7 +304,7 @@
/**
* If {@code true} then disable auto discovery on server.
*
- * By default auto discovery is automatically enabled if global property
+ * By default, auto discovery is automatically enabled if global property
* {@value org.glassfish.jersey.CommonProperties#FEATURE_AUTO_DISCOVERY_DISABLE} is not disabled. If set then the server
* property value overrides the global property value.
* <p>
@@ -345,9 +345,28 @@
public static final String OUTBOUND_CONTENT_LENGTH_BUFFER = CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER;
/**
+ * If {@code true} then disable configuration of Json Binding (JSR-367) feature on server.
+ *
+ * By default, Json Binding is automatically enabled if global property
+ * {@value org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE} is not disabled. If set then the server
+ * property value overrides the global property value.
+ * <p>
+ * The default value is {@code false}.
+ * </p>
+ * <p>
+ * The name of the configuration property is <tt>{@value}</tt>.
+ * </p>
+ * <p>This constant is an alias for {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE_SERVER}</p>
+ *
+ * @see org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE
+ */
+ @PropertyAlias
+ public static final String JSON_BINDING_FEATURE_DISABLE = CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER;
+
+ /**
* If {@code true} then disable configuration of Json Processing (JSR-353) feature on server.
*
- * By default Json Processing is automatically enabled if global property
+ * By default, Json Processing is automatically enabled if global property
* {@value org.glassfish.jersey.CommonProperties#JSON_PROCESSING_FEATURE_DISABLE} is not disabled. If set then the server
* property value overrides the global property value.
* <p>
@@ -366,7 +385,7 @@
/**
* If {@code true} then disable META-INF/services lookup on server.
*
- * By default Jersey looks up SPI implementations described by META-INF/services/* files.
+ * By default, Jersey looks up SPI implementations described by META-INF/services/* files.
* Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}.
* <p>
* The default value is {@code false}.
@@ -385,7 +404,7 @@
/**
* If {@code true} then disable configuration of MOXy Json feature on server.
*
- * By default MOXy Json is automatically enabled if global property
+ * By default, MOXy Json is automatically enabled if global property
* {@value org.glassfish.jersey.CommonProperties#MOXY_JSON_FEATURE_DISABLE} is not disabled. If set then the server
* property value overrides the global property value.
* <p>
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
index 7078db8..531e927 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java
@@ -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
@@ -34,6 +34,8 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -129,6 +131,14 @@
private final boolean rfc7231LocationHeaderRelativeUriResolution;
/**
+ * Cached value of configuration property
+ * {@link org.glassfish.jersey.server.ServerProperties#RESPONSE_SET_STATUS_OVER_SEND_ERROR}.
+ * If {@code true} method {@link ServerRuntime.CompletionCallbackRunner#onComplete(Throwable)}
+ * is used over {@link DefaultExceptionMapper#toResponse(Throwable)}.
+ */
+ private final boolean configSetStatusOverSendError;
+
+ /**
* Default exception mapper (@since 3.1.0 according to JAX-RS 3.1 spec)
*/
private static final ExceptionMapper<Throwable> DEFAULT_EXCEPTION_MAPPER = new DefaultExceptionMapper();
@@ -195,6 +205,9 @@
this.rfc7231LocationHeaderRelativeUriResolution = ServerProperties.getValue(configuration.getProperties(),
ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231,
Boolean.FALSE, Boolean.class);
+
+ this.configSetStatusOverSendError = ServerProperties.getValue(configuration.getProperties(),
+ ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, false, Boolean.class);
}
/**
@@ -450,15 +463,17 @@
if (!processResponseError(responseError)) {
// Pass the exception to the container.
- LOGGER.log(Level.WARNING, LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(), responseError);
-
try {
request.getResponseWriter().failure(responseError);
} finally {
- defaultMapperResponse = processResponseWithDefaultExceptionMapper(responseError, request);
-
- // completionCallbackRunner.onComplete(responseError); is called from
- // processResponseWithDefaultExceptionMapper
+ if (runtime.configSetStatusOverSendError) {
+ completionCallbackRunner.onComplete(responseError);
+ } else {
+ LOGGER.log(Level.WARNING,
+ LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER(),
+ responseError);
+ defaultMapperResponse = processResponseWithDefaultExceptionMapper(responseError, request);
+ }
}
}
@@ -544,9 +559,8 @@
waeResponse = webApplicationException.getResponse();
if (waeResponse != null && waeResponse.hasEntity()) {
- LOGGER.log(Level.FINE,
- LocalizationMessages.EXCEPTION_MAPPING_WAE_ENTITY(waeResponse.getStatus()),
- throwable);
+ LOGGER.log(Level.FINE, LocalizationMessages
+ .EXCEPTION_MAPPING_WAE_ENTITY(waeResponse.getStatus()), throwable);
return waeResponse;
}
}
@@ -801,7 +815,7 @@
}
};
- private final Object stateLock = new Object();
+ private final ReadWriteLock stateLock = new ReentrantReadWriteLock();
private State state = RUNNING;
private boolean cancelled = false;
@@ -833,11 +847,13 @@
@Override
public void onTimeout(final ContainerResponseWriter responseWriter) {
final TimeoutHandler handler = timeoutHandler;
+ stateLock.readLock().lock();
try {
- synchronized (stateLock) {
- if (state == SUSPENDED) {
- handler.handleTimeout(this);
- }
+ if (state == SUSPENDED) {
+ stateLock.readLock().unlock(); // unlock before handleTimeout to prevent write lock in handleTimeout
+ handler.handleTimeout(this);
+ } else {
+ stateLock.readLock().unlock();
}
} catch (final Throwable throwable) {
resume(throwable);
@@ -846,9 +862,9 @@
@Override
public void onComplete(final Throwable throwable) {
- synchronized (stateLock) {
- state = COMPLETED;
- }
+ stateLock.writeLock().lock();
+ state = COMPLETED;
+ stateLock.writeLock().unlock();
}
@Override
@@ -876,14 +892,19 @@
@Override
public boolean suspend() {
- synchronized (stateLock) {
- if (state == RUNNING) {
- if (responder.processingContext.request().getResponseWriter().suspend(
- AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS, this)) {
- state = SUSPENDED;
- return true;
- }
+ stateLock.readLock().lock();
+ if (state == RUNNING) {
+ stateLock.readLock().unlock();
+ if (responder.processingContext.request().getResponseWriter().suspend(
+ AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS, this)) {
+ // Must release read lock before acquiring write lock
+ stateLock.writeLock().lock();
+ state = SUSPENDED;
+ stateLock.writeLock().unlock();
+ return true;
}
+ } else {
+ stateLock.readLock().unlock();
}
return false;
}
@@ -926,12 +947,17 @@
}
private boolean resume(final Runnable handler) {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
if (state != SUSPENDED) {
return false;
}
- state = RESUMED;
+ } finally {
+ stateLock.readLock().unlock();
}
+ stateLock.writeLock().lock();
+ state = RESUMED;
+ stateLock.writeLock().unlock();
try {
responder.runtime.requestScope.runInScope(requestContext, handler);
@@ -979,7 +1005,8 @@
}
private boolean cancel(final Value<Response> responseValue) {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
if (cancelled) {
return true;
}
@@ -987,10 +1014,15 @@
if (state != SUSPENDED) {
return false;
}
- state = RESUMED;
- cancelled = true;
+ } finally {
+ stateLock.readLock().unlock();
}
+ stateLock.writeLock().lock();
+ state = RESUMED;
+ cancelled = true;
+ stateLock.writeLock().unlock();
+
responder.runtime.requestScope.runInScope(requestContext, new Runnable() {
@Override
public void run() {
@@ -1007,29 +1039,41 @@
}
public boolean isRunning() {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
return state == RUNNING;
+ } finally {
+ stateLock.readLock().unlock();
}
}
@Override
public boolean isSuspended() {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
return state == SUSPENDED;
+ } finally {
+ stateLock.readLock().unlock();
}
}
@Override
public boolean isCancelled() {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
return cancelled;
+ } finally {
+ stateLock.readLock().unlock();
}
}
@Override
public boolean isDone() {
- synchronized (stateLock) {
+ stateLock.readLock().lock();
+ try {
return state == COMPLETED;
+ } finally {
+ stateLock.readLock().unlock();
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
index 761065e..91ec565 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyRequestTimeoutHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,8 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -42,7 +44,7 @@
private ScheduledFuture<?> timeoutTask = null; // guarded by runtimeLock
private ContainerResponseWriter.TimeoutHandler timeoutHandler = null; // guarded by runtimeLock
private boolean suspended = false; // guarded by runtimeLock
- private final Object runtimeLock = new Object();
+ private final Lock runtimeLock = new ReentrantLock();
private final ContainerResponseWriter containerResponseWriter;
private final ScheduledExecutorService executor;
@@ -71,7 +73,8 @@
* @see ContainerResponseWriter#suspend(long, TimeUnit, ContainerResponseWriter.TimeoutHandler)
*/
public boolean suspend(final long timeOut, final TimeUnit unit, final TimeoutHandler handler) {
- synchronized (runtimeLock) {
+ runtimeLock.lock();
+ try {
if (suspended) {
return false;
}
@@ -81,6 +84,8 @@
containerResponseWriter.setSuspendTimeout(timeOut, unit);
return true;
+ } finally {
+ runtimeLock.unlock();
}
}
@@ -94,7 +99,8 @@
* @see ContainerResponseWriter#setSuspendTimeout(long, TimeUnit)
*/
public void setSuspendTimeout(final long timeOut, final TimeUnit unit) throws IllegalStateException {
- synchronized (runtimeLock) {
+ runtimeLock.lock();
+ try {
if (!suspended) {
throw new IllegalStateException(LocalizationMessages.SUSPEND_NOT_SUSPENDED());
}
@@ -110,18 +116,21 @@
@Override
public void run() {
+ runtimeLock.lock();
try {
- synchronized (runtimeLock) {
- timeoutHandler.onTimeout(containerResponseWriter);
- }
+ timeoutHandler.onTimeout(containerResponseWriter);
} catch (final Throwable throwable) {
LOGGER.log(Level.WARNING, LocalizationMessages.SUSPEND_HANDLER_EXECUTION_FAILED(), throwable);
+ } finally {
+ runtimeLock.unlock();
}
}
}, timeOut, unit);
} catch (final IllegalStateException ex) {
LOGGER.log(Level.WARNING, LocalizationMessages.SUSPEND_SCHEDULING_ERROR(), ex);
}
+ } finally {
+ runtimeLock.unlock();
}
}
@@ -132,10 +141,15 @@
close(false);
}
- private synchronized void close(final boolean interruptIfRunning) {
- if (timeoutTask != null) {
- timeoutTask.cancel(interruptIfRunning);
- timeoutTask = null;
+ private void close(final boolean interruptIfRunning) {
+ runtimeLock.lock();
+ try {
+ if (timeoutTask != null) {
+ timeoutTask.cancel(interruptIfRunning);
+ timeoutTask = null;
+ }
+ } finally {
+ runtimeLock.unlock();
}
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
index f8abbed..4e95a47 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,8 @@
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
@@ -54,7 +56,7 @@
private final Consumer<Binding> registerBinding;
private final Set<Class<?>> bindingCache;
- private final Object bindingCacheLock;
+ private final Lock bindingCacheLock;
private volatile ResourceModel resourceModel;
@@ -73,7 +75,7 @@
this.injectInstance = injectInstance;
this.registerBinding = registerBinding;
this.bindingCache = Collections.newSetFromMap(new IdentityHashMap<>());
- this.bindingCacheLock = new Object();
+ this.bindingCacheLock = new ReentrantLock();
}
@Override
@@ -110,11 +112,14 @@
return;
}
- synchronized (bindingCacheLock) {
+ bindingCacheLock.lock();
+ try {
if (bindingCache.contains(resourceClass)) {
return;
}
unsafeBindResource(resourceClass, null);
+ } finally {
+ bindingCacheLock.unlock();
}
}
@@ -135,7 +140,8 @@
return;
}
- synchronized (bindingCacheLock) {
+ bindingCacheLock.lock();
+ try {
if (bindingCache.contains(resourceClass)) {
return;
}
@@ -144,6 +150,8 @@
}
bindingCache.add(resourceClass);
+ } finally {
+ bindingCacheLock.unlock();
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
index a7d5829..dc99a5d 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/jmx/MBeanExposer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,8 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -60,7 +62,7 @@
private volatile ResourcesMBeanGroup resourceClassStatsGroup;
private volatile ExceptionMapperMXBeanImpl exceptionMapperMXBean;
private final AtomicBoolean destroyed = new AtomicBoolean(false);
- private final Object LOCK = new Object();
+ private final Lock LOCK = new ReentrantLock();
/**
* Name of domain that will prefix mbeans {@link ObjectName}. The code uses this
@@ -110,45 +112,47 @@
void registerMBean(Object mbean, String namePostfix) {
final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
final String name = domain + namePostfix;
+ LOCK.lock();
try {
- synchronized (LOCK) {
- if (destroyed.get()) {
- // already destroyed
- return;
- }
- final ObjectName objectName = new ObjectName(name);
- if (mBeanServer.isRegistered(objectName)) {
-
- LOGGER.log(Level.WARNING,
- LocalizationMessages.WARNING_MONITORING_MBEANS_BEAN_ALREADY_REGISTERED(objectName));
- mBeanServer.unregisterMBean(objectName);
- }
- mBeanServer.registerMBean(mbean, objectName);
+ if (destroyed.get()) {
+ // already destroyed
+ return;
}
+ final ObjectName objectName = new ObjectName(name);
+ if (mBeanServer.isRegistered(objectName)) {
+
+ LOGGER.log(Level.WARNING,
+ LocalizationMessages.WARNING_MONITORING_MBEANS_BEAN_ALREADY_REGISTERED(objectName));
+ mBeanServer.unregisterMBean(objectName);
+ }
+ mBeanServer.registerMBean(mbean, objectName);
} catch (JMException e) {
throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_MBEANS_REGISTRATION(name), e);
+ } finally {
+ LOCK.unlock();
}
}
private void unregisterJerseyMBeans(boolean destroy) {
final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ LOCK.lock();
try {
- synchronized (LOCK) {
- if (destroy) {
- destroyed.set(true); // do not register new beans since now
- }
+ if (destroy) {
+ destroyed.set(true); // do not register new beans since now
+ }
- if (domain == null) {
- // No bean has been registered yet.
- return;
- }
- final Set<ObjectName> names = mBeanServer.queryNames(new ObjectName(domain + ",*"), null);
- for (ObjectName name : names) {
- mBeanServer.unregisterMBean(name);
- }
+ if (domain == null) {
+ // No bean has been registered yet.
+ return;
+ }
+ final Set<ObjectName> names = mBeanServer.queryNames(new ObjectName(domain + ",*"), null);
+ for (ObjectName name : names) {
+ mBeanServer.unregisterMBean(name);
}
} catch (Exception e) {
throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_MBEANS_UNREGISTRATION_DESTROY(), e);
+ } finally {
+ LOCK.unlock();
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/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/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
index 7e9db27..917d094 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.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
@@ -309,7 +309,7 @@
private static class ClassReaderWrapper {
private static final Logger LOGGER = Logger.getLogger(ClassReader.class.getName());
- private static final int WARN_VERSION = Opcodes.V22;
+ private static final int WARN_VERSION = Opcodes.V24;
private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
private final byte[] b;
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
index 14e86e3..7b97eb9 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018 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
@@ -19,11 +19,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.server.internal.AbstractResourceFinderAdapter;
import org.glassfish.jersey.server.internal.LocalizationMessages;
@@ -109,52 +112,17 @@
@Override
public InputStream open() {
//noinspection NullableProblems
- return new InputStream() {
+ return new InputStreamWrapper() {
@Override
- public int read() throws IOException {
- return jarInputStream.read();
- }
-
- @Override
- public int read(final byte[] bytes) throws IOException {
- return jarInputStream.read(bytes);
- }
-
- @Override
- public int read(final byte[] bytes, final int i, final int i2) throws IOException {
- return jarInputStream.read(bytes, i, i2);
- }
-
- @Override
- public long skip(final long l) throws IOException {
- return jarInputStream.skip(l);
- }
-
- @Override
- public int available() throws IOException {
- return jarInputStream.available();
+ protected InputStream getWrapped() {
+ return jarInputStream;
}
@Override
public void close() throws IOException {
jarInputStream.closeEntry();
}
-
- @Override
- public synchronized void mark(final int i) {
- jarInputStream.mark(i);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- jarInputStream.reset();
- }
-
- @Override
- public boolean markSupported() {
- return jarInputStream.markSupported();
- }
};
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
index aa2874e..501372a 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarZipSchemeResourceFinderFactory.java
@@ -16,13 +16,13 @@
package org.glassfish.jersey.server.internal.scanning;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -155,7 +155,7 @@
return new URL(jarUrlString).openStream();
} catch (final MalformedURLException e) {
return Files.newInputStream(
- new File(UriComponent.decode(jarUrlString, UriComponent.Type.PATH)).toPath());
+ Path.of(UriComponent.decode(jarUrlString, UriComponent.Type.PATH)));
}
}
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
index 06a9432..d482dde 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/PackageNamesScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -27,6 +27,8 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import org.glassfish.jersey.internal.OsgiRegistry;
import org.glassfish.jersey.internal.util.ReflectionHelper;
@@ -54,7 +56,7 @@
* URI schemes.
* <p>
* Further schemes may be registered by registering an implementation of
- * {@link UriSchemeResourceFinderFactory} in the META-INF/services file whose name is the
+ * {@link UriSchemeResourceFinderFactory} in the META-INF/services file whose name is
* the fully qualified class name of {@link UriSchemeResourceFinderFactory}.
* <p>
* If a URI scheme is not supported a {@link ResourceFinderException} will be thrown
@@ -195,13 +197,15 @@
public abstract static class ResourcesProvider {
private static volatile ResourcesProvider provider;
+ private static final Lock RESOURCE_PROVIDER_LOCK = new ReentrantLock();
private static ResourcesProvider getInstance() {
// Double-check idiom for lazy initialization
ResourcesProvider result = provider;
if (result == null) { // first check without locking
- synchronized (ResourcesProvider.class) {
+ RESOURCE_PROVIDER_LOCK.lock();
+ try {
result = provider;
if (result == null) { // second check with locking
provider = result = new ResourcesProvider() {
@@ -214,6 +218,8 @@
};
}
+ } finally {
+ RESOURCE_PROVIDER_LOCK.unlock();
}
}
@@ -226,9 +232,9 @@
final ReflectPermission rp = new ReflectPermission("suppressAccessChecks");
security.checkPermission(rp);
}
- synchronized (ResourcesProvider.class) {
- ResourcesProvider.provider = provider;
- }
+ RESOURCE_PROVIDER_LOCK.lock();
+ ResourcesProvider.provider = provider;
+ RESOURCE_PROVIDER_LOCK.unlock();
}
/**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
index 5a7188a..62ce38d 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
@@ -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
@@ -21,6 +21,9 @@
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.Locale;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@@ -56,13 +59,14 @@
private byte[] wadlXmlRepresentation;
private String lastModified;
+ private final Lock lock = new ReentrantLock();
@Context
private WadlApplicationContext wadlContext;
public WadlResource() {
- this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT).format(new Date());
+ this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT, Locale.US).format(new Date());
}
private boolean isCached(UriInfo uriInfo, boolean detailedWadl) {
@@ -71,7 +75,8 @@
@Produces({"application/vnd.sun.wadl+xml", "application/xml"})
@GET
- public synchronized Response getWadl(@Context UriInfo uriInfo) {
+ public Response getWadl(@Context UriInfo uriInfo) {
+ lock.lock();
try {
if (!wadlContext.isWadlGenerationEnabled()) {
return Response.status(Response.Status.NOT_FOUND).build();
@@ -81,7 +86,7 @@
if ((wadlXmlRepresentation == null) || (!isCached(uriInfo, detailedWadl))) {
this.lastBaseUri = uriInfo.getBaseUri();
lastDetailedWadl = detailedWadl;
- this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT).format(new Date());
+ this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT, Locale.US).format(new Date());
ApplicationDescription applicationDescription = wadlContext.getApplication(uriInfo,
detailedWadl);
@@ -103,6 +108,8 @@
return Response.ok(new ByteArrayInputStream(wadlXmlRepresentation)).header("Last-modified", lastModified).build();
} catch (Exception e) {
throw new ProcessingException("Error generating /application.wadl.", e);
+ } finally {
+ lock.unlock();
}
}
@@ -110,9 +117,10 @@
@Produces({"application/xml"})
@GET
@Path("{path}")
- public synchronized Response getExternalGrammar(
+ public Response getExternalGrammar(
@Context UriInfo uriInfo,
@PathParam("path") String path) {
+ lock.lock();
try {
// Fail if wadl generation is disabled
if (!wadlContext.isWadlGenerationEnabled()) {
@@ -135,6 +143,8 @@
.build();
} catch (Exception e) {
throw new ProcessingException(LocalizationMessages.ERROR_WADL_RESOURCE_EXTERNAL_GRAMMAR(), e);
+ } finally {
+ lock.unlock();
}
}
diff --git a/core-server/src/main/resources/META-INF/NOTICE.markdown b/core-server/src/main/resources/META-INF/NOTICE.markdown
index 92d64be..2016cb4 100644
--- a/core-server/src/main/resources/META-INF/NOTICE.markdown
+++ b/core-server/src/main/resources/META-INF/NOTICE.markdown
@@ -36,7 +36,7 @@
* Copyright (c) 2015-2018 Oracle and/or its affiliates. All rights reserved.
* Copyright 2010-2013 Coda Hale and Yammer, Inc.
-org.objectweb.asm Version 9.6
+org.objectweb.asm Version 9.7.1
* License: Modified BSD (https://asm.ow2.io/license.html)
* Copyright: (c) 2000-2011 INRIA, France Telecom. All rights reserved.
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java b/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
index 50a5402..003a735 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/JarUtils.java
@@ -90,11 +90,7 @@
final InputStream f = new BufferedInputStream(
Files.newInputStream(new File(base, entry.getKey()).toPath()));
- final byte[] buf = new byte[1024];
- int read = 1024;
- while ((read = f.read(buf, 0, read)) != -1) {
- jos.write(buf, 0, read);
- }
+ f.transferTo(jos);
jos.closeEntry();
}
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
index 34f29d6..07b368e 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/FormParamTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -402,8 +402,8 @@
initiateWebApplication(FormResourceDate.class);
final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
- final String date_RFC1036 = "Sunday, 06-Nov-94 08:49:37 GMT";
- final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
+ final String date_RFC1036 = "Sunday, 07-Nov-04 08:49:37 GMT";
+ final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
final Form form = new Form();
form.param("a", date_RFC1123);
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterDateTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterDateTest.java
index 1f14c63..91acc2a 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterDateTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterDateTest.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
@@ -40,6 +40,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParamConverterDateTest extends AbstractTest {
+ private final String format = "EEE MMM dd HH:mm:ss Z yyyy";
+ private final SimpleDateFormat formatter = new SimpleDateFormat(format, new Locale("US"));
@Path("/")
public static class DateResource {
@@ -55,7 +57,7 @@
public void testDateResource() throws ExecutionException, InterruptedException {
initiateWebApplication(getBinder(), ParamConverterDateTest.DateResource.class);
final ContainerResponse responseContext = getResponseContext(UriBuilder.fromPath("/")
- .queryParam("d", new Date()).build().toString());
+ .queryParam("d", formatter.format(new Date())).build().toString());
assertEquals(200, responseContext.getStatus());
}
@@ -80,8 +82,6 @@
);
}
try {
- final String format = "EEE MMM dd HH:mm:ss Z yyyy";
- final SimpleDateFormat formatter = new SimpleDateFormat(format, new Locale("US"));
return rawType.cast(formatter.parse(value));
} catch (final ParseException ex) {
throw new ExtractorException(ex);
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
index 904c2e1..d193046 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/scanning/JarFileScannerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,7 +19,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -106,7 +106,7 @@
private int countJarEntriesUsingScanner(final String parent, final boolean recursive) throws IOException {
int scannedEntryCount = 0;
- try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+ try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, parent, recursive);
while (jarFileScanner.hasNext()) {
// Fetch next entry.
@@ -128,7 +128,7 @@
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testClassEnumerationWithNonexistentPackage(final boolean recursive) throws IOException {
- try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+ try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, "jakarta/ws/r", recursive);
assertFalse(jarFileScanner.hasNext(), "Unexpectedly found package 'jakarta.ws.r' in jakarta.ws.rs-api");
}
@@ -137,7 +137,7 @@
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testClassEnumerationWithClassPrefix(final boolean recursive) throws IOException {
- try (final InputStream jaxRsApi = Files.newInputStream(Paths.get(this.jaxRsApiPath))) {
+ try (final InputStream jaxRsApi = Files.newInputStream(Path.of(this.jaxRsApiPath))) {
final JarFileScanner jarFileScanner = new JarFileScanner(jaxRsApi, "jakarta/ws/rs/GE", recursive);
assertFalse(jarFileScanner.hasNext(), "Unexpectedly found package 'jakarta.ws.rs.GE' in jakarta.ws.rs-api");
}
diff --git a/docs/pom.xml b/docs/pom.xml
index 329183d..e4a4f8d 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml
index aa4aee9..4294bae 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
@@ -72,6 +72,40 @@
</entry>
</row>
<row>
+ <entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE; /
+ &jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT; /
+ &jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER;</entry>
+ <entry><literal>jersey.config.disableJsonBinding</literal> /
+ <literal>jersey.config.client.disableJsonBinding</literal> /
+ <literal>jersey.config.server.disableJsonBinding</literal></entry>
+ <entry>
+ <para>
+ Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>.
+ Can also be set as a system property.
+ </para>
+ <para>
+ Since 2.45.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION; </entry>
+ <entry><literal>jersey.config.application.disableJsonBinding</literal></entry>
+ <entry>
+ <para>
+ Disables configuration of Json Binding (JSR-367) feature for <literal>jakarta.ws.rs.core.Application</literal>
+ subclasses whose package names are specified as a value. The value is comma-separated string
+ defining prefixes of the application package names. Can also be set as a system property.
+ </para>
+ <para>
+ By default, Json Binding is automatically enabled.
+ </para>
+ <para>
+ Since 2.45.
+ </para>
+ </entry>
+ </row>
+ <row>
<entry>&jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE; /
&jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT; /
&jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER;</entry>
@@ -203,6 +237,39 @@
</entry>
</row>
<row>
+ <entry>&jersey.common.CommonProperties.THREAD_FACTORY;(Jersey 3.1.7 or later)
+ </entry>
+ <entry>
+ <literal>jersey.config.threads.factory</literal>
+ </entry>
+ <entry>
+ <para>
+ Defines the <literal>java.util.concurrent.ThreadFactory</literal> to be used by internal default
+ <literal>ExecutorServices</literal>.
+ </para>
+ <para>
+ The default is <literal>java.util.concurrent.Executors#defaultThreadFactory()</literal> on
+ platform threads and<literal>Thread.ofVirtual().factory()</literal> on virtual threads.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>&jersey.common.CommonProperties.USE_VIRTUAL_THREADS;(Jersey 3.1.7 or later)
+ </entry>
+ <entry>
+ <literal>jersey.config.threads.use.virtual</literal>
+ </entry>
+ <entry>
+ <para>
+ Defines whether the virtual threads should be used by Jersey on JDK 21+ when not using an exact number
+ of threads by <literal>FixedThreadPool</literal>.
+ </para>
+ <para>
+ The default is &lit.false; for this version of Jersey.
+ </para>
+ </entry>
+ </row>
+ <row>
<entry>&jersey.logging.LoggingFeature.LOGGING_FEATURE_LOGGER_NAME;
</entry>
<entry>
@@ -383,6 +450,15 @@
</entry>
</row>
<row>
+ <entry>&jersey.server.ServerProperties.JSON_BINDING_FEATURE_DISABLE;</entry>
+ <entry><literal>jersey.config.server.disableJsonBinding</literal></entry>
+ <entry>
+ <para>
+ Disables configuration of Json Processing (JSR-353) feature. Default value is <literal>false</literal>.
+ </para>
+ </entry>
+ </row>
+ <row>
<entry>&jersey.server.ServerProperties.JSON_PROCESSING_FEATURE_DISABLE;</entry>
<entry><literal>jersey.config.server.disableJsonProcessing</literal></entry>
<entry>
@@ -1073,6 +1149,15 @@
</entry>
</row>
<row>
+ <entry>&jersey.client.ClientProperties.JSON_BINDING_FEATURE_DISABLE;</entry>
+ <entry><literal>jersey.config.client.disableJsonBinding</literal></entry>
+ <entry>
+ <para>
+ Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>.
+ </para>
+ </entry>
+ </row>
+ <row>
<entry>&jersey.client.ClientProperties.JSON_PROCESSING_FEATURE_DISABLE;</entry>
<entry><literal>jersey.config.client.disableJsonProcessing</literal></entry>
<entry>
@@ -1170,7 +1255,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 +1452,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 +1512,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>
@@ -2199,6 +2381,42 @@
</para>
</entry>
</row>
+ <row>
+ <entry>&jersey.netty.NettyClientProperties.MAX_HEADER_SIZE;</entry>
+ <entry><literal>jersey.config.client.netty.maxHeaderSize</literal></entry>
+ <entry>
+ <para>
+ Parameter which allows extending of the header size for the Netty connector
+
+ Default header size is 8192b.
+ <literal>Since 2.44</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>&jersey.netty.NettyClientProperties.MAX_CHUNK_SIZE;</entry>
+ <entry><literal>jersey.config.client.netty.maxChunkSize</literal></entry>
+ <entry>
+ <para>
+ Parameter which allows extending of the chunk size for the Netty connector
+
+ Default chunk size is 8192b.
+ <literal>Since 2.44</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>&jersey.netty.NettyClientProperties.MAX_INITIAL_LINE_LENGTH;</entry>
+ <entry><literal>jersey.config.client.netty.maxInitialLineLength</literal></entry>
+ <entry>
+ <para>
+ Parameter which allows extending of the initial line length for the Netty connector
+
+ Default initial line length is 4096b.
+ <literal>Since 2.44</literal>
+ </para>
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -2307,4 +2525,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<HttpSession> {
+
+ 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<SessionInject> {
+
+ 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<SessionInject> 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..8037dc9 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,7 +52,47 @@
</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>22</entry></row>
+ <row><entry>3.1.5</entry><entry>11</entry><entry>22</entry></row>
+ <row><entry>3.1.6</entry><entry>11</entry><entry>23</entry></row>
+ <row><entry>3.1.7</entry><entry>11</entry><entry>23</entry></row>
+ </tbody>
+ </tgroup>
+ </table>
</para>
+ <section>
+ <title>Virtual Threads and Thread Factories</title>
+ <para>
+ With JDK 21 and above, Jersey (since 2.44) has the ability to use virtual threads instead of
+ the <literal>CachedThreadPool</literal> in the internal <literal>ExecutorServices</literal>.
+ Jersey also has the ability to specify the backing <literal>ThreadFactory</literal> for the
+ default <literal>ExecutorServices</literal> (the default <literal>ExecutorServices</literal>
+ can be overridden by the &jersey.common.spi.ExecutorServiceProvider; SPI).
+ </para>
+ <para>
+ To enable virtual threads and/or specify the <literal>ThreadFactory</literal>, use
+ &jersey.common.CommonProperties.USE_VIRTUAL_THREADS; and/or &jersey.common.CommonProperties.THREAD_FACTORY;
+ properties, respectively. See also the <xref linkend="appendix-properties-common"/> in appendix for property details.
+ </para>
+ </section>
</section>
<section>
<title>Introduction to Jersey dependencies</title>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent
index be67534..5fe6f8a 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<T></link>">
<!ENTITY jaxrs.core.GenericType "<link xlink:href='&jaxrs.javadoc.uri;/core/GenericType.html'>GenericType<T></link>">
@@ -350,6 +351,7 @@
<!ENTITY jersey.client.ClientProperties.DEFAULT_CHUNK_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#DEFAULT_CHUNK_SIZE'>ClientProperties.DEFAULT_CHUNK_SIZE</link>" >
<!ENTITY jersey.client.ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" >
<!ENTITY jersey.client.ClientProperties.FOLLOW_REDIRECTS "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#FOLLOW_REDIRECTS'>ClientProperties.FOLLOW_REDIRECTS</link>" >
+<!ENTITY jersey.client.ClientProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#JSON_BINDING_FEATURE_DISABLE'>ClientProperties.JSON_BINDING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.client.ClientProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>ClientProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.client.ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#METAINF_SERVICES_LOOKUP_DISABLE'>ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE</link>" >
<!ENTITY jersey.client.ClientProperties.MOXY_JSON_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#MOXY_JSON_FEATURE_DISABLE'>ClientProperties.MOXY_JSON_FEATURE_DISABLE</link>" >
@@ -359,6 +361,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>" >
@@ -394,6 +397,10 @@
<!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" >
<!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT</link>" >
<!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE_SERVER'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_SERVER</link>" >
+<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE'>CommonProperties.JSON_BINDING_FEATURE_DISABLE</link>" >
+<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT</link>" >
+<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER</link>" >
+<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_APPLICATION'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER</link>" >
@@ -414,9 +421,13 @@
<!ENTITY jersey.common.CommonProperties.JSON_JACKSON_DISABLED_MODULES_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_JACKSON_DISABLED_MODULES'>CommonProperties.JSON_JACKSON_DISABLED_MODULES_CLIENT</link>" >
<!ENTITY jersey.common.CommonProperties.JSON_JACKSON_DISABLED_MODULES_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_JACKSON_DISABLED_MODULES'>CommonProperties.JSON_JACKSON_DISABLED_MODULES_SERVER</link>" >
<!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.CommonProperties.THREAD_FACTORY "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#THREAD_FACTORY'>CommonProperties.THREAD_FACTORY</link>" >
+<!ENTITY jersey.common.CommonProperties.USE_VIRTUAL_THREADS "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#USE_VIRTUAL_THREADS'>CommonProperties.USE_VIRTUAL_THREADS</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 +564,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>">
@@ -583,6 +599,9 @@
<!ENTITY jersey.netty.NettyClientProperties.MAX_REDIRECTS "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#MAX_REDIRECTS'>NettyClientProperties.MAX_REDIRECTS</link>" >
<!ENTITY jersey.netty.NettyClientProperties.PRESERVE_METHOD_ON_REDIRECT "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#PRESERVE_METHOD_ON_REDIRECT'>NettyClientProperties.PRESERVE_METHOD_ON_REDIRECT</link>" >
<!ENTITY jersey.netty.NettyClientProperties.EXPECT_100_CONTINUE_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#EXPECT_100_CONTINUE_TIMEOUT'>NettyClientProperties.EXPECT_100_CONTINUE_TIMEOUT</link>" >
+<!ENTITY jersey.netty.NettyClientProperties.MAX_HEADER_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#MAX_HEADER_SIZE'>NettyClientProperties.MAX_HEADER_SIZE</link>" >
+<!ENTITY jersey.netty.NettyClientProperties.MAX_INITIAL_LINE_LENGTH "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#MAX_INITIAL_LINE_LENGTH'>NettyClientProperties.MAX_INITIAL_LINE_LENGTH</link>" >
+<!ENTITY jersey.netty.NettyClientProperties.MAX_CHUNK_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyClientProperties.html#MAX_CHUNK_SIZE'>NettyClientProperties.MAX_CHUNK_SIZE</link>" >
<!ENTITY jersey.netty.NettyConnectorProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/netty/connector/NettyConnectorProvider.html'>NettyConnectorProvider</link>">
<!ENTITY jersey.server.ApplicationHandler "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ApplicationHandler.html'>ApplicationHandler</link>">
<!ENTITY jersey.server.BackgroundScheduler "<link xlink:href='&jersey.javadoc.uri.prefix;/server/BackgroundScheduler.html'>@BackgroundScheduler</link>">
@@ -612,6 +631,7 @@
<!ENTITY jersey.server.ServerProperties.BV_SEND_ERROR_IN_RESPONSE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#BV_SEND_ERROR_IN_RESPONSE'>ServerProperties.BV_SEND_ERROR_IN_RESPONSE</link>" >
<!ENTITY jersey.server.ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" >
<!ENTITY jersey.server.ServerProperties.HTTP_METHOD_OVERRIDE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#HTTP_METHOD_OVERRIDE'>ServerProperties.HTTP_METHOD_OVERRIDE</link>" >
+<!ENTITY jersey.server.ServerProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#JSON_BINDING_FEATURE_DISABLE'>ServerProperties.JSON_BINDING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.server.ServerProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>ServerProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" >
<!ENTITY jersey.server.ServerProperties.LANGUAGE_MAPPINGS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#LANGUAGE_MAPPINGS'>ServerProperties.LANGUAGE_MAPPINGS</link>" >
<!ENTITY jersey.server.ServerProperties.MEDIA_TYPE_MAPPINGS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#MEDIA_TYPE_MAPPINGS'>ServerProperties.MEDIA_TYPE_MAPPINGS</link>" >
@@ -971,6 +991,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 288b923..f27d2f0 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
@@ -1129,7 +1129,7 @@
public class JsonbContextResolver implements ContextResolver<Jsonb> {
@Override
- public Jsonb getContext(Class>?< type) {
+ public Jsonb getContext(Class<?> type) {
JsonbConfig config = new JsonbConfig();
// configure JsonbConfig
...
@@ -1753,8 +1753,8 @@
<programlisting language="java">// MediaType of the body part will be derived from the file.
final List<EntityPart> multiPartEntity = new List<>();
-list.add(EntityPart.withFileName("file001.txt").content(new FileInputStream("file001.txt")).build());
-list.add(EntityPart.withFileName("mypom.xml").content(new FileInputStream("pom.xml")).build());
+list.add(EntityPart.withFileName("file001.txt").content(Files.newInputStream(Path.of("file001.txt"))).build());
+list.add(EntityPart.withFileName("mypom.xml").content(Files.newInputStream(Path.of("pom.xml"))).build());
final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
final Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);
@@ -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<MultiPartProperties></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/config/checkstyle.xml b/etc/config/checkstyle.xml
index 36a7def..52d0455 100644
--- a/etc/config/checkstyle.xml
+++ b/etc/config/checkstyle.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- 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
@@ -88,7 +88,7 @@
<!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
<module name="JavadocMethod">
- <property name="scope" value="protected"/>
+ <property name="accessModifiers" value="protected"/>
<!-- <property name="allowUndeclaredRTE" value="true"/>-->
</module>
<module name="JavadocType">
diff --git a/etc/config/copyright-exclude b/etc/config/copyright-exclude
index 62b47fc..9c4e32d 100644
--- a/etc/config/copyright-exclude
+++ b/etc/config/copyright-exclude
@@ -41,6 +41,7 @@
/etc/config/copyright.txt
/etc/config/edl-copyright.txt
/etc/jenkins/
+/etc/scripts/
/etc/travis/
/LICENSE.md
/third-party-license-readme.txt
@@ -92,3 +93,4 @@
/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonBindingProviderTest.java
/connectors/jdk-connector/src/test/resources
/tools
+/media/multipart/src/test/resources/multipart
diff --git a/etc/jenkins/Jenkinsfile_EE4J_build b/etc/jenkins/Jenkinsfile_EE4J_build
index 65a8b56..609d150 100644
--- a/etc/jenkins/Jenkinsfile_EE4J_build
+++ b/etc/jenkins/Jenkinsfile_EE4J_build
@@ -5,6 +5,10 @@
triggers {
pollSCM('H H * * *')
}
+ options {
+ disableConcurrentBuilds()
+ buildDiscarder(logRotator(numToKeepStr:'15', artifactNumToKeepStr: '2' ))
+ }
tools {
jdk 'oracle-jdk8-latest'
maven 'apache-maven-latest'
diff --git a/etc/jenkins/Jenkinsfile_ci_build b/etc/jenkins/Jenkinsfile_ci_build
index 4a622e4..276cc17 100644
--- a/etc/jenkins/Jenkinsfile_ci_build
+++ b/etc/jenkins/Jenkinsfile_ci_build
@@ -3,6 +3,8 @@
options {
timeout(time: 30, activity: true, unit: 'HOURS')
+ buildDiscarder(logRotator(numToKeepStr:'15', artifactNumToKeepStr: '2' ))
+ disableConcurrentBuilds()
}
stages {
@@ -19,6 +21,7 @@
steps {
sh '''
bash ${WORKSPACE}/etc/jenkins/jenkins_build.sh
+ bash ${WORKSPACE}/etc/scripts/validation/dependency-convergence.sh
'''
}
}
@@ -33,6 +36,8 @@
steps {
sh '''
bash ${WORKSPACE}/etc/jenkins/jenkins_build.sh
+ export EXCLUDE_ARGS=' -pl !:jersey-container-jetty11-http,!:jersey-jetty11-connector '
+ bash ${WORKSPACE}/etc/scripts/validation/dependency-convergence.sh
'''
}
}
diff --git a/etc/jenkins/Jenkinsfile_master_build b/etc/jenkins/Jenkinsfile_master_build
index a4c5483..9b62947 100644
--- a/etc/jenkins/Jenkinsfile_master_build
+++ b/etc/jenkins/Jenkinsfile_master_build
@@ -5,6 +5,10 @@
triggers {
pollSCM('H H * * *')
}
+ options {
+ disableConcurrentBuilds()
+ buildDiscarder(logRotator(numToKeepStr:'15', artifactNumToKeepStr: '2' ))
+ }
tools {
jdk 'oracle-jdk8-latest'
maven 'apache-maven-latest'
diff --git a/etc/jenkins/jenkins_build.sh b/etc/jenkins/jenkins_build.sh
index 9983a05..3543e90 100644
--- a/etc/jenkins/jenkins_build.sh
+++ b/etc/jenkins/jenkins_build.sh
@@ -2,4 +2,4 @@
export DEBUG=true
-mvn -V -U -B -e -Pstaging clean install glassfish-copyright:check -Dcopyright.quiet=false
\ No newline at end of file
+mvn -V -U -B -e -Pstaging clean install glassfish-copyright:check -Dcopyright.quiet=false -DskipSBOM
diff --git a/etc/scripts/apidocs.sh b/etc/scripts/apidocs.sh
new file mode 100755
index 0000000..12b2364
--- /dev/null
+++ b/etc/scripts/apidocs.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+mvn -U -V -B clean install -Ppre-release -pl :apidocs -am -DskipTests
\ No newline at end of file
diff --git a/etc/scripts/checkstyle.sh b/etc/scripts/checkstyle.sh
new file mode 100755
index 0000000..ad36942
--- /dev/null
+++ b/etc/scripts/checkstyle.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+mvn -V -U -B checkstyle:checkstyle-aggregate -Dcheckstyle.output.format="plain" -Dcheckstyle.output.file=checkstyle.log
\ No newline at end of file
diff --git a/etc/scripts/copyright.sh b/etc/scripts/copyright.sh
new file mode 100755
index 0000000..a874923
--- /dev/null
+++ b/etc/scripts/copyright.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+readonly CP_PATTERN='Copyright year is wrong'
+
+
+[[ -n ${1} ]] && readonly LOG_FILE=${1} || readonly LOG_FILE='copyright.log'
+
+
+echo ${LOG_FILE}
+
+mvn -U -B glassfish-copyright:copyright -Dcopyright.quiet=false | grep "${CP_PATTERN}" | tee ${LOG_FILE}
+
+grep "${CP_PATTERN}" ${LOG_FILE} || exit 0 && exit 1
\ No newline at end of file
diff --git a/etc/scripts/test-archetypes.sh b/etc/scripts/test-archetypes.sh
new file mode 100755
index 0000000..8ac27e3
--- /dev/null
+++ b/etc/scripts/test-archetypes.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+mvn -U -V -B clean install -pl org.glassfish.jersey.archetypes:project
\ No newline at end of file
diff --git a/etc/scripts/validation/dependency-convergence.sh b/etc/scripts/validation/dependency-convergence.sh
new file mode 100755
index 0000000..9bcf4fe
--- /dev/null
+++ b/etc/scripts/validation/dependency-convergence.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+readonly VALIDATION_DEPENDENCIES_MATCH='<!-- Insert dependencies here -->'
+readonly VALIDATION_POM=validation.pom.xml
+readonly POM_TEMPLATE_NAME=pom.template.xml
+readonly TEMP_FILE=modules.xml
+
+readonly MVN_CLI='org.apache.maven.plugins:maven-enforcer-plugin:enforce -Denforcer.rules=dependencyConvergence'
+
+readonly DEPENDENCY_GENERATION_PATTERN='<dependency><groupId>${project.groupId}</groupId><artifactId>${project.artifactId}</artifactId><version>${jersey.version}</version></dependency>'
+
+# Path to this script
+[ -h "${0}" ] && readonly SCRIPT_PATH="$(readlink "${0}")" || readonly SCRIPT_PATH="${0}"
+
+readonly CURRENT_LOCATION=$(dirname -- "${SCRIPT_PATH}")
+readonly WS_DIR=$(cd ${CURRENT_LOCATION}; cd '../../..' ; pwd -P)
+
+#Prepare pom.xml from template
+
+cp -a ${CURRENT_LOCATION}/${POM_TEMPLATE_NAME} ${CURRENT_LOCATION}/${VALIDATION_POM}
+
+export JERSEY_VERSION=$(mvn exec:exec -Dexec.executable='echo' -Dexec.args='${project.version}' -f ${WS_DIR}/pom.xml -q -pl org.glassfish.jersey:project)
+
+echo "Validating convergences for Jersey "$JERSEY_VERSION
+echo '****************************************************'
+echo `mvn -v`
+echo '****************************************************'
+
+#get list of modules to b validated
+mvn -f ${WS_DIR}/pom.xml -Dexec.executable='echo' \
+ -Dtests.excluded \
+ -Dexec.args=${DEPENDENCY_GENERATION_PATTERN} \
+ ${MVN_ARGS} \
+ ${EXCLUDE_ARGS} \
+ -pl '!:helloworld-benchmark' exec:exec -q > ${CURRENT_LOCATION}/${TEMP_FILE}
+
+#add the list of modules to the prepared pom.xml
+sed -e "/${VALIDATION_DEPENDENCIES_MATCH}/ {" -e "r ${CURRENT_LOCATION}/${TEMP_FILE}" -e 'd' -e '}' -i ${CURRENT_LOCATION}/${VALIDATION_POM}
+
+#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}
+
+#exit with saved exit stateus
+exit $MAVEN_BUILD_RESULT
diff --git a/etc/scripts/validation/pom.template.xml b/etc/scripts/validation/pom.template.xml
new file mode 100644
index 0000000..1e58300
--- /dev/null
+++ b/etc/scripts/validation/pom.template.xml
@@ -0,0 +1,41 @@
+<?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">
+ <groupId>org.glassfish.jersey.validation</groupId>
+ <artifactId>dependency-convergences</artifactId>
+ <version>0.0.1</version>
+ <modelVersion>4.0.0</modelVersion>
+
+ <packaging>war</packaging>
+ <name>jersey-dependency-convergence-validation</name>
+
+ <description>dependencyConvergence rule check</description>
+
+
+ <dependencies>
+ <!-- Insert dependencies here -->
+ </dependencies>
+
+ <properties>
+ <jersey.version>3.0.99-SNAPSHOT</jersey.version>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/examples/NOTICE.md b/examples/NOTICE.md
index 0dcc83c..ed616c2 100644
--- a/examples/NOTICE.md
+++ b/examples/NOTICE.md
@@ -1,4 +1,4 @@
-# Notice for Jersey
+# Notice for Jersey
This content is produced and maintained by the Eclipse Jersey project.
* Project home: https://projects.eclipse.org/projects/ee4j.jersey
@@ -39,8 +39,8 @@
Bean Validation API 3.0.2
* License: Apache License, 2.0
-* Project: http://beanvalidation.org/1.1/
-* Copyright: 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
+* Project: http://beanvalidation.org/3.0/
+* Copyright: 2009, 2020 Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag.
Hibernate Validator CDI, 8.0.1.Final
@@ -58,25 +58,25 @@
* Project: http://www.seamframework.org/Weld
* Copyright 2010, Red Hat, Inc., and individual contributors by the @authors tag.
-Google Guava Version 18.0
+Google Guava Version 33.3.0-jre
* License: Apache License, 2.0
-* Copyright (C) 2009 The Guava Authors
+* Copyright (C) 2009, 2024 The Guava Authors
-jakarta.inject Version: 1
+jakarta.inject Version: 2.0.1
* License: Apache License, 2.0
-* Copyright (C) 2009 The JSR-330 Expert Group
+* Copyright (C) 2009, 2021 The JSR-330 Expert Group
-Javassist Version 3.29.2-GA
+Javassist Version 3.30.2-GA
* License: Apache License, 2.0
* Project: http://www.javassist.org/
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
-Jackson JAX-RS Providers Version 2.15.3
+Jackson JAX-RS Providers Version 2.18.0
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
* Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
-jQuery v1.12.4
+jQuery v3.7.1
* License: jquery.org/license
* Project: jquery.org
* Copyright: (c) jQuery Foundation
@@ -96,7 +96,7 @@
* Project: http://www.kineticjs.com, https://github.com/ericdrowell/KineticJS
* Copyright: Eric Rowell
-org.objectweb.asm Version 9.6
+org.objectweb.asm Version 9.7.1
* License: Modified BSD (https://asm.ow2.io/license.html)
* Copyright (c) 2000-2011 INRIA, France Telecom. All rights reserved.
diff --git a/examples/assemblies/pom.xml b/examples/assemblies/pom.xml
index 840d169..defda8f 100644
--- a/examples/assemblies/pom.xml
+++ b/examples/assemblies/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/bookmark-em/pom.xml b/examples/bookmark-em/pom.xml
index d2aeec0..853e732 100644
--- a/examples/bookmark-em/pom.xml
+++ b/examples/bookmark-em/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/bookmark/pom.xml b/examples/bookmark/pom.xml
index 7db8bdb..173c3d3 100644
--- a/examples/bookmark/pom.xml
+++ b/examples/bookmark/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/bookstore-webapp/pom.xml b/examples/bookstore-webapp/pom.xml
index 9a9df87..220a6f9 100644
--- a/examples/bookstore-webapp/pom.xml
+++ b/examples/bookstore-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
diff --git a/examples/cdi-webapp/pom.xml b/examples/cdi-webapp/pom.xml
index aa597e1..f84bd16 100644
--- a/examples/cdi-webapp/pom.xml
+++ b/examples/cdi-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/clipboard-programmatic/pom.xml b/examples/clipboard-programmatic/pom.xml
index b105240..5dcaddb 100644
--- a/examples/clipboard-programmatic/pom.xml
+++ b/examples/clipboard-programmatic/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/clipboard/pom.xml b/examples/clipboard/pom.xml
index 1b02500..67ced27 100644
--- a/examples/clipboard/pom.xml
+++ b/examples/clipboard/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/configured-client/pom.xml b/examples/configured-client/pom.xml
index 99df9fe..443a713 100644
--- a/examples/configured-client/pom.xml
+++ b/examples/configured-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -56,8 +56,32 @@
<groupId>org.eclipse.microprofile.config</groupId>
<artifactId>microprofile-config-api</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.reactivestreams</groupId>
+ <artifactId>reactive-streams</artifactId>
+ </exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.reactivestreams</groupId>
+ <artifactId>reactive-streams</artifactId>
+ <version>1.0.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
<!-- Instead of helidon-microprofile-config, smallrye-config can be used -->
<!-- <dependency>-->
diff --git a/examples/declarative-linking/pom.xml b/examples/declarative-linking/pom.xml
index d9d1329..ded117e 100644
--- a/examples/declarative-linking/pom.xml
+++ b/examples/declarative-linking/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -50,8 +50,8 @@
</dependency>
<dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>jakarta.el</artifactId>
+ <groupId>org.glassfish.expressly</groupId>
+ <artifactId>expressly</artifactId>
</dependency>
<dependency>
diff --git a/examples/entity-filtering-security/pom.xml b/examples/entity-filtering-security/pom.xml
index 1a93a33..e6740b2 100644
--- a/examples/entity-filtering-security/pom.xml
+++ b/examples/entity-filtering-security/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/entity-filtering-selectable/pom.xml b/examples/entity-filtering-selectable/pom.xml
index 8d00104..7291abb 100644
--- a/examples/entity-filtering-selectable/pom.xml
+++ b/examples/entity-filtering-selectable/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/entity-filtering/pom.xml b/examples/entity-filtering/pom.xml
index 38bf12f..359bd51 100644
--- a/examples/entity-filtering/pom.xml
+++ b/examples/entity-filtering/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/exception-mapping/pom.xml b/examples/exception-mapping/pom.xml
index 4966661..8fa1804 100644
--- a/examples/exception-mapping/pom.xml
+++ b/examples/exception-mapping/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/extended-wadl-webapp/README.MD b/examples/extended-wadl-webapp/README.MD
index d7a59d1..6c4f676 100644
--- a/examples/extended-wadl-webapp/README.MD
+++ b/examples/extended-wadl-webapp/README.MD
@@ -15,9 +15,6 @@
Contents
--------
-The description of what's done here you'll find in the [jersey 1
-wiki](https://wikis.oracle.com/display/Jersey/HowToConfigureExtendedWADL).
-
The difference in configuration against jersey 1.x is in property
configuring the custom WadlGeneratorConfig. Instead of property key
'com.sun.jersey.config.property.WadlGeneratorConfig' use the property
@@ -48,6 +45,8 @@
instructions at [the module README file](../../README.html) in order to
deploy the example.
+NOTE: the example must be run with a JDK prior to JDK 13 otherwise javadoc plugin won't work properly.
+
Otherwise, you can run the example using embedded GlassFish as follows:
You can run the example using Grizzly as follows:
diff --git a/examples/extended-wadl-webapp/pom.xml b/examples/extended-wadl-webapp/pom.xml
index 44e2161..fce24b1 100644
--- a/examples/extended-wadl-webapp/pom.xml
+++ b/examples/extended-wadl-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -108,7 +108,7 @@
<!-- logging -->
<dependency>
<groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
+ <artifactId>slf4j-reload4j</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
@@ -149,7 +149,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
- <version>2.5.0</version>
+ <version>3.2.0</version>
<executions>
<execution>
<id>xjc</id>
@@ -289,6 +289,57 @@
<profiles>
<profile>
+ <id>javadocAndTestsSkipJDK13</id>
+ <activation>
+ <jdk>[13,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <echo>****************************************************</echo>
+ <echo>****THIS EXAMPLE WORKS ONLY ON JDKs PRIOR to 13!****</echo>
+ <echo>********CURRENT JDK IS NOT SUPPORTED!***************</echo>
+ <echo>****************************************************</echo>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.14.0</version>
+ <configuration>
+ <verbose>false</verbose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
<id>pre-release</id>
<build>
<plugins>
diff --git a/examples/freemarker-webapp/pom.xml b/examples/freemarker-webapp/pom.xml
index 9a48724..a5c09ac 100644
--- a/examples/freemarker-webapp/pom.xml
+++ b/examples/freemarker-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/groovy/pom.xml b/examples/groovy/pom.xml
index fcb5f2d..c16feed 100644
--- a/examples/groovy/pom.xml
+++ b/examples/groovy/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -42,6 +42,30 @@
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-commons</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
@@ -62,7 +86,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
- <version>5.8.2</version>
+ <version>${junit5.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -113,10 +137,12 @@
<goal>removeTestStubs</goal>
<goal>groovydoc</goal>
</goals>
+ <configuration>
+ <targetBytecode>11</targetBytecode>
+ </configuration>
</execution>
</executions>
</plugin>
-
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
@@ -140,7 +166,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
- <version>3.0.0</version>
+ <version>${buildhelper.mvn.plugin.version}</version>
<executions>
<execution>
<id>3</id>
diff --git a/examples/helloworld-benchmark/pom.xml b/examples/helloworld-benchmark/pom.xml
index 1c4ff36..484425d 100644
--- a/examples/helloworld-benchmark/pom.xml
+++ b/examples/helloworld-benchmark/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-cdi2-se/pom.xml b/examples/helloworld-cdi2-se/pom.xml
index ffdc694..2ce6028 100644
--- a/examples/helloworld-cdi2-se/pom.xml
+++ b/examples/helloworld-cdi2-se/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-netty/pom.xml b/examples/helloworld-netty/pom.xml
index 2d93501..356b250 100644
--- a/examples/helloworld-netty/pom.xml
+++ b/examples/helloworld-netty/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-programmatic/pom.xml b/examples/helloworld-programmatic/pom.xml
index 4b9800a..e599d69 100644
--- a/examples/helloworld-programmatic/pom.xml
+++ b/examples/helloworld-programmatic/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-pure-jax-rs/pom.xml b/examples/helloworld-pure-jax-rs/pom.xml
index 4cf9d86..a57ae55 100644
--- a/examples/helloworld-pure-jax-rs/pom.xml
+++ b/examples/helloworld-pure-jax-rs/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-spring-annotations/pom.xml b/examples/helloworld-spring-annotations/pom.xml
index a860c3b..31a7e88 100644
--- a/examples/helloworld-spring-annotations/pom.xml
+++ b/examples/helloworld-spring-annotations/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -73,7 +73,6 @@
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
diff --git a/examples/helloworld-spring-webapp/pom.xml b/examples/helloworld-spring-webapp/pom.xml
index 9c5b918..4b4937e 100644
--- a/examples/helloworld-spring-webapp/pom.xml
+++ b/examples/helloworld-spring-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -55,6 +55,12 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>io.micrometer</groupId>
+ <artifactId>micrometer-observation</artifactId>
+ </exclusion>
+ </exclusions>
<version>${spring6.version}</version>
</dependency>
<dependency>
@@ -87,7 +93,7 @@
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.2</version>
+ <version>${commons.logging.version}</version>
<exclusions>
<exclusion>
<groupId>jakarta.servlet</groupId>
diff --git a/examples/helloworld-webapp/pom.xml b/examples/helloworld-webapp/pom.xml
index 1a6e33e..979ad14 100644
--- a/examples/helloworld-webapp/pom.xml
+++ b/examples/helloworld-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld-weld/pom.xml b/examples/helloworld-weld/pom.xml
index 173f831..525986c 100644
--- a/examples/helloworld-weld/pom.xml
+++ b/examples/helloworld-weld/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml
index dbce15d..56708f7 100644
--- a/examples/helloworld/pom.xml
+++ b/examples/helloworld/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/http-patch/pom.xml b/examples/http-patch/pom.xml
index 5a33c71..80db3f3 100644
--- a/examples/http-patch/pom.xml
+++ b/examples/http-patch/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -49,9 +49,22 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
diff --git a/examples/http-trace/pom.xml b/examples/http-trace/pom.xml
index 094ee32..2132d42 100644
--- a/examples/http-trace/pom.xml
+++ b/examples/http-trace/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/https-clientserver-grizzly/pom.xml b/examples/https-clientserver-grizzly/pom.xml
index c746082..ece4643 100644
--- a/examples/https-clientserver-grizzly/pom.xml
+++ b/examples/https-clientserver-grizzly/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/https-server-glassfish/pom.xml b/examples/https-server-glassfish/pom.xml
index 45986d9..8075f5d 100644
--- a/examples/https-server-glassfish/pom.xml
+++ b/examples/https-server-glassfish/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/java8-webapp/pom.xml b/examples/java8-webapp/pom.xml
index 6b68484..99584a4 100644
--- a/examples/java8-webapp/pom.xml
+++ b/examples/java8-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/jaxb/pom.xml b/examples/jaxb/pom.xml
index 71a0217..3cca828 100644
--- a/examples/jaxb/pom.xml
+++ b/examples/jaxb/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -41,7 +41,7 @@
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
- <version>4.1.2</version>
+ <version>4.4.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
diff --git a/examples/jaxrs-types-injection/pom.xml b/examples/jaxrs-types-injection/pom.xml
index 0dfa0bd..1c2c80a 100644
--- a/examples/jaxrs-types-injection/pom.xml
+++ b/examples/jaxrs-types-injection/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/jersey-ejb/pom.xml b/examples/jersey-ejb/pom.xml
index 57da3d0..d99f597 100644
--- a/examples/jersey-ejb/pom.xml
+++ b/examples/jersey-ejb/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-binding-webapp/pom.xml b/examples/json-binding-webapp/pom.xml
index 8764047..43fa250 100644
--- a/examples/json-binding-webapp/pom.xml
+++ b/examples/json-binding-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-jackson/pom.xml b/examples/json-jackson/pom.xml
index 65a975d..0c8a048 100644
--- a/examples/json-jackson/pom.xml
+++ b/examples/json-jackson/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-jettison/pom.xml b/examples/json-jettison/pom.xml
index 803e10b..0ce37b9 100644
--- a/examples/json-jettison/pom.xml
+++ b/examples/json-jettison/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-moxy/pom.xml b/examples/json-moxy/pom.xml
index b2013e6..4df878e 100644
--- a/examples/json-moxy/pom.xml
+++ b/examples/json-moxy/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-processing-webapp/pom.xml b/examples/json-processing-webapp/pom.xml
index 50e42ab..7f71dfc 100644
--- a/examples/json-processing-webapp/pom.xml
+++ b/examples/json-processing-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/json-with-padding/pom.xml b/examples/json-with-padding/pom.xml
index 4cc0bd4..bbb310d 100644
--- a/examples/json-with-padding/pom.xml
+++ b/examples/json-with-padding/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/managed-beans-webapp/pom.xml b/examples/managed-beans-webapp/pom.xml
index a5c1ebd..f30f8aa 100644
--- a/examples/managed-beans-webapp/pom.xml
+++ b/examples/managed-beans-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/managed-client-simple-webapp/pom.xml b/examples/managed-client-simple-webapp/pom.xml
index 5e59f48..c151b6a 100644
--- a/examples/managed-client-simple-webapp/pom.xml
+++ b/examples/managed-client-simple-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/managed-client-webapp/pom.xml b/examples/managed-client-webapp/pom.xml
index 2b8d9c3..3b35c8a 100644
--- a/examples/managed-client-webapp/pom.xml
+++ b/examples/managed-client-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/managed-client/pom.xml b/examples/managed-client/pom.xml
index 8a766b4..8b3bb3e 100644
--- a/examples/managed-client/pom.xml
+++ b/examples/managed-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/micrometer/pom.xml b/examples/micrometer/pom.xml
index 6d4c0d5..18ca982 100644
--- a/examples/micrometer/pom.xml
+++ b/examples/micrometer/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/multipart-webapp/pom.xml b/examples/multipart-webapp/pom.xml
index 6350442..d22e8d6 100644
--- a/examples/multipart-webapp/pom.xml
+++ b/examples/multipart-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/oauth-client-twitter/pom.xml b/examples/oauth-client-twitter/pom.xml
index 4541ea1..0e7a847 100644
--- a/examples/oauth-client-twitter/pom.xml
+++ b/examples/oauth-client-twitter/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
index 5d39bde..e0b6f77 100644
--- a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
+++ b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
@@ -17,7 +17,7 @@
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.List;
import java.util.Properties;
@@ -145,7 +145,7 @@
private static void loadSettings() {
InputStream st = null;
try {
- st = Files.newInputStream(Paths.get(PROPERTIES_FILE_NAME));
+ st = Files.newInputStream(Path.of(PROPERTIES_FILE_NAME));
PROPERTIES.load(st);
} catch (final IOException e) {
// ignore
@@ -178,7 +178,7 @@
private static void storeSettings() {
OutputStream st = null;
try {
- st = Files.newOutputStream(Paths.get(PROPERTIES_FILE_NAME));
+ st = Files.newOutputStream(Path.of(PROPERTIES_FILE_NAME));
PROPERTIES.store(st, null);
} catch (final IOException e) {
// ignore
diff --git a/examples/open-tracing/pom.xml b/examples/open-tracing/pom.xml
index a780791..90fb9ca 100644
--- a/examples/open-tracing/pom.xml
+++ b/examples/open-tracing/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -62,6 +62,22 @@
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>io.opentracing</groupId>
+ <artifactId>opentracing-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.opentracing</groupId>
+ <artifactId>opentracing-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </exclusion>
</exclusions>
</dependency>
diff --git a/examples/osgi-helloworld-webapp/additional-bundle/pom.xml b/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
index 9553b68..2393524 100644
--- a/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/additional-bundle/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml b/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
index 40daeaa..458a1cf 100644
--- a/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/alternate-version-bundle/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-helloworld-webapp/functional-test/pom.xml b/examples/osgi-helloworld-webapp/functional-test/pom.xml
index 5014c5e..81ac944 100644
--- a/examples/osgi-helloworld-webapp/functional-test/pom.xml
+++ b/examples/osgi-helloworld-webapp/functional-test/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java b/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
index 404c63d..cfd299d 100644
--- a/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
+++ b/examples/osgi-helloworld-webapp/functional-test/src/test/java/org/glassfish/jersey/examples/helloworld/test/AbstractWebAppTest.java
@@ -14,7 +14,7 @@
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
@@ -228,7 +228,7 @@
try {
- final BufferedReader reader = Files.newBufferedReader(Paths.get(felixPolicy));
+ final BufferedReader reader = Files.newBufferedReader(Path.of(felixPolicy));
String line;
final Set<String> cpiNames = new HashSet<String>();
diff --git a/examples/osgi-helloworld-webapp/lib-bundle/pom.xml b/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
index 243a982..743a5c1 100644
--- a/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/lib-bundle/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-helloworld-webapp/pom.xml b/examples/osgi-helloworld-webapp/pom.xml
index 33cf268..3775e19 100644
--- a/examples/osgi-helloworld-webapp/pom.xml
+++ b/examples/osgi-helloworld-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -25,16 +25,21 @@
<name>jersey-examples-osgi-helloworld-webapp</name>
<packaging>pom</packaging>
- <modules>
- <module>war-bundle</module>
- <module>functional-test</module>
- <module>lib-bundle</module>
- <module>additional-bundle</module>
- <module>alternate-version-bundle</module>
- </modules>
-
<profiles>
<profile>
+ <id>securityOn</id>
+ <activation>
+ <jdk>[11,24)</jdk>
+ </activation>
+ <modules>
+ <module>war-bundle</module>
+ <module>functional-test</module>
+ <module>lib-bundle</module>
+ <module>additional-bundle</module>
+ <module>alternate-version-bundle</module>
+ </modules>
+ </profile>
+ <profile>
<id>pre-release</id>
<build>
<plugins>
diff --git a/examples/osgi-helloworld-webapp/war-bundle/pom.xml b/examples/osgi-helloworld-webapp/war-bundle/pom.xml
index c867b58..790c4ab 100644
--- a/examples/osgi-helloworld-webapp/war-bundle/pom.xml
+++ b/examples/osgi-helloworld-webapp/war-bundle/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-http-service/bundle/pom.xml b/examples/osgi-http-service/bundle/pom.xml
index eed47ac..3e0b865 100644
--- a/examples/osgi-http-service/bundle/pom.xml
+++ b/examples/osgi-http-service/bundle/pom.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 Distribution License v. 1.0, which is available at
diff --git a/examples/osgi-http-service/functional-test/pom.xml b/examples/osgi-http-service/functional-test/pom.xml
index ccc2999..6e74fc8 100644
--- a/examples/osgi-http-service/functional-test/pom.xml
+++ b/examples/osgi-http-service/functional-test/pom.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 Distribution License v. 1.0, which is available at
@@ -144,8 +144,8 @@
<!-- Logging dependencies-->
<dependency>
<groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>1.6.4</version>
+ <artifactId>slf4j-reload4j</artifactId>
+ <version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
diff --git a/examples/osgi-http-service/pom.xml b/examples/osgi-http-service/pom.xml
index e560c3b..fa1bd88 100644
--- a/examples/osgi-http-service/pom.xml
+++ b/examples/osgi-http-service/pom.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 Distribution License v. 1.0, which is available at
diff --git a/examples/pom.xml b/examples/pom.xml
index 738a2c2..8e2fa59 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -183,7 +183,7 @@
<plugin>
<groupId>org.commonjava.maven.plugins</groupId>
<artifactId>directory-maven-plugin</artifactId>
- <version>0.3.1</version>
+ <version>1.0</version>
<executions>
<execution>
<id>directories</id>
diff --git a/examples/reload/pom.xml b/examples/reload/pom.xml
index 789ccd0..041f1b2 100644
--- a/examples/reload/pom.xml
+++ b/examples/reload/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
index 8e922b7..e28fe2d 100644
--- a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
+++ b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/App.java
@@ -18,7 +18,7 @@
import java.nio.file.Files;
import java.nio.file.FileSystems;
import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
@@ -72,10 +72,10 @@
try {
watcher = FileSystems.getDefault().newWatchService();
- Path srcDir = Paths.get("src/main/java/org/glassfish/jersey/examples/reload");
+ Path srcDir = Path.of("src/main/java/org/glassfish/jersey/examples/reload");
registerWatcher(watcher, srcDir);
- Path configFilePath = Paths.get(".");
+ Path configFilePath = Path.of(".");
registerWatcher(watcher, configFilePath);
} catch (IOException e) {
diff --git a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
index 2a789ff..5c2b57c 100644
--- a/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
+++ b/examples/reload/src/main/java/org/glassfish/jersey/examples/reload/compiler/JavaFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -14,7 +14,7 @@
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import javax.tools.SimpleJavaFileObject;
@@ -47,7 +47,7 @@
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
String filePath = path + File.separator + className.replace('.', '/') + Kind.SOURCE.extension;
- final byte[] bytes = Files.readAllBytes(Paths.get(filePath));
+ final byte[] bytes = Files.readAllBytes(Path.of(filePath));
return new String(bytes);
}
diff --git a/examples/rest31-sebootstrap-multipart/pom.xml b/examples/rest31-sebootstrap-multipart/pom.xml
index 5d6dae4..16304cf 100644
--- a/examples/rest31-sebootstrap-multipart/pom.xml
+++ b/examples/rest31-sebootstrap-multipart/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/rx-client-webapp/pom.xml b/examples/rx-client-webapp/pom.xml
index 94fa73a..d96ab76 100644
--- a/examples/rx-client-webapp/pom.xml
+++ b/examples/rx-client-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-async-managed/pom.xml b/examples/server-async-managed/pom.xml
index 9350e11..32c11a8 100644
--- a/examples/server-async-managed/pom.xml
+++ b/examples/server-async-managed/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-async-standalone/client/pom.xml b/examples/server-async-standalone/client/pom.xml
index 9085cc1..2383ee5 100644
--- a/examples/server-async-standalone/client/pom.xml
+++ b/examples/server-async-standalone/client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-async-standalone/pom.xml b/examples/server-async-standalone/pom.xml
index 399782e..c9aeb07 100644
--- a/examples/server-async-standalone/pom.xml
+++ b/examples/server-async-standalone/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-async-standalone/webapp/pom.xml b/examples/server-async-standalone/webapp/pom.xml
index 551c9ac..63defcf 100644
--- a/examples/server-async-standalone/webapp/pom.xml
+++ b/examples/server-async-standalone/webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-async/pom.xml b/examples/server-async/pom.xml
index d1150ee..24c3087 100644
--- a/examples/server-async/pom.xml
+++ b/examples/server-async/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-sent-events-jaxrs/pom.xml b/examples/server-sent-events-jaxrs/pom.xml
index 19827bd..cd6b511 100644
--- a/examples/server-sent-events-jaxrs/pom.xml
+++ b/examples/server-sent-events-jaxrs/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/server-sent-events-jersey/pom.xml b/examples/server-sent-events-jersey/pom.xml
index d7076bb..7b33a28 100644
--- a/examples/server-sent-events-jersey/pom.xml
+++ b/examples/server-sent-events-jersey/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/servlet3-webapp/pom.xml b/examples/servlet3-webapp/pom.xml
index 4fc1811..0b0d588 100644
--- a/examples/servlet3-webapp/pom.xml
+++ b/examples/servlet3-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -112,6 +112,15 @@
<profiles>
<profile>
+ <id>jdk8_tests</id>
+ <activation>
+ <jdk>1.8</jdk>
+ </activation>
+ <properties>
+ <junit5.version>${junit5.jdk8.version}</junit5.version>
+ </properties>
+ </profile>
+ <profile>
<id>pre-release</id>
<build>
<plugins>
diff --git a/examples/simple-console/pom.xml b/examples/simple-console/pom.xml
index 2b4a56f..8482b16 100644
--- a/examples/simple-console/pom.xml
+++ b/examples/simple-console/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/sse-item-store-jaxrs-webapp/pom.xml b/examples/sse-item-store-jaxrs-webapp/pom.xml
index 793d173..99f18aa 100644
--- a/examples/sse-item-store-jaxrs-webapp/pom.xml
+++ b/examples/sse-item-store-jaxrs-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/sse-item-store-jersey-webapp/pom.xml b/examples/sse-item-store-jersey-webapp/pom.xml
index ca3fa79..7c99e82 100644
--- a/examples/sse-item-store-jersey-webapp/pom.xml
+++ b/examples/sse-item-store-jersey-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/sse-twitter-aggregator/pom.xml b/examples/sse-twitter-aggregator/pom.xml
index 815fc66..60c4f26 100644
--- a/examples/sse-twitter-aggregator/pom.xml
+++ b/examples/sse-twitter-aggregator/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java b/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
index a3e6788..ebde366 100644
--- a/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
+++ b/examples/sse-twitter-aggregator/src/main/java/org/glassfish/jersey/examples/aggregator/App.java
@@ -13,7 +13,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
@@ -144,7 +144,7 @@
InputStream st = null;
try {
String homeDir = System.getProperty("user.home");
- st = Files.newInputStream(Paths.get(homeDir, TWITTER_PROPERTIES_FILE_NAME));
+ st = Files.newInputStream(Path.of(homeDir, TWITTER_PROPERTIES_FILE_NAME));
properties.load(st);
} catch (IOException e) {
// ignore
@@ -230,7 +230,7 @@
try {
fileStream = webRootPath == null
? App.class.getResourceAsStream(WEB_ROOT + uri)
- : Files.newInputStream(Paths.get(webRootPath, uri));
+ : Files.newInputStream(Path.of(webRootPath, uri));
} catch (IOException e) {
fileStream = null;
}
diff --git a/examples/system-properties-example/pom.xml b/examples/system-properties-example/pom.xml
index 867f7b1..e34f979 100644
--- a/examples/system-properties-example/pom.xml
+++ b/examples/system-properties-example/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/webapp-example-parent/pom.xml b/examples/webapp-example-parent/pom.xml
index 9da2791..7d67f0c 100644
--- a/examples/webapp-example-parent/pom.xml
+++ b/examples/webapp-example-parent/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/examples/xml-moxy/pom.xml b/examples/xml-moxy/pom.xml
index 8f0b775..87161dc 100644
--- a/examples/xml-moxy/pom.xml
+++ b/examples/xml-moxy/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Distribution License v. 1.0, which is available at
diff --git a/ext/bean-validation/pom.xml b/ext/bean-validation/pom.xml
index ad8dca3..3247430 100644
--- a/ext/bean-validation/pom.xml
+++ b/ext/bean-validation/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2018, 2019 Payara Foundation and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
@@ -141,10 +141,15 @@
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
</dependency>
-
<dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>jakarta.el</artifactId>
+ <groupId>org.glassfish.expressly</groupId>
+ <artifactId>expressly</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>jakarta.el</groupId>
+ <artifactId>jakarta.el-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
diff --git a/ext/bean-validation/src/main/java/module-info.java b/ext/bean-validation/src/main/java/module-info.java
index 9113ddc..a0d312e 100644
--- a/ext/bean-validation/src/main/java/module-info.java
+++ b/ext/bean-validation/src/main/java/module-info.java
@@ -32,6 +32,8 @@
exports org.glassfish.jersey.server.validation;
exports org.glassfish.jersey.server.validation.internal;
+ exports org.glassfish.jersey.server.validation.internal.hibernate;
+ opens org.glassfish.jersey.server.validation;
opens org.glassfish.jersey.server.validation.internal;
opens org.glassfish.jersey.server.validation.internal.hibernate;
}
\ No newline at end of file
diff --git a/ext/cdi/jersey-cdi-rs-inject/pom.xml b/ext/cdi/jersey-cdi-rs-inject/pom.xml
index 551ea1d..bc1f50d 100644
--- a/ext/cdi/jersey-cdi-rs-inject/pom.xml
+++ b/ext/cdi/jersey-cdi-rs-inject/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml b/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
index 7a1b56a..d1b474f 100644
--- a/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
+++ b/ext/cdi/jersey-cdi1x-ban-custom-hk2-binding/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/cdi/jersey-cdi1x-servlet/pom.xml b/ext/cdi/jersey-cdi1x-servlet/pom.xml
index 9ad8b20..24a1d19 100644
--- a/ext/cdi/jersey-cdi1x-servlet/pom.xml
+++ b/ext/cdi/jersey-cdi1x-servlet/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/cdi/jersey-cdi1x-transaction/pom.xml b/ext/cdi/jersey-cdi1x-transaction/pom.xml
index 580ff73..eca2aef 100644
--- a/ext/cdi/jersey-cdi1x-transaction/pom.xml
+++ b/ext/cdi/jersey-cdi1x-transaction/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -65,6 +65,16 @@
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.el</groupId>
+ <artifactId>jakarta.el-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
diff --git a/ext/cdi/jersey-cdi1x-validation/pom.xml b/ext/cdi/jersey-cdi1x-validation/pom.xml
index af7f6f4..b6949f2 100644
--- a/ext/cdi/jersey-cdi1x-validation/pom.xml
+++ b/ext/cdi/jersey-cdi1x-validation/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/cdi/jersey-cdi1x/pom.xml b/ext/cdi/jersey-cdi1x/pom.xml
index a54124c..02912a9 100644
--- a/ext/cdi/jersey-cdi1x/pom.xml
+++ b/ext/cdi/jersey-cdi1x/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
index e41d4c9..a47aced 100644
--- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
+++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
@@ -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.
* Copyright (c) 2018, 2022 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -45,7 +45,6 @@
import jakarta.inject.Singleton;
import jakarta.ws.rs.core.Application;
-
import jakarta.annotation.ManagedBean;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.RequestScoped;
@@ -143,6 +142,8 @@
private volatile Map<Class<?>, Set<Method>> methodsToSkip = new HashMap<>();
private volatile Map<Class<?>, Set<Field>> fieldsToSkip = new HashMap<>();
+ private boolean initialized = false;
+
public CdiComponentProvider() {
customHk2TypesProvider = CdiUtil.lookupService(Hk2CustomBoundTypesProvider.class);
injectionManagerStore = CdiUtil.createHk2InjectionManagerStore();
@@ -154,7 +155,7 @@
this.injectionManager = injectionManager;
this.beanManager = CdiUtil.getBeanManager();
- if (beanManager != null) {
+ if (beanManager != null && !injectionManager.getClass().getSimpleName().equals("NonInjectionManager")) {
// Try to get CdiComponentProvider created by CDI.
final CdiComponentProvider extension = beanManager.getExtension(CdiComponentProvider.class);
@@ -167,18 +168,19 @@
bindHk2ClassAnalyzer();
LOGGER.config(LocalizationMessages.CDI_PROVIDER_INITIALIZED());
+ initialized = true;
}
}
}
@Override
public boolean bind(final Class<?> clazz, final Set<Class<?>> providerContracts) {
- return bind(clazz, providerContracts, ContractProvider.NO_PRIORITY);
+ return initialized && bind(clazz, providerContracts, ContractProvider.NO_PRIORITY);
}
@Override
public boolean bind(Class<?> component, ContractProvider contractProvider) {
- return contractProvider != null
+ return initialized && contractProvider != null
? bind(component, contractProvider.getContracts(), contractProvider.getPriority(component))
: bind(component, Collections.EMPTY_SET);
}
@@ -628,11 +630,8 @@
ClassAnalyzer defaultClassAnalyzer =
injectionManager.getInstance(ClassAnalyzer.class, ClassAnalyzer.DEFAULT_IMPLEMENTATION_NAME);
- int skippedElements = methodsToSkip.size() + fieldsToSkip.size();
-
- ClassAnalyzer customizedClassAnalyzer = skippedElements > 0
- ? new InjecteeSkippingAnalyzer(defaultClassAnalyzer, methodsToSkip, fieldsToSkip, beanManager)
- : defaultClassAnalyzer;
+ ClassAnalyzer customizedClassAnalyzer =
+ new InjecteeSkippingAnalyzer(defaultClassAnalyzer, methodsToSkip, fieldsToSkip, beanManager);
Binder binder = new AbstractBinder() {
@Override
diff --git a/ext/cdi/jersey-weld2-se/pom.xml b/ext/cdi/jersey-weld2-se/pom.xml
index ba3f6b3..2e68812 100644
--- a/ext/cdi/jersey-weld2-se/pom.xml
+++ b/ext/cdi/jersey-weld2-se/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -67,6 +67,18 @@
<groupId>jakarta.interceptor</groupId>
<artifactId>jakarta.interceptor-api</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>jakarta.inject</groupId>
+ <artifactId>jakarta.inject-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.el</groupId>
+ <artifactId>jakarta.el-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
diff --git a/ext/cdi/pom.xml b/ext/cdi/pom.xml
index 7fc99fc..129a0d4 100644
--- a/ext/cdi/pom.xml
+++ b/ext/cdi/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/entity-filtering/pom.xml b/ext/entity-filtering/pom.xml
index 8394fd4..98d85cf 100644
--- a/ext/entity-filtering/pom.xml
+++ b/ext/entity-filtering/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/metainf-services/pom.xml b/ext/metainf-services/pom.xml
index 37f08bf..3a6e9c6 100644
--- a/ext/metainf-services/pom.xml
+++ b/ext/metainf-services/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/micrometer/pom.xml b/ext/micrometer/pom.xml
index e6b5e76..5583c1e 100644
--- a/ext/micrometer/pom.xml
+++ b/ext/micrometer/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java
index 66cdaf7..8b6d9b3 100644
--- a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java
+++ b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.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
@@ -23,6 +23,9 @@
import org.glassfish.jersey.server.ExtendedUriInfo;
import org.glassfish.jersey.server.monitoring.RequestEvent;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+
/**
* Factory methods for {@link KeyValue KeyValues} associated with a request-response
* exchange that is handled by Jersey server.
@@ -38,6 +41,9 @@
private static final KeyValue URI_ROOT = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("root");
+ private static final KeyValue URI_UNKNOWN = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
+ .withValue("UNKNOWN");
+
private static final KeyValue EXCEPTION_NONE = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.EXCEPTION
.withValue("None");
@@ -82,17 +88,30 @@
* @return the uri KeyValue derived from the request event
*/
static KeyValue uri(RequestEvent event) {
- ContainerResponse response = event.getContainerResponse();
- if (response != null) {
- int status = response.getStatus();
+ int status = 0;
+ if (event.getContainerResponse() != null) {
+ status = event.getContainerResponse().getStatus();
+ } else if (WebApplicationException.class.isInstance(event.getException())) {
+ Response webAppResponse = ((WebApplicationException) event.getException()).getResponse();
+ if (webAppResponse != null) {
+ status = webAppResponse.getStatus();
+ }
+ }
+ if (status != 0) {
if (JerseyTags.isRedirection(status) && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_REDIRECTION;
}
if (status == 404 && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_NOT_FOUND;
}
+ if (status >= 500 && status <= 599) {
+ return STATUS_SERVER_ERROR;
+ }
}
String matchingPattern = JerseyTags.getMatchingPattern(event);
+ if (matchingPattern == null) {
+ return URI_UNKNOWN;
+ }
if (matchingPattern.equals("/")) {
return URI_ROOT;
}
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/main/java/org/glassfish/jersey/micrometer/server/ObservationRequestEventListener.java b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/ObservationRequestEventListener.java
index 953944b..2db4cd1 100644
--- a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/ObservationRequestEventListener.java
+++ b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/ObservationRequestEventListener.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
@@ -65,7 +65,7 @@
switch (event.getType()) {
case ON_EXCEPTION:
- if (!isNotFoundException(event)) {
+ if (!isClientError(event) || observations.get(containerRequest) != null) {
break;
}
startObservation(event);
@@ -102,13 +102,14 @@
observations.put(event.getContainerRequest(), new ObservationScopeAndContext(scope, jerseyContext));
}
- 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 static class ObservationScopeAndContext {
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/exception/JerseyKeyValuesTest.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java
new file mode 100644
index 0000000..99bad31
--- /dev/null
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.micrometer.server.exception;
+
+import io.micrometer.common.KeyValue;
+import io.micrometer.common.KeyValues;
+import org.glassfish.jersey.micrometer.server.DefaultJerseyObservationConvention;
+import org.glassfish.jersey.micrometer.server.JerseyContext;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+import org.glassfish.jersey.server.internal.monitoring.RequestEventImpl;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.NotFoundException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.Optional;
+
+public class JerseyKeyValuesTest {
+ @Test
+ public void testOnException() {
+ ExtendedUriInfo uriInfo = (ExtendedUriInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{ExtendedUriInfo.class},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ switch (method.getName()) {
+ case "getMatchedTemplates":
+ return Collections.emptyList();
+ }
+ return null;
+ }
+ });
+ RequestEventImpl event = new RequestEventImpl.Builder()
+ .setExtendedUriInfo(uriInfo)
+ .setException(new NotFoundException(), RequestEvent.ExceptionCause.ORIGINAL)
+ .build(RequestEvent.Type.ON_EXCEPTION);
+ JerseyContext context = new JerseyContext(event);
+ DefaultJerseyObservationConvention convention = new DefaultJerseyObservationConvention("Test-Metric");
+ KeyValues values = convention.getLowCardinalityKeyValues(context);
+ Optional<KeyValue> kv = values.stream().filter(p -> p.getValue().equals("NOT_FOUND")).findFirst();
+ MatcherAssert.assertThat(kv.isPresent(), Matchers.equalTo(true));
+ }
+}
diff --git a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/observation/AbstractObservationRequestEventListenerTest.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/observation/AbstractObservationRequestEventListenerTest.java
index 0ae7ab6..d46e855 100644
--- a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/observation/AbstractObservationRequestEventListenerTest.java
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/observation/AbstractObservationRequestEventListenerTest.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 java.util.logging.Logger;
import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.MediaType;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
@@ -38,6 +39,7 @@
import io.micrometer.tracing.test.simple.SpansAssert;
import org.glassfish.jersey.micrometer.server.ObservationApplicationEventListener;
import org.glassfish.jersey.micrometer.server.ObservationRequestEventListener;
+import org.glassfish.jersey.micrometer.server.mapper.ResourceGoneExceptionMapper;
import org.glassfish.jersey.micrometer.server.resources.TestResource;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
@@ -85,6 +87,7 @@
final ResourceConfig config = new ResourceConfig();
config.register(listener);
config.register(TestResource.class);
+ config.register(ResourceGoneExceptionMapper.class);
return config;
}
@@ -131,6 +134,53 @@
.hasTag("outcome", "SUCCESS")
.hasTag("status", "200")
.hasTag("uri", "/sub-resource/sub-hello/{name}");
+ assertThat(observationRegistry.getCurrentObservation()).isNull();
+ }
+
+ @Test
+ void errorResourcesAreTimed() {
+ try {
+ target("throws-exception").request().get();
+ }
+ catch (Exception ignored) {
+ }
+ try {
+ target("throws-webapplication-exception").request().get();
+ }
+ catch (Exception ignored) {
+ }
+ try {
+ target("throws-mappable-exception").request().get();
+ }
+ 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"))
+ .timer()
+ .count()).isEqualTo(1);
+
+ assertThat(registry.get(METRIC_NAME)
+ .tags(tagsFrom("/throws-webapplication-exception", "401", "CLIENT_ERROR", "NotAuthorizedException"))
+ .timer()
+ .count()).isEqualTo(1);
+
+ assertThat(registry.get(METRIC_NAME)
+ .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);
+
+ assertThat(observationRegistry.getCurrentObservation()).isNull();
}
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/microprofile/mp-config/pom.xml b/ext/microprofile/mp-config/pom.xml
index 7461b17..7c9463c 100644
--- a/ext/microprofile/mp-config/pom.xml
+++ b/ext/microprofile/mp-config/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -30,7 +30,11 @@
<artifactId>jersey-mp-config</artifactId>
<properties>
- <surefire.coverage.argline>--add-modules=ALL-MODULE-PATH</surefire.coverage.argline>
+ <surefire.coverage.argline>
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
</properties>
<dependencies>
diff --git a/ext/microprofile/mp-rest-client/pom.xml b/ext/microprofile/mp-rest-client/pom.xml
index 18ed04f..948501a 100644
--- a/ext/microprofile/mp-rest-client/pom.xml
+++ b/ext/microprofile/mp-rest-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
index 9f8ebd1..08eaf0a 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -379,6 +379,11 @@
if (!headersContext.isPresent()) {
for (InboundHeadersProvider provider : interfaceModel.context().inboundHeadersProviders()) {
inbound.putAll(provider.inboundHeaders());
+ if (RestClientBuilderImpl.DefaultInboundHeaderProvider.class.isInstance(provider)) {
+ MultivaluedMap<String, String> fromFactory =
+ ((ClientHeadersFactory) provider).update(inbound, customHeaders);
+ customHeaders.putAll(fromFactory);
+ }
}
}
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
index 1e81f52..687d228 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021 Payara Foundation and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -33,7 +33,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.logging.Level;
@@ -48,8 +47,11 @@
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.RuntimeDelegate;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
@@ -57,6 +59,7 @@
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptor;
import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
+import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;
import org.eclipse.microprofile.rest.client.ext.QueryParamStyle;
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
import org.eclipse.microprofile.rest.client.spi.RestClientListener;
@@ -66,10 +69,13 @@
import org.glassfish.jersey.client.Initializable;
import org.glassfish.jersey.client.spi.ConnectorProvider;
import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil;
+import org.glassfish.jersey.innate.VirtualThreadUtil;
+import org.glassfish.jersey.internal.RuntimeDelegateDecorator;
import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.message.internal.HeaderUtils;
import org.glassfish.jersey.uri.JerseyQueryParamStyle;
/**
@@ -92,6 +98,7 @@
private final List<AsyncInvocationInterceptorFactoryPriorityWrapper> asyncInterceptorFactories;
private final Config config;
private final ConfigWrapper configWrapper;
+ private final DefaultInboundHeaderProvider defaultInboundHeaderProvider;
private URI uri;
private ClientBuilder clientBuilder;
private Supplier<ExecutorService> executorService;
@@ -111,7 +118,10 @@
asyncInterceptorFactories = new ArrayList<>();
config = ConfigProvider.getConfig();
configWrapper = new ConfigWrapper(clientBuilder.getConfiguration());
- executorService = Executors::newCachedThreadPool;
+ executorService = () -> VirtualThreadUtil.withConfig(configWrapper).newCachedThreadPool();
+
+ defaultInboundHeaderProvider = new DefaultInboundHeaderProvider(clientBuilder.getConfiguration());
+ inboundHeaderProviders.add(defaultInboundHeaderProvider);
}
@Override
@@ -491,6 +501,11 @@
return this;
}
+ public RestClientBuilder header(String s, Object o) {
+ defaultInboundHeaderProvider.header(s, o);
+ return this;
+ }
+
private static class InjectionManagerExposer implements Feature {
InjectionManager injectionManager;
@@ -529,4 +544,34 @@
}
}
+ /* package*/ static class DefaultInboundHeaderProvider implements InboundHeadersProvider, ClientHeadersFactory {
+ private final RuntimeDelegate delegate;
+ private final MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
+
+ private DefaultInboundHeaderProvider(Configuration configuration) {
+ this.delegate = RuntimeDelegateDecorator.configured(configuration);
+ }
+
+ private void header(String key, Object value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ headers.add(key, HeaderUtils.asString(value, delegate));
+ }
+
+ @Override
+ public Map<String, List<String>> inboundHeaders() {
+ return headers;
+ }
+
+ @Override
+ public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,
+ MultivaluedMap<String, String> clientOutgoingHeaders) {
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putAll(incomingHeaders);
+ clientOutgoingHeaders.forEach((k, v) -> map.addAll(k, v));
+ return map;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
index d583419..0dff2b1 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,7 +24,7 @@
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.security.AccessController;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -161,6 +161,13 @@
@Override
public void destroy(Object instance, CreationalContext<Object> creationalContext) {
+ if (AutoCloseable.class.isInstance(instance)) {
+ try {
+ ((AutoCloseable) instance).close();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
}
@Override
@@ -350,7 +357,7 @@
}
return result;
} else if (location.startsWith(FILE_LOCATION)) {
- return Files.newInputStream(Paths.get(URI.create(location)));
+ return Files.newInputStream(Path.of(URI.create(location)));
} else {
throw new IllegalStateException("Location of keystore must start with either classpath: or file:, but is: "
+ location
diff --git a/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties b/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
index 3afc639..5a3b074 100644
--- a/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
+++ b/ext/microprofile/mp-rest-client/src/main/resources/org/glassfish/jersey/microprofile/restclient/internal/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,3 +16,4 @@
err.invalid.proxy.uri=Invalid proxy URI: {0}.
err.invalid.proxy.port=Invalid proxy port: {0}.
+err.null.header=Header cannot be null.
diff --git a/ext/microprofile/pom.xml b/ext/microprofile/pom.xml
index 826ad7f..8037dec 100644
--- a/ext/microprofile/pom.xml
+++ b/ext/microprofile/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc-bean-validation/pom.xml b/ext/mvc-bean-validation/pom.xml
index f6dec8f..9ee18d9 100644
--- a/ext/mvc-bean-validation/pom.xml
+++ b/ext/mvc-bean-validation/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc-freemarker/pom.xml b/ext/mvc-freemarker/pom.xml
index cdb3dc8..3fa9f9f 100644
--- a/ext/mvc-freemarker/pom.xml
+++ b/ext/mvc-freemarker/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc-jsp/pom.xml b/ext/mvc-jsp/pom.xml
index bc6942f..a412253 100644
--- a/ext/mvc-jsp/pom.xml
+++ b/ext/mvc-jsp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc-mustache/pom.xml b/ext/mvc-mustache/pom.xml
index dd4bd53..2b32c8b 100644
--- a/ext/mvc-mustache/pom.xml
+++ b/ext/mvc-mustache/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc-thymeleaf/pom.xml b/ext/mvc-thymeleaf/pom.xml
new file mode 100644
index 0000000..bae0fd2
--- /dev/null
+++ b/ext/mvc-thymeleaf/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available 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.5.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/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.java
similarity index 71%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.java
index 0fdbe9d..aba4aac 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/ThymeleafConfigurationFactory.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
@@ -14,7 +14,10 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
- */
-package org.glassfish.jersey.test.jetty11.http2;
+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/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.java
similarity index 77%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.java
index 0fdbe9d..d8cd7ae 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/ext/mvc-thymeleaf/src/main/java/org/glassfish/jersey/server/mvc/thymeleaf/package-info.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
@@ -14,7 +14,4 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
- */
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.server.mvc.thymeleaf;
diff --git a/ext/mvc/pom.xml b/ext/mvc/pom.xml
index 8fc1613..628530f 100644
--- a/ext/mvc/pom.xml
+++ b/ext/mvc/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java b/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
index ed0c590..b375afe 100644
--- a/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
+++ b/ext/mvc/src/main/java/org/glassfish/jersey/server/mvc/spi/AbstractTemplateProcessor.java
@@ -16,13 +16,13 @@
package org.glassfish.jersey.server.mvc.spi;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -182,7 +182,7 @@
// File-system path.
if (reader == null) {
try {
- reader = new InputStreamReader(Files.newInputStream(new File(template).toPath()), encoding);
+ reader = new InputStreamReader(Files.newInputStream(Path.of(template)), encoding);
} catch (final IOException ioe) {
// NOOP.
}
diff --git a/ext/pom.xml b/ext/pom.xml
index 3a78913..59e1c68 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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/proxy-client/pom.xml b/ext/proxy-client/pom.xml
index df5ae88..a623b2f 100644
--- a/ext/proxy-client/pom.xml
+++ b/ext/proxy-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java b/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
index 6bca315..aeffb03 100644
--- a/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
+++ b/ext/proxy-client/src/main/java/org/glassfish/jersey/client/proxy/RequestParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,6 +35,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -43,6 +44,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* Collector to retrieve parameters for setting up the HTTP request sent in the invoke method of WebResourceFactory
@@ -145,7 +147,7 @@
throws IllegalAccessException, IntrospectionException, InvocationTargetException {
Class<?> beanClass = beanParam.getClass();
List<Field> fields = new ArrayList<>();
- getAllFields(fields, beanClass);
+ getAllNonStaticFields(fields, beanClass);
for (final Field field : fields) {
Object value = null;
@@ -156,7 +158,7 @@
anns.put(ann.annotationType(), ann);
}
- if (hasAnyParamAnnotation(anns)) {
+ if (field.canAccess(beanParam) && hasAnyParamAnnotation(anns)) {
value = field.get(beanParam);
} else {
// get getter annotations if there are no field annotations
@@ -178,11 +180,15 @@
}
}
- private List<Field> getAllFields(List<Field> fields, Class<?> type) {
- fields.addAll(Arrays.asList(type.getDeclaredFields()));
+ private List<Field> getAllNonStaticFields(List<Field> fields, Class<?> type) {
+
+ List<Field> nonStaticFields = Arrays.stream(type.getDeclaredFields())
+ .filter(field -> !Modifier.isStatic(field.getModifiers()))
+ .collect(Collectors.toList());
+ fields.addAll(nonStaticFields);
if (type.getSuperclass() != null) {
- getAllFields(fields, type.getSuperclass());
+ getAllNonStaticFields(fields, type.getSuperclass());
}
return fields;
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java
new file mode 100644
index 0000000..06250c7
--- /dev/null
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyBeanParamWithPrivateField.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.proxy;
+
+
+import jakarta.ws.rs.QueryParam;
+
+/**
+ * @author Divyansh Shekhar Gaur
+ */
+public class MyBeanParamWithPrivateField {
+
+ @QueryParam("privateFieldParam")
+ private String privateFieldParam;
+
+ private static String privateStaticField;
+
+ static String staticField;
+
+ public MyBeanParamWithPrivateField() {}
+
+ public String getPrivateFieldParam() {
+ return privateFieldParam;
+ }
+
+ public void setPrivateFieldParam(String privateFieldParam) {
+ this.privateFieldParam = privateFieldParam;
+ }
+
+ public static String getPrivateStaticField() {
+ return privateStaticField;
+ }
+
+ public static void setPrivateStaticField(String privateStaticField) {
+ MyBeanParamWithPrivateField.privateStaticField = privateStaticField;
+ }
+
+ public static String getStaticField() {
+ return staticField;
+ }
+
+ public static void setStaticField(String staticField) {
+ MyBeanParamWithPrivateField.staticField = staticField;
+ }
+}
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
index 1b49f50..81fd9b4 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParam.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -54,6 +54,11 @@
}
@Override
+ public String echoPrivateField(@BeanParam MyBeanParamWithPrivateField bean) {
+ return bean.getPrivateFieldParam();
+ }
+
+ @Override
public String echo(MyBeanParam bean) {
return ("HEADER=" + bean.getHeaderParam() + ",PATH=" + bean.getPathParam() + ",FORM="
+ bean.getFormParam1() + "," + bean.getFormParam2() + ",QUERY=" + bean.getQueryParam()
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
index 5e73615..f4b7f5c 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/MyResourceWithBeanParamIfc.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -61,6 +61,12 @@
@POST
@Consumes("application/x-www-form-urlencoded")
+ @Path("getPrivateField")
+ @Produces("text/plain")
+ public String echoPrivateField(@BeanParam MyBeanParamWithPrivateField bean);
+
+ @POST
+ @Consumes("application/x-www-form-urlencoded")
@Path("all/{pathParam}")
@Produces("text/plain")
public String echo(@BeanParam MyBeanParam bean);
diff --git a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
index d9b361a..6819e0c 100644
--- a/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
+++ b/ext/proxy-client/src/test/java/org/glassfish/jersey/client/proxy/WebResourceFactoryBeanParamTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -138,4 +138,14 @@
assertEquals("query", response);
}
+
+ @Test
+ public void testBeanParamPrivateFieldQuery() {
+ MyBeanParamWithPrivateField myGetBeanParam = new MyBeanParamWithPrivateField();
+ myGetBeanParam.setPrivateFieldParam("query");
+
+ String response = resourceWithBeanParam.echoPrivateField(myGetBeanParam);
+
+ assertEquals("query", response);
+ }
}
\ No newline at end of file
diff --git a/ext/rx/pom.xml b/ext/rx/pom.xml
index 0b1c5ed..3d5a1c9 100644
--- a/ext/rx/pom.xml
+++ b/ext/rx/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/rx/rx-client-guava/pom.xml b/ext/rx/rx-client-guava/pom.xml
index 61b9d62..97f6c5e 100644
--- a/ext/rx/rx-client-guava/pom.xml
+++ b/ext/rx/rx-client-guava/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/rx/rx-client-rxjava/pom.xml b/ext/rx/rx-client-rxjava/pom.xml
index 1746317..22aa2fc 100644
--- a/ext/rx/rx-client-rxjava/pom.xml
+++ b/ext/rx/rx-client-rxjava/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/rx/rx-client-rxjava2/pom.xml b/ext/rx/rx-client-rxjava2/pom.xml
index 63347a6..1dafe7a 100644
--- a/ext/rx/rx-client-rxjava2/pom.xml
+++ b/ext/rx/rx-client-rxjava2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/spring6/pom.xml b/ext/spring6/pom.xml
index ea337d7..2d93477 100644
--- a/ext/spring6/pom.xml
+++ b/ext/spring6/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -81,7 +81,6 @@
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.2</version>
<scope>test</scope>
</dependency>
@@ -94,6 +93,22 @@
<groupId>org.ow2.asm</groupId>
<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>
</exclusions>
</dependency>
@@ -114,6 +129,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>jakarta.inject</groupId>
+ <artifactId>jakarta.inject-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
@@ -210,6 +229,23 @@
<profiles>
<profile>
+ <id>HK2_JDK8_dependencyConvergence_skip</id>
+ <activation>
+ <jdk>1.8</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <configuration>
+ <rulesToSkip>dependencyConvergence</rulesToSkip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
<id>SpringExclude</id>
<activation>
<jdk>[1.8,17)</jdk>
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/ext/wadl-doclet/pom.xml b/ext/wadl-doclet/pom.xml
index 1d64afe..8deb34f 100644
--- a/ext/wadl-doclet/pom.xml
+++ b/ext/wadl-doclet/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,8 +35,8 @@
<properties>
<java.sourceDirectory>${project.basedir}/src/main/java</java.sourceDirectory>
- <java8_11.build.outputDirectory>${project.basedir}/target</java8_11.build.outputDirectory>
- <java8_11.sourceDirectory>${project.basedir}/src/main/java8_11</java8_11.sourceDirectory>
+ <java11.build.outputDirectory>${project.basedir}/target</java11.build.outputDirectory>
+ <java11.sourceDirectory>${project.basedir}/src/main/java8_11</java11.sourceDirectory>
<java12.build.outputDirectory>${project.basedir}/target-java12</java12.build.outputDirectory>
<java12.sourceDirectory>${project.basedir}/src/main/java12</java12.sourceDirectory>
</properties>
@@ -44,12 +44,12 @@
<profiles>
<profile>
- <id>jdk1.8_11</id>
+ <id>jdk11</id>
<activation>
- <jdk>[1.8,12)</jdk>
+ <jdk>[11,12)</jdk>
</activation>
<build>
- <directory>${java8_11.build.outputDirectory}</directory>
+ <directory>${java11.build.outputDirectory}</directory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
@@ -63,7 +63,7 @@
<configuration>
<sources>
<source>${java.sourceDirectory}</source>
- <source>${java8_11.sourceDirectory}</source>
+ <source>${java11.sourceDirectory}</source>
</sources>
</configuration>
</execution>
@@ -109,7 +109,7 @@
<!-- ${java12.build.outputDirectory} does not work here -->
<exists>target-java12/classes/org/glassfish/jersey/wadl/doclet/ResourceDoclet.class</exists>
</file>
- <jdk>[1.8,12)</jdk>
+ <jdk>[11,12)</jdk>
</activation>
<build>
<plugins>
@@ -136,7 +136,7 @@
<goal>copy-resources</goal>
</goals>
<configuration>
- <outputDirectory>${java8_11.build.outputDirectory}/classes/META-INF/versions/12</outputDirectory>
+ <outputDirectory>${java11.build.outputDirectory}/classes/META-INF/versions/12</outputDirectory>
<resources>
<resource>
<directory>${java12.build.outputDirectory}/classes</directory>
@@ -155,7 +155,7 @@
<phase>package</phase>
<configuration>
<target>
- <property name="sources-jar" value="${java8_11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+ <property name="sources-jar" value="${java11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
<echo>sources-jar: ${sources-jar}</echo>
<zip destfile="${sources-jar}" update="true">
<zipfileset dir="${java12.sourceDirectory}" prefix="META-INF/versions/12"/>
diff --git a/incubator/cdi-inject-weld/pom.xml b/incubator/cdi-inject-weld/pom.xml
index 91f28cb..07e11fb 100644
--- a/incubator/cdi-inject-weld/pom.xml
+++ b/incubator/cdi-inject-weld/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
index b653b54..a1c5032 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -129,13 +129,7 @@
* CDI does not provide sufficient support for ThreadScoped Supplier
*/
if (binding.getScope() == PerThread.class) {
- BeanManagerImpl manager;
- if (beanManager instanceof BeanManagerProxy) {
- manager = ((BeanManagerProxy) beanManager).unwrap();
- } else {
- manager = (BeanManagerImpl) beanManager;
- }
- abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, manager));
+ abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, beanManagerImpl(beanManager)));
} else {
abd.addBean(new InitializableSupplierInstanceBean<>(runtimeType, binding));
abd.addBean(new InitializableSupplierInstanceBeanBridge<>(runtimeType, binding));
@@ -164,12 +158,18 @@
InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
supplierBean.setInjectionTarget(jit);
- final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager);
-
- abd.addBean(supplierBean);
- abd.addBean(supplierBeanBridge);
-
- return new BindingBeanPair(binding, supplierBean, supplierBeanBridge);
+ /*
+ * CDI does not provide sufficient support for ThreadScoped Supplier
+ */
+ if (binding.getScope() == PerThread.class) {
+ abd.addBean(new SupplierThreadScopeClassBean(runtimeType, binding, supplierBean, beanManagerImpl(beanManager)));
+ return null;
+ } else {
+ final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager);
+ abd.addBean(supplierBean);
+ abd.addBean(supplierBeanBridge);
+ return new BindingBeanPair(binding, supplierBean, supplierBeanBridge);
+ }
}
/**
@@ -258,6 +258,14 @@
return null;
}
+ private static BeanManagerImpl beanManagerImpl(BeanManager beanManager) {
+ if (beanManager instanceof BeanManagerProxy) {
+ return ((BeanManagerProxy) beanManager).unwrap();
+ } else {
+ return (BeanManagerImpl) beanManager;
+ }
+ }
+
private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget,
Bean<T> bean, Collection<InjectionResolver> resolvers) {
BasicInjectionTarget<T> it = (BasicInjectionTarget<T>) injectionTarget;
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
index c5f211e..3415b46 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -111,31 +111,4 @@
ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this);
return factory.create(beanInstance);
}
-
- private static class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> {
-
- private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>();
-
- private final Supplier<T> supplier;
-
- /**
- * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
- *
- * @param supplier provider of the value.
- */
- private ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) {
- super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId);
- this.supplier = supplier;
- }
-
- @Override
- public Object invoke(Object obj, Method method, Object... arguments) throws Throwable {
- Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get());
- return super.invoke(instance, method, arguments);
- }
-
- public void dispose() {
- this.instances.clear();
- }
- }
}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java
new file mode 100644
index 0000000..fe3e8b4
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java
@@ -0,0 +1,114 @@
+/*
+ * 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.weld.internal.bean;
+
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.jboss.weld.bean.proxy.BeanInstance;
+import org.jboss.weld.bean.proxy.ProxyFactory;
+import org.jboss.weld.manager.BeanManagerImpl;
+
+import jakarta.enterprise.context.Dependent;
+import jakarta.enterprise.context.spi.CreationalContext;
+import jakarta.ws.rs.RuntimeType;
+import java.lang.annotation.Annotation;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+
+/**
+ * Creates an implementation of {@link jakarta.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link jakarta.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget} because serves already
+ * created proxy, therefore the create operation just return provided instance without any other contextual operation
+ * (produce, inject, destroy).
+ * <p>
+ * This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and
+ * works through the proxy which serves the correct instance per the given thread.
+ * <p>
+ * Register example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(MyFactoryInjectionSupplier.class)
+ * .to(MyBean.class)
+ * .in(PerThread.class);
+ * }
+ * }
+ * </pre>
+ * Inject example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ */
+class SupplierThreadScopeClassBean extends JerseyBean<Object> {
+ private final LazyValue<ThreadScopeBeanInstance<Object>> beanInstance;
+ private final SupplierClassBinding binding;
+ private final LazyValue<Object> proxy;
+ private final AtomicReference<CreationalContext> creationalContextAtomicReference = new AtomicReference<>();
+
+ SupplierThreadScopeClassBean(RuntimeType runtimeType,
+ SupplierClassBinding binding,
+ SupplierClassBean supplierClassBean,
+ BeanManagerImpl beanManager) {
+ super(runtimeType, binding);
+ this.binding = binding;
+ this.beanInstance = Values.lazy((Value<ThreadScopeBeanInstance<Object>>) () -> {
+ Supplier supplierInstance = supplierClassBean.create(creationalContextAtomicReference.get());
+ ThreadScopeBeanInstance scopeBeanInstance =
+ new ThreadScopeBeanInstance(supplierInstance, this, beanManager.getContextId());
+ return scopeBeanInstance;
+ });
+ this.proxy = Values.lazy((Value<Object>) () -> createClientProxy(beanInstance.get(), beanManager.getContextId()));
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Dependent.class;
+ }
+
+ @Override
+ public Object create(CreationalContext<Object> ctx) {
+ creationalContextAtomicReference.set(ctx);
+ return proxy.get();
+ }
+
+ @Override
+ public void destroy(Object instance, CreationalContext<Object> creationalContext) {
+ if (beanInstance.isInitialized()) {
+ this.beanInstance.get().dispose();
+ }
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return (Class<?>) this.binding.getContracts().iterator().next();
+ }
+
+ private <T> T createClientProxy(BeanInstance beanInstance, String contextId) {
+ ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this);
+ return factory.create(beanInstance);
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java
new file mode 100644
index 0000000..73ac651
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available 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.weld.internal.bean;
+
+import org.jboss.weld.bean.StringBeanIdentifier;
+import org.jboss.weld.bean.proxy.ContextBeanInstance;
+
+import jakarta.enterprise.inject.spi.Bean;
+import jakarta.enterprise.inject.spi.PassivationCapable;
+import java.lang.reflect.Method;
+import java.util.WeakHashMap;
+import java.util.function.Supplier;
+
+/**
+ * {@link org.glassfish.jersey.internal.inject.PerThread} scope bean instance used from
+ * {@link InitializableSupplierThreadScopeBean} and {@link SupplierThreadScopeClassBean}.
+ *
+ * @param <T> Typed of the bean supplied by a {@code Supplier}.
+ */
+class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> {
+
+ private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>();
+
+ private final Supplier<T> supplier;
+
+ /**
+ * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
+ *
+ * @param supplier provider of the value.
+ */
+ ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) {
+ super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId);
+ this.supplier = supplier;
+ }
+
+ @Override
+ public Object invoke(Object obj, Method method, Object... arguments) throws Throwable {
+ Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get());
+ return super.invoke(instance, method, arguments);
+ }
+
+ public void dispose() {
+ this.instances.clear();
+ }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
index 60d48e4..8917bb0 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -347,8 +347,10 @@
}
BindingBeanPair pair = BeanHelper.registerSupplier(
runtimeType, (SupplierClassBinding<?>) binding, abd, injectionResolvers, beanManager);
- for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) {
- supplierClassBindings.add(contract, pair);
+ if (pair != null) {
+ for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) {
+ supplierClassBindings.add(contract, pair);
+ }
}
} else if (InitializableInstanceBinding.class.isAssignableFrom(binding.getClass())) {
if (RuntimeType.SERVER == runtimeType
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
index 85bfe56..9a6d8da 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -30,6 +30,7 @@
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests {@link CachedConstructorAnalyzer}.
@@ -110,7 +111,8 @@
Constructor<BothAnnotatedConstructor> constructor = analyzer.getConstructor();
assertEquals(1, constructor.getParameterCount());
- assertEquals(Integer.class, constructor.getParameterTypes()[0]);
+ Class<?> parameterType = constructor.getParameterTypes()[0];
+ assertTrue(parameterType.equals(String.class) || parameterType.equals(Integer.class));
}
@Test
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
index 68b57d9..14bd268 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,9 +26,11 @@
static final String GREETING = "Ahoj";
+ private String greeting = GREETING + "#" + Thread.currentThread().getName();
+
@Override
public String getGreeting() {
- return GREETING + "#" + Thread.currentThread().getName();
+ return greeting;
}
@Override
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
index b7806c1..97d4a49 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -97,6 +97,13 @@
binder.bindFactory(new ThreadScopeTest.SupplierGreeting2(ThreadScopeTest.EnglishGreeting2.GREETING))
.to(ThreadScopeTest.EnglishGreeting2.class)
.in(PerThread.class);
+
+ //testSupplierClassBindingThreadScopedInSingletonScope
+ binder.bindAsContract(ThreadScopeTest.SingletonObject3.class)
+ .in(Singleton.class);
+ binder.bindFactory(ThreadScopeTest.SupplierGreeting3.class)
+ .to(ThreadScopeTest.Greeting3.class)
+ .in(PerThread.class);
}
//ClientInstanceInjectionTest
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
index 144c333..7c959fe 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,6 +18,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import jakarta.enterprise.context.RequestScoped;
@@ -181,7 +182,7 @@
}
@Test
- public void testThreadScopedInSingletonScope() {
+ public void testThreadScopedInSingletonScope() throws InterruptedException {
// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
// BindingTestHelper.bind(injectionManager, binder -> {
// binder.bindAsContract(SingletonObject.class)
@@ -202,6 +203,52 @@
assertNotNull(greeting2);
assertEquals(greeting1, greeting2);
+
+ final AtomicReference<String> greetingAtomicReference = new AtomicReference<>();
+ Runnable runnable = () ->
+ greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting());
+
+ Thread newThread = new Thread(runnable);
+ newThread.start();
+ newThread.join();
+
+ assertEquals(greeting1.getGreeting(), greeting2.getGreeting());
+ assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get());
+ }
+
+ @Test
+ public void testSupplierClassBindingThreadScopedInSingletonScope() throws InterruptedException {
+// InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+// BindingTestHelper.bind(injectionManager, binder -> {
+// binder.bindAsContract(SingletonObject.class)
+// .in(Singleton.class);
+//
+// binder.bindFactory(SupplierGreeting.class)
+// .to(Greeting.class)
+// .in(PerThread.class);
+// });
+
+ SingletonObject3 instance1 = injectionManager.getInstance(SingletonObject3.class);
+ Greeting3 greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ SingletonObject3 instance2 = injectionManager.getInstance(SingletonObject3.class);
+ Greeting3 greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertEquals(greeting1, greeting2);
+
+ final AtomicReference<String> greetingAtomicReference = new AtomicReference<>();
+ Runnable runnable = () ->
+ greetingAtomicReference.set(injectionManager.getInstance(SingletonObject3.class).getGreeting().getGreeting());
+
+ Thread newThread = new Thread(runnable);
+ newThread.start();
+ newThread.join();
+
+ assertEquals(greeting1.getGreeting(), greeting2.getGreeting());
+ assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get());
}
@RequestScoped
@@ -227,6 +274,17 @@
}
@Singleton
+ public static class SingletonObject3 {
+
+ @Inject
+ Greeting3 greeting;
+
+ public Greeting3 getGreeting() {
+ return greeting;
+ }
+ }
+
+ @Singleton
public static class SingletonObject {
@Inject
@@ -260,6 +318,14 @@
}
@Vetoed
+ static class SupplierGreeting3 implements Supplier<Greeting3> {
+ @Override
+ public Greeting3 get() {
+ return new CzechGreeting3();
+ }
+ }
+
+ @Vetoed
static class SupplierGreeting2 implements Supplier<Greeting2> {
private final String greetingType;
@@ -291,13 +357,33 @@
}
@Vetoed
+ static class CzechGreeting3 implements Greeting3 {
+
+ static final String GREETING = "Ahoj";
+
+ private String greeting = GREETING + "#" + Thread.currentThread().getName();
+
+ @Override
+ public String getGreeting() {
+ return greeting;
+ }
+
+ @Override
+ public String toString() {
+ return "CzechGreeting";
+ }
+ }
+
+ @Vetoed
static class CzechGreeting2 implements Greeting2 {
static final String GREETING = "Ahoj";
+ private String greeting = GREETING + "#" + Thread.currentThread().getName();
+
@Override
public String getGreeting() {
- return GREETING + "#" + Thread.currentThread().getName();
+ return greeting;
}
@Override
@@ -374,9 +460,11 @@
static final String GREETING = "Ahoj";
+ private String greeting = GREETING + "#" + Thread.currentThread().getName();
+
@Override
public String getGreeting() {
- return GREETING + "#" + Thread.currentThread().getName();
+ return greeting;
}
@Override
@@ -386,6 +474,11 @@
}
@FunctionalInterface
+ static interface Greeting3 {
+ String getGreeting();
+ }
+
+ @FunctionalInterface
static interface Greeting2 {
String getGreeting();
}
diff --git a/incubator/declarative-linking/pom.xml b/incubator/declarative-linking/pom.xml
index c8d7a37..77d0ec3 100644
--- a/incubator/declarative-linking/pom.xml
+++ b/incubator/declarative-linking/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -58,9 +58,9 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>jakarta.el</artifactId>
- <scope>provided</scope>
+ <groupId>org.glassfish.expressly</groupId>
+ <artifactId>expressly</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -88,7 +88,7 @@
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
- <version>1.5.0</version>
+ <version>1.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/incubator/gae-integration/pom.xml b/incubator/gae-integration/pom.xml
index 153b5be..ea2d421 100644
--- a/incubator/gae-integration/pom.xml
+++ b/incubator/gae-integration/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/incubator/html-json/pom.xml b/incubator/html-json/pom.xml
index cb4f25a..0bc7fa3 100644
--- a/incubator/html-json/pom.xml
+++ b/incubator/html-json/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -44,6 +44,8 @@
<surefire.coverage.argline>
--add-exports org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED
--add-exports org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
--add-reads org.glassfish.jersey.incubator.html.json=org.glassfish.jersey.core.server
--add-reads org.glassfish.jersey.incubator.html.json=org.glassfish.jersey.tests.framework.core
--add-reads org.glassfish.jersey.incubator.html.json=org.glassfish.jersey.tests.framework.provider.grizzly
@@ -105,6 +107,16 @@
<groupId>org.netbeans.html</groupId>
<artifactId>ko-ws-tyrus</artifactId>
<version>${net.java.html.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.glassfish.grizzly</groupId>
+ <artifactId>grizzly-framework</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.glassfish.grizzly</groupId>
+ <artifactId>grizzly-http-server</artifactId>
+ </exclusion>
+ </exclusions>
<scope>runtime</scope>
</dependency>
<!-- Overwrite Grizzly dependency defined in ko-ws-tyrus -->
diff --git a/incubator/html-json/src/main/java/module-info.java b/incubator/html-json/src/main/java/module-info.txt
similarity index 85%
rename from incubator/html-json/src/main/java/module-info.java
rename to incubator/html-json/src/main/java/module-info.txt
index 6a2d033..29656d9 100644
--- a/incubator/html-json/src/main/java/module-info.java
+++ b/incubator/html-json/src/main/java/module-info.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,9 @@
requires org.glassfish.jersey.core.common;
requires org.glassfish.jersey.core.client;
+ requires org.openide.util.lookup.RELEASE240;
+ requires net.java.html.json;
+ requires net.java.html;
exports org.glassfish.jersey.media.htmljson;
opens org.glassfish.jersey.media.htmljson;
diff --git a/incubator/html-json/src/test/java/module-info.test b/incubator/html-json/src/test/java/module-info.txt
similarity index 88%
rename from incubator/html-json/src/test/java/module-info.test
rename to incubator/html-json/src/test/java/module-info.txt
index b722e67..d1e14d0 100644
--- a/incubator/html-json/src/test/java/module-info.test
+++ b/incubator/html-json/src/test/java/module-info.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,8 +21,7 @@
requires net.java.html;
requires net.java.html.json;
requires ko.ws.tyrus;
- requires grizzly.framework;
- requires org.openide.util.lookup.RELEASE160;
+ requires org.openide.util.lookup.RELEASE240;
requires org.junit.jupiter.api;
requires org.glassfish.jersey.tests.framework.core;
diff --git a/incubator/injectless-client/pom.xml b/incubator/injectless-client/pom.xml
index 7683faa..485397c 100644
--- a/incubator/injectless-client/pom.xml
+++ b/incubator/injectless-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/incubator/kryo/pom.xml b/incubator/kryo/pom.xml
index 0b8483d..e6b4179 100644
--- a/incubator/kryo/pom.xml
+++ b/incubator/kryo/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,6 +36,8 @@
<properties>
<surefire.coverage.argline>
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
--add-reads org.glassfish.jersey.incubator.media.kryo=org.glassfish.jersey.core.server
--add-reads org.glassfish.jersey.incubator.media.kryo=org.glassfish.jersey.core.client
--add-modules=ALL-MODULE-PATH
diff --git a/incubator/open-tracing/pom.xml b/incubator/open-tracing/pom.xml
index 1e7a319..33a9164 100644
--- a/incubator/open-tracing/pom.xml
+++ b/incubator/open-tracing/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/incubator/pom.xml b/incubator/pom.xml
index 9d0d3eb..3f3fc5d 100644
--- a/incubator/pom.xml
+++ b/incubator/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -39,7 +39,6 @@
<module>cdi-inject-weld</module>
<module>declarative-linking</module>
<module>gae-integration</module>
- <module>html-json</module>
<module>injectless-client</module>
<module>kryo</module>
<module>open-tracing</module>
@@ -53,4 +52,16 @@
<scope>test</scope>
</dependency>
</dependencies>
+
+ <profiles>
+ <profile>
+ <id>HTML-JSON-FOR-PRE-JDK24</id>
+ <activation>
+ <jdk>[11, 24)</jdk>
+ </activation>
+ <modules>
+ <module>html-json</module>
+ </modules>
+ </profile>
+ </profiles>
</project>
diff --git a/inject/cdi2-se/pom.xml b/inject/cdi2-se/pom.xml
index abcc77d..d69cfc9 100644
--- a/inject/cdi2-se/pom.xml
+++ b/inject/cdi2-se/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -51,6 +51,10 @@
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
index 584193f..053dbe8 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 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
@@ -116,18 +116,11 @@
* @param <T> type of the instance which is registered.
*/
public static <T> void registerSupplier(SupplierInstanceBinding<T> binding, AfterBeanDiscovery abd, BeanManager beanManager) {
- BeanManagerImpl manager;
- if (beanManager instanceof BeanManagerProxy) {
- manager = ((BeanManagerProxy) beanManager).unwrap();
- } else {
- manager = (BeanManagerImpl) beanManager;
- }
-
/*
* CDI does not provide sufficient support for ThreadScoped Supplier
*/
if (binding.getScope() == PerThread.class) {
- abd.addBean(new SupplierThreadScopeBean(binding, manager));
+ abd.addBean(new SupplierThreadScopeBean(binding, beanManagerImpl(beanManager)));
} else {
abd.addBean(new SupplierInstanceBean<>(binding));
abd.addBean(new SupplierInstanceBeanBridge<>(binding));
@@ -156,8 +149,23 @@
InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers);
supplierBean.setInjectionTarget(jit);
- abd.addBean(supplierBean);
- abd.addBean(new SupplierBeanBridge(binding, beanManager));
+ /*
+ * CDI does not provide sufficient support for ThreadScoped Supplier
+ */
+ if (binding.getScope() == PerThread.class) {
+ abd.addBean(new SupplierThreadScopeClassBean(binding, supplierBean, beanManagerImpl(beanManager)));
+ } else {
+ abd.addBean(supplierBean);
+ abd.addBean(new SupplierBeanBridge(binding, beanManager));
+ }
+ }
+
+ private static BeanManagerImpl beanManagerImpl(BeanManager beanManager) {
+ if (beanManager instanceof BeanManagerProxy) {
+ return ((BeanManagerProxy) beanManager).unwrap();
+ } else {
+ return (BeanManagerImpl) beanManager;
+ }
}
private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget,
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java
index a0c0d34..b95ae0a 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.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
@@ -17,20 +17,13 @@
package org.glassfish.jersey.inject.cdi.se.bean;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.WeakHashMap;
-import java.util.function.Supplier;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.spi.CreationalContext;
-import jakarta.enterprise.inject.spi.Bean;
-import jakarta.enterprise.inject.spi.PassivationCapable;
import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
-import org.jboss.weld.bean.StringBeanIdentifier;
import org.jboss.weld.bean.proxy.BeanInstance;
-import org.jboss.weld.bean.proxy.ContextBeanInstance;
import org.jboss.weld.bean.proxy.ProxyFactory;
import org.jboss.weld.manager.BeanManagerImpl;
@@ -107,31 +100,4 @@
ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this);
return factory.create(beanInstance);
}
-
- private static class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> {
-
- private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>();
-
- private final Supplier<T> supplier;
-
- /**
- * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
- *
- * @param supplier provider of the value.
- */
- private ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) {
- super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId);
- this.supplier = supplier;
- }
-
- @Override
- public Object invoke(Object obj, Method method, Object... arguments) throws Throwable {
- Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get());
- return super.invoke(instance, method, arguments);
- }
-
- public void dispose() {
- this.instances.clear();
- }
- }
}
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java
new file mode 100644
index 0000000..698bfb0
--- /dev/null
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java
@@ -0,0 +1,111 @@
+/*
+ * 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.cdi.se.bean;
+
+import java.lang.annotation.Annotation;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+import jakarta.enterprise.context.Dependent;
+import jakarta.enterprise.context.spi.CreationalContext;
+
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.jboss.weld.bean.proxy.BeanInstance;
+import org.jboss.weld.bean.proxy.ProxyFactory;
+import org.jboss.weld.manager.BeanManagerImpl;
+
+
+/**
+ * Creates an implementation of {@link jakarta.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}.
+ * Binding provides the information about the bean also called {@link jakarta.enterprise.inject.spi.BeanAttributes} information.
+ * The {@code Bean} does not use {@link org.glassfish.jersey.inject.cdi.se.injector.JerseyInjectionTarget} because serves already
+ * created proxy, therefore the create operation just return provided instance without any other contextual operation
+ * (produce, inject, destroy).
+ * <p>
+ * This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and
+ * works through the proxy which serves the correct instance per the given thread.
+ * <p>
+ * Register example:
+ * <pre>
+ * AbstractBinder {
+ * @Override
+ * protected void configure() {
+ * bindFactory(MyFactoryInjectionSupplier.class)
+ * .to(MyBean.class)
+ * .in(PerThread.class);
+ * }
+ * }
+ * </pre>
+ * Inject example:
+ * <pre>
+ * @Path("/")
+ * public class MyResource {
+ * @Inject
+ * private MyBean myBean;
+ * }
+ * </pre>
+ */
+class SupplierThreadScopeClassBean extends JerseyBean<Object> {
+ private final LazyValue<ThreadScopeBeanInstance<Object>> beanInstance;
+ private final SupplierClassBinding binding;
+ private final LazyValue<Object> proxy;
+ private final AtomicReference<CreationalContext> creationalContextAtomicReference = new AtomicReference<>();
+
+ SupplierThreadScopeClassBean(SupplierClassBinding binding, SupplierClassBean supplierClassBean, BeanManagerImpl beanManager) {
+ super(binding);
+ this.binding = binding;
+ this.beanInstance = Values.lazy((Value<ThreadScopeBeanInstance<Object>>) () -> {
+ Supplier supplierInstance = supplierClassBean.create(creationalContextAtomicReference.get());
+ ThreadScopeBeanInstance scopeBeanInstance =
+ new ThreadScopeBeanInstance(supplierInstance, this, beanManager.getContextId());
+ return scopeBeanInstance;
+ });
+ this.proxy = Values.lazy((Value<Object>) () -> createClientProxy(beanInstance.get(), beanManager.getContextId()));
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return Dependent.class;
+ }
+
+ @Override
+ public Object create(CreationalContext<Object> ctx) {
+ creationalContextAtomicReference.set(ctx);
+ return proxy.get();
+ }
+
+ @Override
+ public void destroy(Object instance, CreationalContext<Object> creationalContext) {
+ if (beanInstance.isInitialized()) {
+ this.beanInstance.get().dispose();
+ }
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return (Class<?>) this.binding.getContracts().iterator().next();
+ }
+
+ private <T> T createClientProxy(BeanInstance beanInstance, String contextId) {
+ ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this);
+ return factory.create(beanInstance);
+ }
+}
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java
new file mode 100644
index 0000000..a200960
--- /dev/null
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available 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.cdi.se.bean;
+
+import org.jboss.weld.bean.StringBeanIdentifier;
+import org.jboss.weld.bean.proxy.ContextBeanInstance;
+
+import java.lang.reflect.Method;
+import java.util.WeakHashMap;
+import java.util.function.Supplier;
+
+import jakarta.enterprise.inject.spi.Bean;
+import jakarta.enterprise.inject.spi.PassivationCapable;
+
+/**
+ * {@link org.glassfish.jersey.internal.inject.PerThread} scope bean instance used from
+ * {@link SupplierThreadScopeBean} and {@link SupplierThreadScopeClassBean}.
+ *
+ * @param <T> Typed of the bean supplied by a {@code Supplier}.
+ */
+class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> {
+
+ private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>();
+
+ private final Supplier<T> supplier;
+
+ /**
+ * Creates a new invocation handler with supplier which provides a current injected value in proper scope.
+ *
+ * @param supplier provider of the value.
+ */
+ ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) {
+ super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId);
+ this.supplier = supplier;
+ }
+
+ @Override
+ public Object invoke(Object obj, Method method, Object... arguments) throws Throwable {
+ Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get());
+ return super.invoke(instance, method, arguments);
+ }
+
+ public void dispose() {
+ this.instances.clear();
+ }
+}
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java
index fd4ae86..3f4f924 100644
--- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java
+++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.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
@@ -26,9 +26,11 @@
static final String GREETING = "Ahoj";
+ private String greeting = GREETING + "#" + Thread.currentThread().getName();
+
@Override
public String getGreeting() {
- return GREETING + "#" + Thread.currentThread().getName();
+ return greeting;
}
@Override
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/DisposableSupplierTest.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/DisposableSupplierTest.java
index 6bade9b..10eec31 100644
--- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/DisposableSupplierTest.java
+++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/DisposableSupplierTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 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
@@ -17,6 +17,8 @@
package org.glassfish.jersey.inject.cdi.se;
import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
@@ -368,9 +370,17 @@
// All instances should be the same because they are request scoped.
ComposedObject instance = injectionManager.getInstance(ComposedObject.class);
- assertEquals("1", instance.getFirst());
- assertEquals("2", instance.getSecond());
- assertEquals("3", instance.getThird());
+ Set<String> set1 = new HashSet<String>() {{
+ add("1");
+ add("2");
+ add("3");
+ }};
+ Set<String> set2 = new HashSet<String>() {{
+ add(instance.getFirst().toString());
+ add(instance.getSecond().toString());
+ add(instance.getThird().toString());
+ }};
+ assertEquals(set1, set2);
});
Supplier<String> cleanedSupplier = atomicSupplier.get();
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java
index cf377c1..1fe627a 100644
--- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java
+++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 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
@@ -17,6 +17,7 @@
package org.glassfish.jersey.inject.cdi.se;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
@@ -167,7 +168,7 @@
}
@Test
- public void testThreadScopedInSingletonScope() {
+ public void testThreadScopedInSingletonScope() throws InterruptedException {
InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
BindingTestHelper.bind(injectionManager, binder -> {
binder.bindAsContract(SingletonObject.class)
@@ -188,6 +189,52 @@
assertNotNull(greeting2);
assertEquals(greeting1, greeting2);
+
+ final AtomicReference<String> greetingAtomicReference = new AtomicReference<>();
+ Runnable runnable = () ->
+ greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting());
+
+ Thread newThread = new Thread(runnable);
+ newThread.start();
+ newThread.join();
+
+ assertEquals(greeting1.getGreeting(), greeting2.getGreeting());
+ assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get());
+ }
+
+ @Test
+ public void testSupplierClassBindingThreadScopedInSingletonScope() throws InterruptedException {
+ InjectionManager injectionManager = BindingTestHelper.createInjectionManager();
+ BindingTestHelper.bind(injectionManager, binder -> {
+ binder.bindAsContract(SingletonObject.class)
+ .in(Singleton.class);
+
+ binder.bindFactory(SupplierGreeting.class)
+ .to(Greeting.class)
+ .in(PerThread.class);
+ });
+
+ SingletonObject instance1 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting1 = instance1.getGreeting();
+ assertNotNull(greeting1);
+
+ // Precisely the same object
+ SingletonObject instance2 = injectionManager.getInstance(SingletonObject.class);
+ Greeting greeting2 = instance2.getGreeting();
+ assertNotNull(greeting2);
+
+ assertEquals(greeting1, greeting2);
+
+ final AtomicReference<String> greetingAtomicReference = new AtomicReference<>();
+ Runnable runnable = () ->
+ greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting());
+
+ Thread newThread = new Thread(runnable);
+ newThread.start();
+ newThread.join();
+
+ assertEquals(greeting1.getGreeting(), greeting2.getGreeting());
+ assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get());
}
@RequestScoped
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/CachedConstructorAnalyzerTest.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/CachedConstructorAnalyzerTest.java
index cc9e78a..7e105aa 100644
--- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/CachedConstructorAnalyzerTest.java
+++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/CachedConstructorAnalyzerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -30,6 +30,7 @@
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests {@link CachedConstructorAnalyzer}.
@@ -110,7 +111,8 @@
Constructor<BothAnnotatedConstructor> constructor = analyzer.getConstructor();
assertEquals(1, constructor.getParameterCount());
- assertEquals(Integer.class, constructor.getParameterTypes()[0]);
+ Class<?> parameterType = constructor.getParameterTypes()[0];
+ assertTrue(parameterType.equals(String.class) || parameterType.equals(Integer.class));
}
@Test
diff --git a/inject/hk2/pom.xml b/inject/hk2/pom.xml
index 81c7787..1f21a2d 100644
--- a/inject/hk2/pom.xml
+++ b/inject/hk2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -61,7 +61,6 @@
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
- <version>${javassist.version}</version>
</dependency>
<dependency>
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/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/DisposableSupplierTest.java b/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/DisposableSupplierTest.java
index 89d2db3..bb290a2 100644
--- a/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/DisposableSupplierTest.java
+++ b/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/DisposableSupplierTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 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
@@ -17,6 +17,8 @@
package org.glassfish.jersey.inject.hk2;
import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
@@ -374,9 +376,17 @@
// All instances should be the same because they are request scoped.
ComposedObject instance = injectionManager.getInstance(ComposedObject.class);
- assertEquals("1", instance.first);
- assertEquals("2", instance.second);
- assertEquals("3", instance.third);
+ Set<String> set1 = new HashSet<String>() {{
+ add("1");
+ add("2");
+ add("3");
+ }};
+ Set<String> set2 = new HashSet<String>() {{
+ add(instance.first.toString());
+ add(instance.second.toString());
+ add(instance.third.toString());
+ }};
+ assertEquals(set1, set2);
});
Supplier<String> cleanedSupplier = atomicSupplier.get();
diff --git a/inject/pom.xml b/inject/pom.xml
index 8af41ab..2e4f1a0 100644
--- a/inject/pom.xml
+++ b/inject/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/media/jaxb/pom.xml b/media/jaxb/pom.xml
index f93452f..8e9cbb8 100644
--- a/media/jaxb/pom.xml
+++ b/media/jaxb/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -83,21 +83,6 @@
<inherited>true</inherited>
</plugin>
<plugin>
- <groupId>de.jflex</groupId>
- <artifactId>maven-jflex-plugin</artifactId>
- <version>1.4.3</version>
- <executions>
- <execution>
- <goals>
- <goal>generate</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<inherited>true</inherited>
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
index 1d3c5c5..0b95efd 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
@@ -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
@@ -21,6 +21,8 @@
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -57,6 +59,7 @@
private static final Map<Class<?>, WeakReference<JAXBContext>> jaxbContexts =
new WeakHashMap<Class<?>, WeakReference<JAXBContext>>();
+ private static final Lock jaxbContextsLock = new ReentrantLock();
private final Providers jaxrsProviders;
private final boolean fixedResolverMediaType;
private final Value<ContextResolver<JAXBContext>> mtContext;
@@ -149,7 +152,7 @@
/**
* Get the JAXB unmarshaller for the given class and media type.
* <p>
- * In case this provider instance has been {@link #AbstractJaxbProvider(Providers, MediaType)
+ * In case this provider instance has been {@link AbstractJaxbProvider(Providers, MediaType)
* created with a fixed resolver media type}, the supplied media type argument will be ignored.
* </p>
*
@@ -192,7 +195,7 @@
/**
* Get the JAXB marshaller for the given class and media type.
* <p>
- * In case this provider instance has been {@link #AbstractJaxbProvider(Providers, MediaType)
+ * In case this provider instance has been {@link AbstractJaxbProvider(Providers, MediaType)
* created with a fixed resolver media type}, the supplied media type argument will be ignored.
* </p>
*
@@ -280,7 +283,8 @@
* @throws JAXBException in case the JAXB context retrieval fails.
*/
protected JAXBContext getStoredJaxbContext(Class type) throws JAXBException {
- synchronized (jaxbContexts) {
+ jaxbContextsLock.lock();
+ try {
final WeakReference<JAXBContext> ref = jaxbContexts.get(type);
JAXBContext c = (ref != null) ? ref.get() : null;
if (c == null) {
@@ -288,7 +292,10 @@
jaxbContexts.put(type, new WeakReference<JAXBContext>(c));
}
return c;
+ } finally {
+ jaxbContextsLock.unlock();
}
+
}
/**
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
index e7e399d..7065c43 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,8 @@
import java.lang.reflect.Type;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.core.Context;
@@ -54,6 +56,7 @@
public class JaxbStringReaderProvider {
private static final Map<Class, JAXBContext> jaxbContexts = new WeakHashMap<Class, JAXBContext>();
+ private static final Lock jaxbContextsLock = new ReentrantLock();
private final Value<ContextResolver<JAXBContext>> mtContext;
private final Value<ContextResolver<Unmarshaller>> mtUnmarshaller;
@@ -116,13 +119,16 @@
* @throws JAXBException in case JAXB context retrieval fails.
*/
protected JAXBContext getStoredJAXBContext(Class type) throws JAXBException {
- synchronized (jaxbContexts) {
+ jaxbContextsLock.lock();
+ try {
JAXBContext c = jaxbContexts.get(type);
if (c == null) {
c = JAXBContext.newInstance(type);
jaxbContexts.put(type, c);
}
return c;
+ } finally {
+ jaxbContextsLock.unlock();
}
}
diff --git a/media/json-binding/pom.xml b/media/json-binding/pom.xml
index 427b9aa..b07b09c 100644
--- a/media/json-binding/pom.xml
+++ b/media/json-binding/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -94,6 +94,14 @@
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>org.glassfish</groupId>
+ <artifactId>jakarta.json</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.parsson</groupId>
+ <artifactId>parsson</artifactId>
+ </exclusion>
</exclusions>
</dependency>
diff --git a/media/json-binding/src/main/java/module-info.java b/media/json-binding/src/main/java/module-info.java
index 146f6df..357206f 100644
--- a/media/json-binding/src/main/java/module-info.java
+++ b/media/json-binding/src/main/java/module-info.java
@@ -15,6 +15,8 @@
*/
module org.glassfish.jersey.media.jsonb {
+ requires java.logging;
+
requires jakarta.annotation;
requires jakarta.inject;
requires jakarta.json.bind;
diff --git a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java
index b80ac9e..a41afb0 100644
--- a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java
+++ b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.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
@@ -16,16 +16,25 @@
package org.glassfish.jersey.jsonb;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;
+import org.glassfish.jersey.ApplicationSupplier;
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.internal.InternalProperties;
+import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.jsonb.internal.JsonBindingAutoDiscoverable;
import org.glassfish.jersey.jsonb.internal.JsonBindingProvider;
+import java.security.AccessController;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
/**
* Feature used to register JSON-B providers.
* <p>
@@ -50,12 +59,85 @@
*/
public class JsonBindingFeature implements Feature {
+ private static final Logger LOGGER = Logger.getLogger(JsonBindingFeature.class.getName());
private static final String JSON_FEATURE = JsonBindingFeature.class.getSimpleName();
@Override
public boolean configure(final FeatureContext context) {
final Configuration config = context.getConfiguration();
+ // ---- Allow to disable for compatibility with Pre JAX-RS 2.1 Jersey.
+
+ /* Either system properties */
+ final String bindingDisabledBySystemProperty = AccessController.doPrivileged(
+ PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE));
+
+ final String bindingDisabledBySystemPropertyClient = AccessController.doPrivileged(
+ PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT));
+
+ final String bindingDisabledBySystemPropertyServer = AccessController.doPrivileged(
+ PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER));
+
+ final RuntimeType runtimeType = config.getRuntimeType();
+
+ boolean bindingDisabledBySystem = PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemProperty)
+ || (runtimeType == RuntimeType.CLIENT
+ && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyClient))
+ || (runtimeType == RuntimeType.SERVER
+ && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyServer));
+
+ /* Or config property */
+ final Boolean bindingDisabled = CommonProperties.getValue(config.getProperties(), runtimeType,
+ CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.class);
+
+ /* Config property takes precedence */
+ if ((bindingDisabledBySystem && !Boolean.FALSE.equals(bindingDisabled)) || Boolean.TRUE.equals(bindingDisabled)) {
+ return false;
+ }
+
+ final Set<String> disabledPackageNames = new HashSet<>();
+
+ /* Only a certain package names */
+ final String bindingDisabledPackageBySystemProperty = RuntimeType.SERVER == runtimeType
+ ? AccessController.doPrivileged(PropertiesHelper.getSystemProperty(
+ CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION))
+ : null;
+
+ final String bindingDisabledPackage = RuntimeType.SERVER == runtimeType
+ ? CommonProperties.getValue(config.getProperties(), runtimeType,
+ CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, String.class)
+ : null;
+
+ separatePackageNames(disabledPackageNames, bindingDisabledPackageBySystemProperty);
+ separatePackageNames(disabledPackageNames, bindingDisabledPackage);
+
+ if (!disabledPackageNames.isEmpty() && !Boolean.FALSE.equals(bindingDisabled)) {
+ try {
+ Application app = null;
+ if (InjectionManagerSupplier.class.isInstance(context)) {
+ app = ((InjectionManagerSupplier) context).getInjectionManager().getInstance(Application.class);
+ if (app != null) {
+ while (ApplicationSupplier.class.isInstance(app) && ((ApplicationSupplier) app).getApplication() != app) {
+ app = ((ApplicationSupplier) app).getApplication();
+ }
+ for (String disabledPackageName : disabledPackageNames) {
+ if (app.getClass().getName().startsWith(disabledPackageName)) {
+ return false;
+ }
+ }
+ }
+ }
+ if (app == null) {
+ LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(
+ LocalizationMessages.ERROR_JSONB_APPLICATION_NOT_FOUND()));
+ }
+ } catch (Throwable throwable) {
+ LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(throwable.getMessage()));
+ }
+ }
+
+ // ---- End of disabling for compatibility with Pre JAX-RS 2.1 Jersey.
+
final String jsonFeature = CommonProperties.getValue(
config.getProperties(),
config.getRuntimeType(),
@@ -74,4 +156,12 @@
return true;
}
+
+ private static void separatePackageNames(Set<String> set, String packages) {
+ if (packages != null) {
+ for (String packageName : packages.split(",")) {
+ set.add(packageName.trim());
+ }
+ }
+ }
}
diff --git a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties
index 4eee493..371e641 100644
--- a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties
+++ b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2019 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
@@ -14,6 +14,8 @@
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
#
+error.jsonb.application.not.found=Application not found.
+error.jsonb.detecting.application=JSON-B could not detect the application name: {0}.
error.jsonb.serialization=Error writing JSON-B serialized object.
error.jsonb.deserialization=Error deserializing object from entity stream.
error.jsonb.emptystream=JSON-B cannot parse empty input stream.
diff --git a/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java
new file mode 100644
index 0000000..7dc8a3f
--- /dev/null
+++ b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.jsonb.internal;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.jsonb.JsonBindingFeature;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.FeatureContext;
+import java.lang.reflect.Proxy;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class JsonbDisabledTest {
+ @Test
+ public void testDisabled() {
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, true);
+ configReference.set(config2);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+ }
+
+ @Test
+ public void testDisabledBySystemProperty() {
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true");
+ configReference.set(config2);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER);
+ }
+
+ @Test
+ public void testDisabledBySystemPropertyOverridenByConfigProperty() {
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE, "true");
+ config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, false);
+ configReference.set(config2);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE);
+ }
+
+ @Test
+ public void testDisabledByPropertyApplicationPackage() {
+ Application application = new Application() {
+ };
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ injectionManager.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(application).to(Application.class);
+ }
+ });
+ AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager);
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION,
+ "some.does.not.matter, org.glassfish.jersey.jsonb.internal");
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config2);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION);
+ }
+
+ @Test
+ public void disableOnClientOnlyTest() {
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, true);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, true);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL);
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true");
+ configReference.set(config2);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, "true");
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER);
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT);
+ }
+
+ @Test
+ public void testDisabledBySystemPropertyApplicationPackage() {
+ Application application = new Application() {
+ };
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ injectionManager.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(application).to(Application.class);
+ }
+ });
+ AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager);
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference);
+
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION,
+ "some.does.not.matter, org.glassfish.jersey.jsonb.internal");
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config2);
+ Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1));
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION);
+ }
+
+ @Test
+ public void testDisabledBySystemPropertyApplicationPackageEnabledByProperty() {
+ Application application = new Application() {
+ };
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ injectionManager.register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(application).to(Application.class);
+ }
+ });
+ AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager);
+ AtomicReference<CommonConfig> configReference = new AtomicReference<>();
+ FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference);
+
+ CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ configReference.set(config1);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+
+ System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION,
+ "some.does.not.matter, org.glassfish.jersey.jsonb.internal");
+
+ CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+ config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.FALSE);
+ configReference.set(config2);
+ Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1));
+ System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION);
+ }
+
+ private static FeatureContext featureContextForConfig(AtomicReference<CommonConfig> configReference) {
+ return featureContextForConfig(configReference, new AtomicReference<>());
+ }
+ private static FeatureContext featureContextForConfig(AtomicReference<CommonConfig> configReference,
+ AtomicReference<InjectionManager> injectionManager) {
+ return (FeatureContext) Proxy.newProxyInstance(
+ JsonbDisabledTest.class.getClassLoader(),
+ new Class[] {FeatureContext.class, InjectionManagerSupplier.class}, (proxy, method, args) -> {
+ switch (method.getName()) {
+ case "getConfiguration":
+ return configReference.get();
+ case "getInjectionManager":
+ return injectionManager.get();
+ }
+ return null;
+ });
+ }
+}
diff --git a/media/json-gson/pom.xml b/media/json-gson/pom.xml
index 8a78e0a..cc7a577 100644
--- a/media/json-gson/pom.xml
+++ b/media/json-gson/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -71,6 +71,12 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
diff --git a/media/json-jackson/pom.xml b/media/json-jackson/pom.xml
index 777e9d6..fc8bafa 100644
--- a/media/json-jackson/pom.xml
+++ b/media/json-jackson/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JacksonFeature.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JacksonFeature.java
index 5411720..9391bc6 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JacksonFeature.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JacksonFeature.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
@@ -29,8 +29,10 @@
import org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider;
import org.glassfish.jersey.jackson.internal.FilteringJacksonJaxbJsonProvider;
import org.glassfish.jersey.jackson.internal.JacksonFilteringFeature;
+import org.glassfish.jersey.jackson.internal.JaxrsFeatureBag;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.JsonMappingExceptionMapper;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.JsonParseExceptionMapper;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.glassfish.jersey.message.MessageProperties;
import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
@@ -41,7 +43,7 @@
* @author Stepan Kopriva
* @author Michal Gajdos
*/
-public class JacksonFeature implements Feature {
+public class JacksonFeature extends JaxrsFeatureBag<JacksonFeature> implements Feature {
/**
* Define whether to use Jackson's exception mappers ore not
@@ -100,6 +102,16 @@
return this;
}
+ /**
+ * Register {@link JaxRSFeature} with the Jackson providers.
+ * @param feature the {@link JaxRSFeature} to be enabled or disabled.
+ * @param state {@code true} for enabling the feature, {@code false} for disabling.
+ * @return JacksonFeature with {@link JaxRSFeature} registered to be set on a created Jackson provider.
+ */
+ public JacksonFeature jaxrsFeature(JaxRSFeature feature, boolean state) {
+ return super.jaxrsFeature(feature, state);
+ }
+
private static final String JSON_FEATURE = JacksonFeature.class.getSimpleName();
@Override
@@ -138,6 +150,10 @@
context.property(MessageProperties.JSON_MAX_STRING_LENGTH, maxStringLength);
}
+ if (hasJaxrsFeature()) {
+ context.property(JaxrsFeatureBag.JAXRS_FEATURE, this);
+ }
+
return true;
}
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JaxRSFeatureObjectMapper.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JaxRSFeatureObjectMapper.java
new file mode 100644
index 0000000..d759e56
--- /dev/null
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JaxRSFeatureObjectMapper.java
@@ -0,0 +1,67 @@
+/*
+ * 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.jackson;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.glassfish.jersey.jackson.internal.AbstractObjectMapper;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature;
+
+
+/**
+ * The Jackson {@link ObjectMapper} supporting {@link JaxRSFeature}s.
+ */
+public class JaxRSFeatureObjectMapper extends AbstractObjectMapper {
+
+ public JaxRSFeatureObjectMapper() {
+ super();
+ }
+
+ /**
+ * Method for changing state of an on/off {@link org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature}
+ * features.
+ */
+ public ObjectMapper configure(JaxRSFeature f, boolean state) {
+ jaxrsFeatureBag.jaxrsFeature(f, state);
+ return this;
+ }
+
+ /**
+ * Method for enabling specified {@link org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature}s
+ * for parser instances this object mapper creates.
+ */
+ public ObjectMapper enable(JaxRSFeature... features) {
+ if (features != null) {
+ for (JaxRSFeature f : features) {
+ jaxrsFeatureBag.jaxrsFeature(f, true);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Method for disabling specified {@link org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature}s
+ * for parser instances this object mapper creates.
+ */
+ public ObjectMapper disable(JaxRSFeature... features) {
+ if (features != null) {
+ for (JaxRSFeature f : features) {
+ jaxrsFeatureBag.jaxrsFeature(f, false);
+ }
+ }
+ return this;
+ }
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/AbstractObjectMapper.java
similarity index 60%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/AbstractObjectMapper.java
index 0fdbe9d..2f331cf 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/AbstractObjectMapper.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
@@ -14,7 +14,16 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
+package org.glassfish.jersey.jackson.internal;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
+ * Internal ObjectMapper with {@link JaxrsFeatureBag}.
*/
-package org.glassfish.jersey.test.jetty11.http2;
+public abstract class AbstractObjectMapper extends ObjectMapper {
+ protected AbstractObjectMapper() {
+
+ }
+ protected JaxrsFeatureBag jaxrsFeatureBag = new JaxrsFeatureBag();
+}
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 f715407..4defc70 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,6 +18,7 @@
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.StreamReadConstraints;
+import com.fasterxml.jackson.core.json.PackageVersion;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectReader;
@@ -31,6 +32,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;
@@ -38,6 +40,7 @@
import jakarta.inject.Singleton;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
/**
@@ -47,31 +50,50 @@
public class DefaultJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
private Configuration commonConfig;
private static final Logger LOGGER = Logger.getLogger(DefaultJacksonJaxbJsonProvider.class.getName());
+ private final boolean hasConfig;
@Inject
public DefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
- super(new JacksonMapperConfigurator(null, DEFAULT_ANNOTATIONS));
- this.commonConfig = config;
- _providers = providers;
+ this(providers, config, DEFAULT_ANNOTATIONS);
}
//do not register JaxbAnnotationModule because it brakes default annotations processing
private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"};
- public DefaultJacksonJaxbJsonProvider() {
- super(new JacksonMapperConfigurator(null, DEFAULT_ANNOTATIONS));
- }
-
public DefaultJacksonJaxbJsonProvider(Providers providers, Configuration config, Annotations... annotationsToUse) {
super(new JacksonMapperConfigurator(null, annotationsToUse));
this.commonConfig = config;
_providers = providers;
+
+ boolean ex = true;
+ try {
+ Object jaxrsFeatureBag = config.getProperty(JaxrsFeatureBag.JAXRS_FEATURE);
+ if (jaxrsFeatureBag != null && (JaxrsFeatureBag.class.isInstance(jaxrsFeatureBag))) {
+ ((JaxrsFeatureBag) jaxrsFeatureBag).configureJaxrsFeatures(this);
+ }
+ } catch (RuntimeException e) {
+ // ignore - not configured
+ LOGGER.fine(LocalizationMessages.ERROR_CONFIGURING(e.getMessage()));
+ ex = false;
+ }
+ hasConfig = ex;
+ }
+
+ @Override
+ protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) {
+ ObjectMapper mapper = super._locateMapperViaProvider(type, mediaType);
+ if (AbstractObjectMapper.class.isInstance(mapper)) {
+ ((AbstractObjectMapper) mapper).jaxrsFeatureBag.configureJaxrsFeatures(this);
+ }
+ return mapper;
}
@Override
protected JsonEndpointConfig _configForReading(ObjectReader reader, Annotation[] annotations) {
try {
- updateFactoryConstraints(reader.getFactory());
+ if (hasConfig) {
+ updateFactoryConstraints(reader.getFactory());
+ }
} catch (Throwable t) {
// A Jackson 14 would throw NoSuchMethodError, ClassNotFoundException, NoClassDefFoundError or similar
// that should have been ignored
@@ -104,7 +126,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));
}
@@ -127,13 +155,22 @@
if (maxStringLength != StreamReadConstraints.DEFAULT_MAX_STRING_LEN) {
final StreamReadConstraints constraints = jsonFactory.streamReadConstraints();
- jsonFactory.setStreamReadConstraints(
- StreamReadConstraints.builder()
- .maxStringLength(maxStringLength)
- .maxNestingDepth(constraints.getMaxNestingDepth())
- .maxNumberLength(constraints.getMaxNumberLength())
- .build()
- );
+ StreamReadConstraints.Builder builder = StreamReadConstraints.builder()
+ // our
+ .maxStringLength(maxStringLength)
+ // customers
+ .maxDocumentLength(constraints.getMaxDocumentLength())
+ .maxNameLength(constraints.getMaxNameLength())
+ .maxNestingDepth(constraints.getMaxNestingDepth())
+ .maxNumberLength(constraints.getMaxNumberLength());
+
+ if (PackageVersion.VERSION.getMinorVersion() >= 18) {
+ builder.maxTokenCount(constraints.getMaxTokenCount());
+ } else {
+ LOGGER.warning(LocalizationMessages.ERROR_JACKSON_STREAMREADCONSTRAINTS_218("maxTokenCount"));
+ }
+
+ jsonFactory.setStreamReadConstraints(builder.build());
}
}
-}
\ No newline at end of file
+}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java
index a12d4d0..74f510c 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.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
@@ -26,6 +26,7 @@
import org.glassfish.jersey.message.filtering.spi.EntityGraphProvider;
import org.glassfish.jersey.message.filtering.spi.EntityInspector;
import org.glassfish.jersey.message.filtering.spi.ObjectGraph;
+import org.glassfish.jersey.message.filtering.spi.ScopeProvider;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
@@ -37,7 +38,6 @@
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
-import org.glassfish.jersey.message.filtering.spi.ScopeProvider;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Context;
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JaxrsFeatureBag.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JaxrsFeatureBag.java
new file mode 100644
index 0000000..4711b56
--- /dev/null
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JaxrsFeatureBag.java
@@ -0,0 +1,58 @@
+/*
+ * 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.jackson.internal;
+
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Internal holder class for {@link JaxRSFeature} settings and their values.
+ */
+public class JaxrsFeatureBag<T extends JaxrsFeatureBag> {
+ protected static final String JAXRS_FEATURE = "jersey.config.jackson.jaxrs.feature";
+
+ private static class JaxRSFeatureState {
+ /* package */ final JaxRSFeature feature;
+ /* package */ final boolean state;
+ public JaxRSFeatureState(JaxRSFeature feature, boolean state) {
+ this.feature = feature;
+ this.state = state;
+ }
+ }
+
+ private Optional<List<JaxRSFeatureState>> jaxRSFeature = Optional.empty();
+
+ public T jaxrsFeature(JaxRSFeature feature, boolean state) {
+ if (!jaxRSFeature.isPresent()) {
+ jaxRSFeature = Optional.of(new ArrayList<>());
+ }
+ jaxRSFeature.ifPresent(list -> list.add(new JaxrsFeatureBag.JaxRSFeatureState(feature, state)));
+ return (T) this;
+ }
+
+ protected boolean hasJaxrsFeature() {
+ return jaxRSFeature.isPresent();
+ }
+
+ /* package */ void configureJaxrsFeatures(ProviderBase providerBase) {
+ jaxRSFeature.ifPresent(list -> list.stream().forEach(state -> providerBase.configure(state.feature, state.state)));
+ }
+}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/base/ProviderBase.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/base/ProviderBase.java
index ecdfbae..350be25 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/base/ProviderBase.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/base/ProviderBase.java
@@ -31,7 +31,6 @@
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectWriterInjector;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.ObjectWriterModifier;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.util.ClassKey;
-import org.glassfish.jersey.jackson.internal.jackson.jaxrs.util.LRUMap;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -44,6 +43,8 @@
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.util.LookupCache;
+import com.fasterxml.jackson.databind.util.LRUMap;
import com.fasterxml.jackson.databind.type.TypeFactory;
public abstract class ProviderBase<
@@ -186,14 +187,12 @@
/**
* Cache for resolved endpoint configurations when reading JSON data
*/
- protected final LRUMap<AnnotationBundleKey, EP_CONFIG> _readers
- = new LRUMap<AnnotationBundleKey, EP_CONFIG>(16, 120);
+ protected final LookupCache<AnnotationBundleKey, EP_CONFIG> _readers;
/**
* Cache for resolved endpoint configurations when writing JSON data
*/
- protected final LRUMap<AnnotationBundleKey, EP_CONFIG> _writers
- = new LRUMap<AnnotationBundleKey, EP_CONFIG>(16, 120);
+ protected final LookupCache<AnnotationBundleKey, EP_CONFIG> _writers;
/*
/**********************************************************
@@ -202,8 +201,9 @@
*/
protected ProviderBase(MAPPER_CONFIG mconfig) {
- _mapperConfig = mconfig;
- _jaxRSFeatures = JAXRS_FEATURE_DEFAULTS;
+ this(mconfig,
+ new LRUMap<>(16, 120),
+ new LRUMap<>(16, 120));
}
/**
@@ -214,8 +214,19 @@
*/
@Deprecated // just to denote it should NOT be directly called; will NOT be removed
protected ProviderBase() {
- _mapperConfig = null;
+ this(null);
+ }
+ /**
+ * @since 2.17
+ */
+ protected ProviderBase(MAPPER_CONFIG mconfig,
+ LookupCache<AnnotationBundleKey, EP_CONFIG> readerCache,
+ LookupCache<AnnotationBundleKey, EP_CONFIG> writerCache)
+ {
+ _mapperConfig = mconfig;
_jaxRSFeatures = JAXRS_FEATURE_DEFAULTS;
+ _readers = readerCache;
+ _writers = writerCache;
}
/*
@@ -1056,4 +1067,4 @@
private final THIS _this() {
return (THIS) this;
}
-}
\ No newline at end of file
+}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/JaxRSFeature.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/JaxRSFeature.java
index 6f864c9..c0f0da5 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/JaxRSFeature.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/JaxRSFeature.java
@@ -40,6 +40,7 @@
* @since 2.15
*/
READ_FULL_STREAM(true),
+
/*
/**********************************************************
/* HTTP headers
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
index 75bc66e..bc280cc 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
@@ -13,8 +13,8 @@
* well as accessing it.
*/
public abstract class MapperConfiguratorBase<IMPL extends MapperConfiguratorBase<IMPL,MAPPER>,
- MAPPER extends ObjectMapper
->
+ MAPPER extends ObjectMapper
+ >
{
/**
* Mapper provider was constructed with if any, or that was constructed
@@ -22,7 +22,7 @@
* If defined (explicitly or implicitly) it will be used, instead
* of using provider-based lookup.
*/
- protected MAPPER _mapper;
+ protected volatile MAPPER _mapper;
/**
* If no mapper was specified when constructed, and no configuration
@@ -30,14 +30,14 @@
* between default mapper and regular one is that default mapper
* is only used if no mapper is found via provider lookup.
*/
- protected MAPPER _defaultMapper;
+ protected volatile MAPPER _defaultMapper;
/**
* Annotations set to use by default; overridden by explicit call
- * to {@link #setAnnotationsToUse}
+ * to {@link #setAnnotationsToUse}. Marked final in v2.17.1.
*/
- protected Annotations[] _defaultAnnotationsToUse;
-
+ protected final Annotations[] _defaultAnnotationsToUse;
+
/**
* To support optional dependency to Jackson JAXB annotations module
* (needed iff JAXB annotations are used for configuration)
@@ -49,7 +49,7 @@
/* Construction
/**********************************************************
*/
-
+
public MapperConfiguratorBase(MAPPER mapper, Annotations[] defaultAnnotations)
{
_mapper = mapper;
@@ -61,7 +61,7 @@
/* Abstract methods to implement
/***********************************************************
*/
-
+
/**
* Method that locates, configures and returns {@link ObjectMapper} to use
*/
@@ -84,27 +84,27 @@
/***********************************************************
*/
- public synchronized final void setMapper(MAPPER m) {
+ public final void setMapper(MAPPER m) {
_mapper = m;
}
- public synchronized final void setAnnotationsToUse(Annotations[] annotationsToUse) {
+ public final void setAnnotationsToUse(Annotations[] annotationsToUse) {
_setAnnotations(mapper(), annotationsToUse);
}
- public synchronized final void configure(DeserializationFeature f, boolean state) {
+ public final void configure(DeserializationFeature f, boolean state) {
mapper().configure(f, state);
}
- public synchronized final void configure(SerializationFeature f, boolean state) {
+ public final void configure(SerializationFeature f, boolean state) {
mapper().configure(f, state);
}
- public synchronized final void configure(JsonParser.Feature f, boolean state) {
+ public final void configure(JsonParser.Feature f, boolean state) {
mapper().configure(f, state);
}
- public synchronized final void configure(JsonGenerator.Feature f, boolean state) {
+ public final void configure(JsonGenerator.Feature f, boolean state) {
mapper().configure(f, state);
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
index eb7c072..ac207b8 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
@@ -25,7 +25,7 @@
*/
@Provider
@Consumes(MediaType.WILDCARD) // NOTE: required to support "non-standard" JSON variants
-@Produces(MediaType.WILDCARD)
+@Produces({MediaType.APPLICATION_JSON, "text/json", MediaType.WILDCARD})
public class JacksonJaxbJsonProvider extends JacksonJsonProvider {
/**
* Default annotation sets to use, if not explicitly defined during
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
index 0871ece..13f9275 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
@@ -52,7 +52,7 @@
*/
@Provider
@Consumes(MediaType.WILDCARD) // NOTE: required to support "non-standard" JSON variants
-@Produces(MediaType.WILDCARD)
+@Produces({MediaType.APPLICATION_JSON, "text/json", MediaType.WILDCARD})
public class JacksonJsonProvider
extends ProviderBase<JacksonJsonProvider,
ObjectMapper,
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JsonMapperConfigurator.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JsonMapperConfigurator.java
index 3e9c770..fd5d9aa 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JsonMapperConfigurator.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JsonMapperConfigurator.java
@@ -1,6 +1,7 @@
package org.glassfish.jersey.jackson.internal.jackson.jaxrs.json;
import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantLock;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.Annotations;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.MapperConfiguratorBase;
@@ -8,7 +9,7 @@
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
-import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
+import com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
/**
* Helper class used to encapsulate details of configuring an
@@ -16,14 +17,17 @@
* well as accessing it.
*/
public class JsonMapperConfigurator
- extends MapperConfiguratorBase<JsonMapperConfigurator, ObjectMapper>
+ extends MapperConfiguratorBase<JsonMapperConfigurator, ObjectMapper>
{
+ // @since 2.17.1
+ private final ReentrantLock _lock = new ReentrantLock();
+
/*
/**********************************************************
/* Construction
/**********************************************************
*/
-
+
public JsonMapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations)
{
super(mapper, defAnnotations);
@@ -33,18 +37,24 @@
* Method that locates, configures and returns {@link ObjectMapper} to use
*/
@Override
- public synchronized ObjectMapper getConfiguredMapper() {
- /* important: should NOT call mapper(); needs to return null
- * if no instance has been passed or constructed
- */
+ public ObjectMapper getConfiguredMapper() {
+ // important: should NOT call mapper(); needs to return null
+ // if no instance has been passed or constructed
return _mapper;
}
@Override
- public synchronized ObjectMapper getDefaultMapper() {
+ public ObjectMapper getDefaultMapper() {
if (_defaultMapper == null) {
- _defaultMapper = new ObjectMapper();
- _setAnnotations(_defaultMapper, _defaultAnnotationsToUse);
+ _lock.lock();
+ try {
+ if (_defaultMapper == null) {
+ _defaultMapper = new ObjectMapper();
+ _setAnnotations(_defaultMapper, _defaultAnnotationsToUse);
+ }
+ } finally {
+ _lock.unlock();
+ }
}
return _defaultMapper;
}
@@ -64,8 +74,15 @@
protected ObjectMapper mapper()
{
if (_mapper == null) {
- _mapper = new ObjectMapper();
- _setAnnotations(_mapper, _defaultAnnotationsToUse);
+ _lock.lock();
+ try {
+ if (_mapper == null) {
+ _mapper = new ObjectMapper();
+ _setAnnotations(_mapper, _defaultAnnotationsToUse);
+ }
+ } finally {
+ _lock.unlock();
+ }
}
return _mapper;
}
@@ -100,22 +117,22 @@
protected AnnotationIntrospector _resolveIntrospector(Annotations ann)
{
switch (ann) {
- case JACKSON:
- return new JacksonAnnotationIntrospector();
- case JAXB:
- /* For this, need to use indirection just so that error occurs
- * when we get here, and not when this class is being loaded
- */
- try {
- if (_jaxbIntrospectorClass == null) {
- _jaxbIntrospectorClass = JaxbAnnotationIntrospector.class;
+ case JACKSON:
+ return new JacksonAnnotationIntrospector();
+ case JAXB:
+ /* For this, need to use indirection just so that error occurs
+ * when we get here, and not when this class is being loaded
+ */
+ try {
+ if (_jaxbIntrospectorClass == null) {
+ _jaxbIntrospectorClass = JakartaXmlBindAnnotationIntrospector.class;
+ }
+ return _jaxbIntrospectorClass.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to instantiate JakartaXmlBindAnnotationIntrospector: "+e.getMessage(), e);
}
- return _jaxbIntrospectorClass.newInstance();
- } catch (Exception e) {
- throw new IllegalStateException("Failed to instantiate JaxbAnnotationIntrospector: "+e.getMessage(), e);
- }
- default:
- throw new IllegalStateException();
+ default:
+ throw new IllegalStateException();
}
}
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
index 3a34c28..44c9073 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
@@ -11,7 +11,7 @@
*/
public final class PackageVersion implements Versioned {
public final static Version VERSION = VersionUtil.parseVersion(
- "2.15.3", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider");
+ "2.18.0", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider");
@Override
public Version version() {
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/LRUMap.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/LRUMap.java
index 7252cd5..c99c987 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/LRUMap.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/LRUMap.java
@@ -3,11 +3,15 @@
import java.util.LinkedHashMap;
import java.util.Map;
+// TO BE REMOVED FROM JACKSON 2.18 or later
/**
* Helper for simple bounded LRU maps used for reusing lookup values.
*
* @since 2.2
+ *
+ * @deprecated Since 2.16.1 Use one from {@code jackson-databind} instead.
*/
+@Deprecated // since 2.16.1
@SuppressWarnings("serial")
public class LRUMap<K,V> extends LinkedHashMap<K,V>
{
@@ -24,5 +28,4 @@
{
return size() > _maxEntries;
}
-
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/package-info.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/package-info.java
index 4ec091c..c18b433 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/package-info.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/util/package-info.java
@@ -1,4 +1,4 @@
/**
* Miscellaneous helper classes used by providers.
*/
-package com.fasterxml.jackson.jaxrs.util;
+package org.glassfish.jersey.jackson.internal.jackson.jaxrs.util;
diff --git a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
index 4251b2f..d893c65 100644
--- a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
+++ b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
@@ -31,7 +31,7 @@
## Third-party Content
-Jackson JAX-RS Providers version 2.15.3
+Jackson JAX-RS Providers version 2.18.0
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
* Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
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..1c66b9c 100644
--- a/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties
+++ b/media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -13,5 +13,7 @@
#
# 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.configuring=Error configuring the DefaultJacksonJaxbJsonProvider: {0}.
+error.jackson.streamreadconstraints=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.15?
+error.jackson.streamreadconstraints218=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.18?
+error.modules.not.loaded=Jackson modules could not be loaded: {0}
\ No newline at end of file
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForBothModulesTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForBothModulesTest.java
index 59d19c1..e9b621a 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForBothModulesTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForBothModulesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 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
@@ -23,6 +23,9 @@
import jakarta.ws.rs.core.Application;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class DefaultJsonJacksonProviderForBothModulesTest extends JerseyTest {
@@ -36,8 +39,12 @@
public final void testDisabledModule() {
final String response = target("entity/simple")
.request().get(String.class);
+ String expected = "{\"name\":\"Hello\",\"value\":\"World\"}";
+ List<String> response_list = Arrays.asList(response.replaceAll("[{}]", "").split(","));
+ List<String> expected_list = Arrays.asList(expected.replaceAll("[{}]", "").split(","));
+ Collections.sort(response_list);
- assertEquals("{\"name\":\"Hello\",\"value\":\"World\"}", response);
+ assertEquals(expected_list, response_list);
}
}
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java
index e75400a..3e40866 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.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
@@ -30,6 +30,7 @@
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -48,9 +49,10 @@
.register(JacksonFeature.class)
.register(TestJacksonJaxbJsonProvider.class)
.property("jersey.config.json.jackson.disabled.modules", "Jdk8Module");
- final String response = target("JAXBEntity")
- .request().get(String.class);
- assertNotEquals("{\"key\":\"key\",\"value\":\"value\"}", response);
+ try (Response response = target("JAXBEntity").request().get()) {
+ assertEquals(400, response.getStatus());
+ assertNotEquals("{\"key\":\"key\",\"value\":\"value\"}", response.readEntity(String.class));
+ }
}
private static class TestJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForEnabledModulesTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForEnabledModulesTest.java
index eaf293d..58a5e5a 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForEnabledModulesTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForEnabledModulesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 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
@@ -22,7 +22,9 @@
import org.junit.jupiter.api.Test;
import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
public class DefaultJsonJacksonProviderForEnabledModulesTest extends JerseyTest {
@@ -34,9 +36,10 @@
@Test
public final void testDisabledModule() {
- final String response = target("entity/simple")
- .request().get(String.class);
- assertNotEquals("{\"name\":\"Hello\",\"value\":\"World\"}", response);
+ try (Response response = target("entity/simple").request().get()) {
+ assertEquals(400, response.getStatus());
+ assertNotEquals("{\"name\":\"Hello\",\"value\":\"World\"}", response.readEntity(String.class));
+ }
}
}
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JaxRSFeatureTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JaxRSFeatureTest.java
new file mode 100644
index 0000000..86b6200
--- /dev/null
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JaxRSFeatureTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.jackson.internal;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.jackson.JaxRSFeatureObjectMapper;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.JaxRSFeature;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ContextResolver;
+import jakarta.ws.rs.ext.Providers;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+public class JaxRSFeatureTest {
+ @Test
+ public void testJaxrsFeatureOnJacksonFeature() {
+ Client client = ClientBuilder.newClient()
+ .register(new JacksonFeature().jaxrsFeature(JaxRSFeature.READ_FULL_STREAM, false))
+ .register(JaxrsFeatureFilter.class);
+
+ try (Response r = client.target("http://xxx.yyy").request().get()) {
+ MatcherAssert.assertThat(r.getStatus(), Matchers.is(200));
+ }
+ }
+
+ @Test
+ public void testJaxrsFeatureOnContextResolver() {
+ Client client = ClientBuilder.newClient()
+ .register(JacksonFeature.class)
+ .register(JaxrsFetureContextResolver.class)
+ .register(JaxrsFeatureFilter.class);
+
+ try (Response r = client.target("http://xxx.yyy").request().get()) {
+ MatcherAssert.assertThat(r.getStatus(), Matchers.is(200));
+ }
+ }
+
+
+ public static class JaxrsFeatureFilter implements ClientRequestFilter {
+ private final DefaultJacksonJaxbJsonProvider jacksonProvider;
+ @Inject
+ public JaxrsFeatureFilter(Providers allProviders) {
+ jacksonProvider = (DefaultJacksonJaxbJsonProvider)
+ allProviders.getMessageBodyReader(Object.class, Object.class, null, MediaType.APPLICATION_JSON_TYPE);
+ try {
+ jacksonProvider.readFrom(Object.class, Object.class, null, MediaType.APPLICATION_JSON_TYPE, null,
+ new ByteArrayInputStream("{}".getBytes()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ };
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ Response.Status status = jacksonProvider.isEnabled(JaxRSFeature.READ_FULL_STREAM)
+ ? Response.Status.FORBIDDEN
+ : Response.Status.OK;
+ requestContext.abortWith(Response.status(status).build());
+ }
+ }
+
+ public static class JaxrsFetureContextResolver implements ContextResolver<ObjectMapper> {
+
+ @Override
+ public ObjectMapper getContext(Class<?> type) {
+ JaxRSFeatureObjectMapper objectMapper = new JaxRSFeatureObjectMapper();
+ objectMapper.disable(JaxRSFeature.READ_FULL_STREAM);
+ return objectMapper;
+ }
+ }
+}
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/StreamReadConstrainsTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/StreamReadConstrainsTest.java
index 925c17e..873377c 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/StreamReadConstrainsTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/StreamReadConstrainsTest.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
@@ -19,7 +19,9 @@
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.StreamReadConstraints;
+import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.exc.StreamConstraintsException;
+import com.fasterxml.jackson.core.json.PackageVersion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -50,6 +52,7 @@
import java.util.List;
public class StreamReadConstrainsTest extends JerseyTest {
+ private static final String ERROR_MSG_PART = "maximum allowed (";
@Override
protected final Application configure() {
@@ -78,7 +81,7 @@
.post(Entity.entity(new MyEntity(8), MediaType.APPLICATION_JSON_TYPE))) {
Assertions.assertEquals(200, response.getStatus());
String errorMsg = response.readEntity(String.class);
- Assertions.assertTrue(errorMsg.contains("maximum length (4)"));
+ Assertions.assertTrue(errorMsg.contains(ERROR_MSG_PART + 4));
}
}
@@ -125,11 +128,31 @@
throw ex;
}
String errorMsg = ex.getCause().getMessage();
- Assertions.assertTrue(errorMsg.contains("maximum length (" + String.valueOf(expectedLength) + ")"));
+ Assertions.assertTrue(errorMsg.contains(ERROR_MSG_PART + String.valueOf(expectedLength)));
}
}
+ @Test
+ void testMatchingVersion() {
+ final Version coreVersion = PackageVersion.VERSION;
+ final Version jerseyVersion = org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.PackageVersion.VERSION;
+ StringBuilder message = new StringBuilder();
+ message.append("Dependency Jackson Version is ")
+ .append(coreVersion.getMajorVersion())
+ .append(".")
+ .append(coreVersion.getMinorVersion());
+ message.append("\n Repackaged Jackson Version is ")
+ .append(jerseyVersion.getMajorVersion())
+ .append(".")
+ .append(jerseyVersion.getMinorVersion());
+
+ Assertions.assertEquals(coreVersion.getMajorVersion(), jerseyVersion.getMajorVersion(), message.toString());
+ Assertions.assertEquals(coreVersion.getMinorVersion(), jerseyVersion.getMinorVersion(), message.toString());
+ Assertions.assertEquals(coreVersion.getMajorVersion(), 2,
+ "update " + DefaultJacksonJaxbJsonProvider.class.getName()
+ + " updateFactoryConstraints method to support version " + coreVersion.getMajorVersion());
+ }
@Test
void testStreamReadConstraintsMethods() {
@@ -137,7 +160,9 @@
+ " Please update the code in " + DefaultJacksonJaxbJsonProvider.class.getName()
+ " updateFactoryConstraints method";
Method[] method = StreamReadConstraints.Builder.class.getDeclaredMethods();
- Assertions.assertEquals(4, method.length, message); // three max + build methods
+ // 2.17 : five setMax... + build() methods
+ // 2.18 : six setMax... + build() methods
+ Assertions.assertEquals(7, method.length, message);
}
@Path("len")
diff --git a/media/json-jettison/pom.xml b/media/json-jettison/pom.xml
index 614fe5e..c14c642 100644
--- a/media/json-jettison/pom.xml
+++ b/media/json-jettison/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/media/json-processing/pom.xml b/media/json-processing/pom.xml
index fa7af46..98f4ae2 100644
--- a/media/json-processing/pom.xml
+++ b/media/json-processing/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/media/moxy/pom.xml b/media/moxy/pom.xml
index 33e2c86..90161de 100644
--- a/media/moxy/pom.xml
+++ b/media/moxy/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -62,21 +62,6 @@
</configuration>
</plugin>
- <plugin>
- <groupId>de.jflex</groupId>
- <artifactId>maven-jflex-plugin</artifactId>
- <version>1.4.3</version>
- <executions>
- <execution>
- <goals>
- <goal>generate</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/generated-sources/rsrc-gen</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
@@ -111,6 +96,11 @@
</dependency>
<dependency>
+ <groupId>jakarta.xml.bind</groupId>
+ <artifactId>jakarta.xml.bind-api</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<exclusions>
@@ -122,6 +112,14 @@
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-activation</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>jakarta.xml.bind</groupId>
+ <artifactId>jakarta.xml.bind-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jakarta.activation</groupId>
+ <artifactId>jakarta.activation-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
@@ -138,12 +136,4 @@
</dependency>
</dependencies>
- <repositories>
- <repository>
- <id>eclipselink.repository</id>
- <name>Eclipse Maven Repository</name>
- <url>https://download.eclipse.org/rt/eclipselink/maven.repo</url>
- <layout>default</layout>
- </repository>
- </repositories>
-</project>
+</project>
\ No newline at end of file
diff --git a/media/multipart/pom.xml b/media/multipart/pom.xml
index 8021c13..49d8114 100644
--- a/media/multipart/pom.xml
+++ b/media/multipart/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,6 +36,9 @@
<properties>
<surefire.coverage.argline>
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate.io=ALL-UNNAMED
--add-exports org.glassfish.jersey.core.client/org.glassfish.jersey.client.innate=ALL-UNNAMED
--add-modules=ALL-MODULE-PATH
</surefire.coverage.argline>
@@ -100,8 +103,8 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.glassfish.jersey.connectors</groupId>
- <artifactId>jersey-jetty-connector</artifactId>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-processing</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
@@ -143,6 +146,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
+ <inherited>true</inherited>
<configuration>
<testExcludes>
<testExclude>org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java</testExclude>
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
index 7287759..d672e1c 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/BodyPart.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 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
@@ -16,10 +16,13 @@
package org.glassfish.jersey.media.multipart;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.text.ParseException;
+import java.util.Arrays;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.core.GenericType;
@@ -28,6 +31,7 @@
import jakarta.ws.rs.ext.MessageBodyReader;
import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.innate.spi.MessageBodyWorkersSettable;
import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
import org.glassfish.jersey.media.multipart.internal.LocalizationMessages;
import org.glassfish.jersey.message.MessageBodyWorkers;
@@ -41,7 +45,7 @@
* @author Paul Sandoz
* @author Michal Gajdos
*/
-public class BodyPart {
+public class BodyPart implements MessageBodyWorkersSettable {
protected ContentDisposition contentDisposition = null;
@@ -285,7 +289,15 @@
}
<T> T getEntityAs(final Class<T> type, Type genericType) {
- if (entity == null || !(entity instanceof BodyPartEntity)) {
+ InputStream inputStream = null;
+ if (BodyPartEntity.class.isInstance(entity)) {
+ inputStream = ((BodyPartEntity) entity).getInputStream();
+ } else if (InputStream.class.isInstance(entity)) {
+ inputStream = (InputStream) entity;
+ } else if (byte[].class.isInstance(entity)) {
+ inputStream = new ByteArrayInputStream((byte[]) entity);
+ }
+ if (inputStream == null) {
throw new IllegalStateException(LocalizationMessages.ENTITY_HAS_WRONG_TYPE());
}
if (type == BodyPartEntity.class) {
@@ -299,8 +311,7 @@
}
try {
- return reader.readFrom(type, genericType, annotations, mediaType, headers,
- ((BodyPartEntity) entity).getInputStream());
+ return reader.readFrom(type, genericType, annotations, mediaType, headers, inputStream);
} catch (final IOException ioe) {
throw new ProcessingException(LocalizationMessages.ERROR_READING_ENTITY(String.class), ioe);
}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
index f95d521..f6c7165 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/ContentDisposition.java
@@ -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
@@ -28,8 +28,6 @@
import org.glassfish.jersey.message.internal.HttpHeaderReader;
import org.glassfish.jersey.uri.UriComponent;
-import jakarta.ws.rs.core.HttpHeaders;
-
/**
* A content disposition header.
*
@@ -60,10 +58,13 @@
private static final Pattern FILENAME_VALUE_CHARS_PATTERN =
Pattern.compile("(%[a-f0-9]{2}|[a-z0-9!#$&+.^_`|~-])+", Pattern.CASE_INSENSITIVE);
+ private static final char QUOTE = '"';
+ private static final char BACK_SLASH = '\\';
+
protected ContentDisposition(final String type, final String fileName, final Date creationDate,
final Date modificationDate, final Date readDate, final long size) {
this.type = type;
- this.fileName = fileName;
+ this.fileName = encodeAsciiFileName(fileName);
this.creationDate = creationDate;
this.modificationDate = modificationDate;
this.readDate = readDate;
@@ -201,7 +202,9 @@
protected void addDateParameter(final StringBuilder sb, final String name, final Date p) {
if (p != null) {
- sb.append("; ").append(name).append("=\"").append(HttpDateFormat.getPreferredDateFormat().format(p)).append("\"");
+ sb.append("; ").append(name).append("=\"")
+ .append(HttpDateFormat.getPreferredDateFormatter().format(p))
+ .append("\"");
}
}
@@ -211,6 +214,23 @@
}
}
+ protected String encodeAsciiFileName(String fileName) {
+ if (fileName == null
+ || (fileName.indexOf(QUOTE) == -1
+ && fileName.indexOf(BACK_SLASH) == -1)) {
+ return fileName;
+ }
+ final char[] chars = fileName.toCharArray();
+ final StringBuilder encodedBuffer = new StringBuilder();
+ for (char c : chars) {
+ if (c == QUOTE || c == BACK_SLASH) {
+ encodedBuffer.append(BACK_SLASH);
+ }
+ encodedBuffer.append(c);
+ }
+ return encodedBuffer.toString();
+ }
+
private void createParameters() throws ParseException {
defineFileName();
@@ -229,7 +249,7 @@
final String fileNameExt = parameters.get("filename*");
if (fileNameExt == null) {
- this.fileName = fileName;
+ this.fileName = encodeAsciiFileName(fileName);
return;
}
@@ -284,7 +304,7 @@
if (value == null) {
return null;
}
- return HttpDateFormat.getPreferredDateFormat().parse(value);
+ return HttpDateFormat.getPreferredDateFormatter().toDate(value);
}
private long createLong(final String name) throws ParseException {
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/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/ClientFilterTests.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/ClientFilterTests.java
new file mode 100644
index 0000000..f7bfa53
--- /dev/null
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/ClientFilterTests.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.media.multipart;
+
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonValue;
+import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.EntityPart;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Tests in clientFilter before the multipart provider is invoked.
+ * Check the workers are set.
+ *
+ * Modified MP Rest Client TCK tests
+ */
+public class ClientFilterTests {
+ /**
+ * Tests that a single file is upload. The response is a simple JSON response with the file information.
+ *
+ * @throws Exception
+ * if a test error occurs
+ */
+ @Test
+ public void uploadFile() throws Exception {
+ try (Client client = createClient()) {
+ final byte[] content;
+ try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file1.txt")) {
+ Assertions.assertNotNull(in, "Could not find /multipart/test-file1.txt");
+ content = in.readAllBytes();
+ }
+ // Send in an InputStream to ensure it works with an InputStream
+ final List<EntityPart> files = List.of(EntityPart.withFileName("test-file1.txt")
+ .content(new ByteArrayInputStream(content))
+ .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE)
+ .build());
+ try (Response response = client.target("http://localhost").request()
+ .post(Entity.entity(files, MediaType.MULTIPART_FORM_DATA))) {
+ Assertions.assertEquals(201, response.getStatus());
+ final JsonArray jsonArray = response.readEntity(JsonArray.class);
+ Assertions.assertNotNull(jsonArray);
+ Assertions.assertEquals(jsonArray.size(), 1);
+ final JsonObject json = jsonArray.getJsonObject(0);
+ Assertions.assertEquals(json.getString("name"), "test-file1.txt");
+ Assertions.assertEquals(json.getString("fileName"), "test-file1.txt");
+ Assertions.assertEquals(json.getString("content"), "This is a test file for file 1.");
+ }
+ }
+ }
+
+ /**
+ * Tests that two files are upload. The response is a simple JSON response with the file information.
+ *
+ * @throws Exception
+ * if a test error occurs
+ */
+ @Test
+ public void uploadMultipleFiles() throws Exception {
+ try (Client client = createClient()) {
+ final Map<String, byte[]> entityPartContent = new LinkedHashMap<>(2);
+ try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file1.txt")) {
+ Assertions.assertNotNull(in, "Could not find /multipart/test-file1.txt");
+ entityPartContent.put("test-file1.txt", in.readAllBytes());
+ }
+ try (InputStream in = ClientFilterTests.class.getResourceAsStream("/multipart/test-file2.txt")) {
+ Assertions.assertNotNull(in, "Could not find /multipart/test-file2.txt");
+ entityPartContent.put("test-file2.txt", in.readAllBytes());
+ }
+ final List<EntityPart> files = entityPartContent.entrySet()
+ .stream()
+ .map((entry) -> {
+ try {
+ return EntityPart.withName(entry.getKey())
+ .fileName(entry.getKey())
+ .content(entry.getValue())
+ .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE)
+ .build();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ })
+ .collect(Collectors.toList());
+
+ try (Response response = client.target("http://localhost").request()
+ .post(Entity.entity(files, MediaType.MULTIPART_FORM_DATA))) {
+ Assertions.assertEquals(201, response.getStatus());
+ final JsonArray jsonArray = response.readEntity(JsonArray.class);
+ Assertions.assertNotNull(jsonArray);
+ Assertions.assertEquals(jsonArray.size(), 2);
+ // Don't assume the results are in a specific order
+ for (JsonValue value : jsonArray) {
+ final JsonObject json = value.asJsonObject();
+ if (json.getString("name").equals("test-file1.txt")) {
+ Assertions.assertEquals(json.getString("fileName"), "test-file1.txt");
+ Assertions.assertEquals(json.getString("content"), "This is a test file for file 1.");
+ } else if (json.getString("name").equals("test-file2.txt")) {
+ Assertions.assertEquals(json.getString("fileName"), "test-file2.txt");
+ Assertions.assertEquals(json.getString("content"), "This is a test file for file 2.");
+ } else {
+ Assertions.fail(String.format("Unexpected entry %s in JSON response: %n%s", json, jsonArray));
+ }
+ }
+ }
+ }
+ }
+
+ private static Client createClient() {
+ return ClientBuilder.newClient().register(new FileManagerFilter());
+ }
+
+ public static class FileManagerFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(final ClientRequestContext requestContext) throws IOException {
+ if (requestContext.getMethod().equals("POST")) {
+ // Download the file
+ @SuppressWarnings("unchecked")
+ final List<EntityPart> entityParts = (List<EntityPart>) requestContext.getEntity();
+ final JsonArrayBuilder jsonBuilder = Json.createArrayBuilder();
+ for (EntityPart part : entityParts) {
+ final JsonObjectBuilder jsonPartBuilder = Json.createObjectBuilder();
+ jsonPartBuilder.add("name", part.getName());
+ if (part.getFileName().isPresent()) {
+ jsonPartBuilder.add("fileName", part.getFileName().get());
+ } else {
+ throw new BadRequestException("No file name for entity part " + part);
+ }
+ jsonPartBuilder.add("content", part.getContent(String.class));
+ jsonBuilder.add(jsonPartBuilder);
+ }
+ requestContext.abortWith(Response.status(201).entity(jsonBuilder.build()).build());
+ } else {
+ requestContext
+ .abortWith(Response.status(Response.Status.BAD_REQUEST).entity("Invalid request").build());
+ }
+ }
+ }
+}
diff --git a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
index e6ff2ed..73790c0 100644
--- a/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
+++ b/media/multipart/src/test/java/org/glassfish/jersey/media/multipart/internal/MultiPartHeaderModificationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,7 +36,6 @@
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
import org.glassfish.jersey.client.spi.ConnectorProvider;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
-import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.spi.TestHelper;
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/media/multipart/src/test/resources/multipart/test-file1.txt b/media/multipart/src/test/resources/multipart/test-file1.txt
new file mode 100644
index 0000000..2ac045a
--- /dev/null
+++ b/media/multipart/src/test/resources/multipart/test-file1.txt
@@ -0,0 +1 @@
+This is a test file for file 1.
\ No newline at end of file
diff --git a/media/multipart/src/test/resources/multipart/test-file2.txt b/media/multipart/src/test/resources/multipart/test-file2.txt
new file mode 100644
index 0000000..ed72b76
--- /dev/null
+++ b/media/multipart/src/test/resources/multipart/test-file2.txt
@@ -0,0 +1 @@
+This is a test file for file 2.
\ No newline at end of file
diff --git a/media/pom.xml b/media/pom.xml
index c196383..03b4ea3 100644
--- a/media/pom.xml
+++ b/media/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/media/sse/pom.xml b/media/sse/pom.xml
index 28ce019..c0f8548 100644
--- a/media/sse/pom.xml
+++ b/media/sse/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -89,6 +89,10 @@
</plugins>
</build>
<properties>
- <surefire.coverage.argline>--add-modules=ALL-MODULE-PATH</surefire.coverage.argline>
+ <surefire.coverage.argline>
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate=ALL-UNNAMED
+ --add-opens org.glassfish.jersey.core.common/org.glassfish.jersey.innate.virtual=ALL-UNNAMED
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
</properties>
</project>
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/EventProcessor.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/EventProcessor.java
index 00e9fe7..ee9f56d 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/EventProcessor.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/EventProcessor.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
@@ -24,6 +24,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -87,6 +88,10 @@
* A map of listeners bound to receive only events of a particular name.
*/
private final Map<String, List<EventListener>> boundListeners;
+ /**
+ * A list of Error Consumers.
+ */
+ private final List<Consumer<Throwable>> throwableConsumers;
/**
* Shutdown handler is invoked when Event processor reaches terminal stage.
@@ -111,6 +116,7 @@
this.unboundListeners = that.unboundListeners;
this.eventListener = that.eventListener;
this.shutdownHandler = that.shutdownHandler;
+ this.throwableConsumers = that.throwableConsumers;
}
private EventProcessor(Builder builder) {
@@ -128,6 +134,7 @@
this.unboundListeners = builder.unboundListeners == null ? Collections.EMPTY_LIST : builder.unboundListeners;
this.eventListener = builder.eventListener;
this.shutdownHandler = builder.shutdownHandler;
+ this.throwableConsumers = builder.throwableConsumers;
}
/**
@@ -199,6 +206,16 @@
}
// if we're here, an unrecoverable error has occurred - just turn off the lights...
shutdownHandler.shutdown();
+ // and notify error handlers
+ if (throwableConsumers != null) {
+ for (Consumer<Throwable> consumer : throwableConsumers) {
+ try {
+ consumer.accept(ex);
+ } catch (Throwable throwable) {
+ LOGGER.fine(String.format("User throwable ignored: %s", throwable.getMessage()));
+ }
+ }
+ }
} finally {
if (eventInput != null && !eventInput.isClosed()) {
eventInput.close();
@@ -357,6 +374,7 @@
private boolean disableKeepAlive;
private List<EventListener> unboundListeners;
private Map<String, List<EventListener>> boundListeners;
+ private List<Consumer<Throwable>> throwableConsumers = null;
private Builder(WebTarget target,
AtomicReference<State> state,
@@ -421,6 +439,17 @@
}
/**
+ * Set the consumers of {@link Throwable} occurring during connection.
+ *
+ * @param throwableConsumers a list of consumers of throwable.
+ * @return updated builder instance.
+ */
+ public Builder throwableConsumers(List<Consumer<Throwable>> throwableConsumers) {
+ this.throwableConsumers = throwableConsumers;
+ return this;
+ }
+
+ /**
* Build the {@link EventProcessor}.
*
* @return built Event processor instance.
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/JerseySseEventSource.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/JerseySseEventSource.java
index d455465..f675181 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/JerseySseEventSource.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/JerseySseEventSource.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
@@ -16,6 +16,8 @@
package org.glassfish.jersey.media.sse.internal;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -72,6 +74,10 @@
* Client provided executor facade.
*/
private final ClientExecutor clientExecutor;
+ /**
+ * List of Throwable consumers passed to EventProcessor.Builder.
+ */
+ private final List<Consumer<Throwable>> throwableConsumers = new ArrayList<>();
/**
* Private constructor.
@@ -110,11 +116,13 @@
public void register(final Consumer<InboundSseEvent> onEvent, final Consumer<Throwable> onError) {
this.subscribe(DEFAULT_SUBSCRIPTION_HANDLER, onEvent, onError, () -> {
});
+ throwableConsumers.add(onError);
}
@Override
public void register(final Consumer<InboundSseEvent> onEvent, final Consumer<Throwable> onError, final Runnable onComplete) {
this.subscribe(DEFAULT_SUBSCRIPTION_HANDLER, onEvent, onError, onComplete);
+ throwableConsumers.add(onError);
}
private void subscribe(final Consumer<Flow.Subscription> onSubscribe,
@@ -173,6 +181,7 @@
EventProcessor processor = EventProcessor
.builder(endpoint, state, clientExecutor, this::onEvent, this::close)
.reconnectDelay(reconnectDelay, reconnectTimeUnit)
+ .throwableConsumers(throwableConsumers)
.build();
clientExecutor.submit(processor);
diff --git a/media/sse/src/test/java/org/glassfish/jersey/media/sse/SseEventSourceRegisterErrorHandlerTest.java b/media/sse/src/test/java/org/glassfish/jersey/media/sse/SseEventSourceRegisterErrorHandlerTest.java
new file mode 100644
index 0000000..036a568
--- /dev/null
+++ b/media/sse/src/test/java/org/glassfish/jersey/media/sse/SseEventSourceRegisterErrorHandlerTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.sse;
+
+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.BadRequestException;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.InternalServerErrorException;
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.sse.InboundSseEvent;
+import jakarta.ws.rs.sse.Sse;
+import jakarta.ws.rs.sse.SseEventSink;
+import jakarta.ws.rs.sse.SseEventSource;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+public class SseEventSourceRegisterErrorHandlerTest extends JerseyTest {
+ @Path("sse")
+ public static class SseEventSourceRegisterTestSseEndpoint {
+
+ @Path("hello")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public void hello(@Context SseEventSink output, @Context Sse sse) throws InterruptedException {
+ output.send(sse.newEvent("HELLO"));
+ }
+
+ @Path("close")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public void close(@Context SseEventSink output, @Context Sse sse) throws InterruptedException {
+ output.close();
+ }
+
+ @Path("500")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public void throw500(@Context SseEventSink output, @Context Sse sse) throws InterruptedException {
+ throw new WebApplicationException();
+ }
+
+ @Path("400")
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public void throw400(@Context SseEventSink output, @Context Sse sse) throws InterruptedException {
+ throw new BadRequestException();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(SseEventSourceRegisterTestSseEndpoint.class);
+ }
+
+ private static final Consumer<InboundSseEvent> EMPTY = event -> {
+ };
+
+ @Test
+ public void testConnection404() throws InterruptedException {
+ WebTarget sseTarget = target("sse");
+ AtomicReference<Throwable> throwable = new AtomicReference<>();
+ CountDownLatch completeLatch = new CountDownLatch(1);
+
+ SseEventSource eventSource = SseEventSource.target(sseTarget).build();
+ eventSource.register(EMPTY, throwable::set, completeLatch::countDown);
+ eventSource.open();
+ completeLatch.await(10_000, TimeUnit.MILLISECONDS);
+ MatcherAssert.assertThat(throwable.get(), Matchers.notNullValue());
+ MatcherAssert.assertThat(throwable.get().getClass(), Matchers.is(NotFoundException.class));
+ }
+
+ @Test
+ public void testError500() throws InterruptedException {
+ WebTarget sseTarget = target("sse/500");
+ AtomicReference<Throwable> throwable = new AtomicReference<>();
+ CountDownLatch completeLatch = new CountDownLatch(1);
+
+ SseEventSource eventSource = SseEventSource.target(sseTarget).build();
+ eventSource.register(EMPTY, throwable::set, completeLatch::countDown);
+ eventSource.open();
+ completeLatch.await(10_000, TimeUnit.MILLISECONDS);
+ MatcherAssert.assertThat(throwable.get(), Matchers.notNullValue());
+ MatcherAssert.assertThat(throwable.get().getClass(), Matchers.is(InternalServerErrorException.class));
+ }
+
+ @Test
+ public void testError400() throws InterruptedException {
+ WebTarget sseTarget = target("sse/400");
+ AtomicReference<Throwable> throwable = new AtomicReference<>();
+ CountDownLatch completeLatch = new CountDownLatch(1);
+
+ SseEventSource eventSource = SseEventSource.target(sseTarget).build();
+ eventSource.register(EMPTY, throwable::set, completeLatch::countDown);
+ eventSource.open();
+ completeLatch.await(10_000, TimeUnit.MILLISECONDS);
+ MatcherAssert.assertThat(throwable.get(), Matchers.notNullValue());
+ MatcherAssert.assertThat(throwable.get().getClass(), Matchers.is(BadRequestException.class));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 742cfbb..d4ff722 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -142,6 +142,9 @@
<contributor>
<name>Stepan Vavra</name>
</contributor>
+ <contributor>
+ <name>Dmytro Dovnar</name>
+ </contributor>
</contributors>
<licenses>
@@ -150,14 +153,14 @@
<url>http://www.eclipse.org/legal/epl-2.0</url>
<distribution>repo</distribution>
<comments>Except for 3rd content and examples.
- See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments>
+ See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments>
</license>
<license>
<name>GPL2 w/ CPE</name>
<url>https://www.gnu.org/software/classpath/license.html</url>
<distribution>repo</distribution>
<comments>Except for 3rd content and examples.
- See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments>
+ See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments>
</license>
<license>
<name>EDL 1.0</name>
@@ -176,9 +179,9 @@
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
<distribution>repo</distribution>
<comments>Google Guava @ org.glassfish.jersey.internal.guava,
- Dropwizard Monitoring inspired classes @ org.glassfish.jersey.server.internal.monitoring.core,
- Hibernate Validation classes @ org.glassfish.jersey.server.validation.internal.hibernate, and
- Jackson JAX-RS Providers @ org.glassfish.jersey.jackson.internal.jackson.jaxrs</comments>
+ Dropwizard Monitoring inspired classes @ org.glassfish.jersey.server.internal.monitoring.core,
+ Hibernate Validation classes @ org.glassfish.jersey.server.validation.internal.hibernate, and
+ Jackson JAX-RS Providers @ org.glassfish.jersey.jackson.internal.jackson.jaxrs</comments>
</license>
<license>
<name>Public Domain</name>
@@ -203,7 +206,7 @@
<url>http://www.opensource.org/licenses/mit-license.php</url>
<distribution>repo</distribution>
<comments>AngularJS, Bootstrap v3.3.7,
- jQuery Barcode plugin 0.3, KineticJS v4.7.1</comments>
+ jQuery Barcode plugin 0.3, KineticJS v4.7.1</comments>
</license>
<license>
<name>W3C license</name>
@@ -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>
@@ -425,12 +428,10 @@
junit.jupiter.execution.parallel.mode.default=same_thread
</configurationParameters>
</properties>
- <systemProperties>
- <property>
- <name>jersey.config.test.container.port</name>
- <value>${jersey.config.test.container.port}</value>
- </property>
- </systemProperties>
+ <systemPropertyVariables>
+ <jersey.config.test.container.port>${jersey.config.test.container.port}
+ </jersey.config.test.container.port>
+ </systemPropertyVariables>
<threadCount>124</threadCount>
</configuration>
<dependencies>
@@ -470,7 +471,7 @@
<doctitle>Jersey ${jersey.version} API Documentation</doctitle>
<windowtitle>Jersey ${jersey.version} API</windowtitle>
<bottom>
- <![CDATA[Copyright © 2007-2023,
+ <![CDATA[Copyright © 2007-2024,
<a href="http://www.oracle.com">Oracle</a>
and/or its affiliates.
All Rights Reserved. Use is subject to license terms.]]>
@@ -481,7 +482,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>
@@ -546,11 +547,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>
@@ -583,6 +579,7 @@
<configLocation>etc/config/checkstyle.xml</configLocation>
<suppressionsLocation>etc/config/checkstyle-suppressions.xml</suppressionsLocation>
<outputFile>${project.build.directory}/checkstyle/checkstyle-result.xml</outputFile>
+ <excludes>**/module-info.java</excludes>
</configuration>
<dependencies>
<dependency>
@@ -637,12 +634,10 @@
<skipTests>${skip.tests}</skipTests>
<skipITs>${skip.tests}</skipITs>
<argLine>${failsafe.coverage.argline}</argLine>
- <systemProperties>
- <property>
- <name>jersey.config.test.container.port</name>
- <value>${jersey.config.test.container.port}</value>
- </property>
- </systemProperties>
+ <systemPropertyVariables>
+ <jersey.config.test.container.port>${jersey.config.test.container.port}
+ </jersey.config.test.container.port>
+ </systemPropertyVariables>
</configuration>
<executions>
<execution>
@@ -795,25 +790,7 @@
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
- <version>1.10.12</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>5.1</version><!-- transitive dependency version increased from 5.0 -->
- <scope>runtime</scope>
+ <version>${mvn.ant.version}</version>
</dependency>
</dependencies>
</plugin>
@@ -865,7 +842,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>
@@ -882,6 +858,27 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>verify</id>
+ <phase>validate</phase>
+ <goals>
+ <!-- Fail the build if checkstyle rules for contributions are not met. -->
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <configLocation>etc/config/checkstyle-verify.xml</configLocation>
+ <consoleOutput>true</consoleOutput>
+ <failOnViolation>true</failOnViolation>
+ <includeTestSourceDirectory>true</includeTestSourceDirectory>
+ <excludes>**/module-info.java</excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
<extensions>
<extension>
@@ -943,23 +940,23 @@
<id>default-compile</id>
<configuration>
compile everything to ensure module-info contains right entries
- <release>11</release>
+ <release>${java.version}</release>
</configuration>
</execution>
- <execution>
+ <!--<execution>
<id>base-compile</id>
<goals>
<goal>compile</goal>
</goals>
- <!-- recompile everything for target VM except the module-info.java -->
+ <!– recompile everything for target VM except the module-info.java –>
<configuration>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
- <source>1.8</source>
- <target>1.8</target>
+ <!– <source>1.8</source>
+ <target>1.8</target>–>
</configuration>
- </execution>
+ </execution>-->
</executions>
</plugin>
</plugins>
@@ -979,9 +976,8 @@
</property>
</activation>
<properties>
-<!-- <release.tests.args>-Dskip.tests=true</release.tests.args>-->
+ <!-- <release.tests.args>-Dskip.tests=true</release.tests.args>-->
<skip.tests>true</skip.tests>
- <skip.e2e>true</skip.e2e>
</properties>
</profile>
<profile>
@@ -1007,7 +1003,7 @@
<activation>
<activeByDefault>false</activeByDefault>
<property>
- <name>!tests.excluded</name>
+ <name>!tests.excluded</name>
</property>
</activation>
<modules>
@@ -1103,10 +1099,10 @@
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
- <id>enforce-property</id>
- <goals>
- <goal>enforce</goal>
- </goals>
+ <id>enforce-property</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
<configuration>
<rules>
<requireProperty>
@@ -1140,14 +1136,6 @@
<version>${moxy.version}</version>
</dependency>
</dependencies>
- <repositories>
- <repository>
- <id>eclipselink.repository</id>
- <name>Eclipse Maven Repository</name>
- <url>https://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
- <layout>default</layout>
- </repository>
- </repositories>
</profile>
<profile>
<id>securityOff</id>
@@ -1165,7 +1153,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>
@@ -1186,29 +1174,29 @@
</distributionManagement>
</profile>
<profile>
- <id>jdk1.7+</id>
+ <id>sbom</id>
<activation>
- <jdk>[1.7,)</jdk>
+ <property>
+ <name>!skipSBOM</name>
+ </property>
</activation>
<build>
<plugins>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-checkstyle-plugin</artifactId>
+ <groupId>org.cyclonedx</groupId>
+ <artifactId>cyclonedx-maven-plugin</artifactId>
+ <version>${cyclonedx.mvn.plugin.version}</version>
+ <inherited>true</inherited>
<executions>
<execution>
- <id>verify</id>
- <phase>validate</phase>
+ <phase>package</phase>
<goals>
- <!-- Fail the build if checkstyle rules for contributions are not met. -->
- <goal>check</goal>
+ <goal>makeAggregateBom</goal>
</goals>
<configuration>
- <configLocation>etc/config/checkstyle-verify.xml</configLocation>
- <consoleOutput>true</consoleOutput>
- <failOnViolation>true</failOnViolation>
- <includeTestSourceDirectory>true</includeTestSourceDirectory>
- <excludes>**/module-info.java</excludes>
+ <!-- <schemaVersion>1.4</schemaVersion>-->
+ <projectType>framework</projectType>
+ <excludeTestProject>true</excludeTestProject>
</configuration>
</execution>
</executions>
@@ -1357,51 +1345,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>
@@ -1424,7 +1367,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>
@@ -1477,20 +1420,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 © 2007-2023,
+ <![CDATA[Copyright © 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>
@@ -1530,7 +1473,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>
@@ -1781,7 +1724,7 @@
<groupId>org.simpleframework</groupId>
<artifactId>simple-http</artifactId>
<version>${simple.version}</version>
- </dependency>
+ </dependency>
<dependency>
<groupId>org.simpleframework</groupId>
@@ -1936,8 +1879,8 @@
<version>${jakarta.el.version}</version>
</dependency>
<dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>jakarta.el</artifactId>
+ <groupId>org.glassfish.expressly</groupId>
+ <artifactId>expressly</artifactId>
<version>${jakarta.el.impl.version}</version>
</dependency>
@@ -2159,9 +2102,9 @@
</dependency>
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>${gson.version}</version>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${gson.version}</version>
</dependency>
<dependency>
@@ -2195,9 +2138,8 @@
<!-- <netbeans.hint.license>gf-cddl-gpl</netbeans.hint.license>-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-<!-- <release.tests.args>-Dmaven.test.skip=false</release.tests.args>-->
-<!-- <release.preparationGoals>clean install</release.preparationGoals>-->
- <skip.e2e>false</skip.e2e>
+ <!-- <release.tests.args>-Dmaven.test.skip=false</release.tests.args>-->
+ <!-- <release.preparationGoals>clean install</release.preparationGoals>-->
<skip.tests>false</skip.tests>
<xdk.absolute.path />
<surefire.security.argline />
@@ -2208,14 +2150,16 @@
<!-- Versions of Maven plugins -->
<antrun.mvn.plugin.version>3.1.0</antrun.mvn.plugin.version>
- <assembly.mvn.plugin.version>3.6.0</assembly.mvn.plugin.version>
- <enforcer.mvn.plugin.version>3.4.1</enforcer.mvn.plugin.version>
- <exec.mvn.plugin.version>3.1.0</exec.mvn.plugin.version>
- <buildhelper.mvn.plugin.version>3.4.0</buildhelper.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.4.0</clean.mvn.plugin.version>
+ <enforcer.mvn.plugin.version>3.5.0</enforcer.mvn.plugin.version>
+ <exec.mvn.plugin.version>3.4.1</exec.mvn.plugin.version>
+ <buildhelper.mvn.plugin.version>3.6.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.12.4</checkstyle.version>
- <compiler.mvn.plugin.version>3.11.0</compiler.mvn.plugin.version>
+ <checkstyle.mvn.plugin.version>3.4.0</checkstyle.mvn.plugin.version>
+ <checkstyle.version>10.17.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
generate too much for OSGi manifest.mf imports (awt etc). The version 3.11.0 however
@@ -2223,90 +2167,95 @@
but the jersey-common module which has to have the separate version for OSGi reasons.
-->
<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>
+ <cyclonedx.mvn.plugin.version>2.8.1</cyclonedx.mvn.plugin.version>
+ <dependency.mvn.plugin.version>3.7.1</dependency.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.1</failsafe.mvn.plugin.version>
+ <failsafe.mvn.plugin.version>3.3.1</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>
- <javadoc.mvn.plugin.version>3.6.0</javadoc.mvn.plugin.version>
- <jxr.mvn.plugin.version>3.3.1</jxr.mvn.plugin.version>
+ <jar.mvn.plugin.version>3.4.2</jar.mvn.plugin.version>
+ <javadoc.mvn.plugin.version>3.11.2</javadoc.mvn.plugin.version>
+ <jxr.mvn.plugin.version>3.4.0</jxr.mvn.plugin.version>
<paxexam.mvn.plugin.version>1.2.4</paxexam.mvn.plugin.version>
- <proguard.mvn.plugin.version>2.6.0</proguard.mvn.plugin.version>
+ <project.info.reports.mvn.plugin.version>3.6.2</project.info.reports.mvn.plugin.version>
<resources.mvn.plugin.version>3.3.1</resources.mvn.plugin.version>
- <shade.mvn.plugin.version>3.5.1</shade.mvn.plugin.version>
- <site.mvn.plugin.version>3.9.1</site.mvn.plugin.version>
- <source.mvn.plugin.version>3.3.0</source.mvn.plugin.version>
- <surefire.mvn.plugin.version>3.2.1</surefire.mvn.plugin.version>
+ <shade.mvn.plugin.version>3.6.0</shade.mvn.plugin.version>
+ <source.mvn.plugin.version>3.3.1</source.mvn.plugin.version>
+ <surefire.mvn.plugin.version>3.5.2</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>
<xml.mvn.plugin.version>1.1.0</xml.mvn.plugin.version>
+ <harness.testing.mvn.plugin.version>3.3.0</harness.testing.mvn.plugin.version>
<!-- END of Versions of Maven plugins -->
<!-- Dependency versions -->
<jersey.version>${project.version}</jersey.version>
- <arquillian.version>1.7.1.Final</arquillian.version>
+ <arquillian.version>1.8.0.Final</arquillian.version>
<arquillian.weld.version>3.0.1.Final</arquillian.weld.version> <!-- 3.0.2.Final fails microprofile TCK tests -->
<!-- asm is now source integrated - keeping this property to see the version -->
<!-- see core-server/src/main/java/jersey/repackaged/asm/.. -->
- <asm.version>9.6</asm.version>
+ <asm.version>9.7.1</asm.version>
<!--required for spring (ext) modules integration -->
- <aspectj.weaver.version>1.9.20.1</aspectj.weaver.version>
-<!-- <bnd.plugin.version>2.3.6</bnd.plugin.version>-->
+ <aspectj.weaver.version>1.9.22.1</aspectj.weaver.version>
+ <!-- <bnd.plugin.version>2.3.6</bnd.plugin.version>-->
<bouncycastle.version>1.70</bouncycastle.version>
- <commons.io.version>2.15.0</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.2</commons.logging.version>
- <fasterxml.classmate.version>1.6.0</fasterxml.classmate.version>
+ <commons.logging.version>1.3.4</commons.logging.version>
+ <fasterxml.classmate.version>1.7.0</fasterxml.classmate.version>
<felix.eventadmin.version>1.6.4</felix.eventadmin.version>
<felix.framework.security.version>2.8.4</felix.framework.security.version>
<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.21</gae.version>
- <groovy.version>4.0.15</groovy.version>
- <gson.version>2.10.1</gson.version>
+ <freemarker.version>2.3.33</freemarker.version>
+ <gae.version>2.0.29</gae.version>
+ <groovy.version>5.0.0-alpha-11</groovy.version>
+ <gson.version>2.11.0</gson.version>
<!--versions, extracted here due to maven-enforcer-plugin -->
-<!-- <commons.codec.version>1.15</commons.codec.version>-->
+ <!-- <commons.codec.version>1.15</commons.codec.version>-->
<com.uber.jaeger.version>0.27.0</com.uber.jaeger.version>
<org.codehaus.gmavenplus.version>3.0.2</org.codehaus.gmavenplus.version>
<!-- end of versions extracted here due to maven-enforcer-plugin -->
<!-- micrometer -->
- <micrometer.version>1.11.5</micrometer.version>
- <micrometer-tracing.version>1.0.11</micrometer-tracing.version>
+ <micrometer.version>1.12.4</micrometer.version>
+ <micrometer-tracing.version>1.0.12</micrometer-tracing.version>
<!-- microprofile -->
<microprofile.config.version>3.0.3</microprofile.config.version>
- <microprofile.rest.client.version>3.0.1</microprofile.rest.client.version>
- <helidon.config.version>3.0.2</helidon.config.version>
- <helidon.config.11.version>1.4.13</helidon.config.11.version> <!-- JDK 11- support -->
- <smallrye.config.version>3.0.0</smallrye.config.version>
+ <microprofile.rest.client3.version>3.0.1</microprofile.rest.client3.version>
+ <microprofile.rest.client.version>4.0</microprofile.rest.client.version>
+ <helidon.config.version>3.2.6</helidon.config.version>
+ <helidon.connector.version>3.2.8</helidon.connector.version>
+ <helidon.config.11.version>1.4.14</helidon.config.11.version> <!-- JDK 11- support -->
+ <smallrye.config.version>3.7.1</smallrye.config.version>
- <guava.version>31.1-jre</guava.version>
- <hamcrest.version>2.2</hamcrest.version>
- <helidon.jersey.connector.version>3.0.2</helidon.jersey.connector.version>
- <xmlunit.version>2.9.0</xmlunit.version>
+ <guava.version>33.3.0-jre</guava.version>
+ <hamcrest.version>3.0</hamcrest.version>
+ <xmlunit.version>2.10.0</xmlunit.version>
<httpclient.version>4.5.14</httpclient.version>
- <httpclient5.version>5.2.1</httpclient5.version>
- <jackson.version>2.15.3</jackson.version>
- <javassist.version>3.29.2-GA</javassist.version>
- <jboss.logging.version>3.5.3.Final</jboss.logging.version>
+ <httpclient5.version>5.3.1</httpclient5.version>
+ <jackson.version>2.18.0</jackson.version>
+ <javassist.version>3.30.2-GA</javassist.version>
<jettison.version>1.3.7</jettison.version> <!-- TODO: 1.3.8 doesn't work; AbstractJsonTest complexBeanWithAttributes -->
+ <jboss.vfs.version>3.3.2.Final</jboss.vfs.version>
+ <jboss.logging.version>3.6.1.Final</jboss.logging.version>
<jmh.version>1.37</jmh.version>
<jmockit.version>1.49</jmockit.version>
<junit4.version>4.13.2</junit4.version>
- <junit5.version>5.10.0</junit5.version>
- <junit-platform-suite.version>1.10.0</junit-platform-suite.version>
- <kryo.version>4.0.2</kryo.version>
- <mockito.version>3.12.4</mockito.version> <!-- CQ 17673 -->
- <mustache.version>0.9.10</mustache.version>
- <netty.version>4.1.100.Final</netty.version>
+ <junit5.version>5.11.4</junit5.version>
+ <junit-platform-suite.version>1.11.0</junit-platform-suite.version>
+ <junit-platform-suite.legacy.version>1.10.0</junit-platform-suite.legacy.version>
+ <kryo.version>4.0.3</kryo.version>
+ <mockito.version>4.11.0</mockito.version> <!-- CQ 17673 -->
+ <mustache.version>0.9.14</mustache.version>
+ <netty.version>4.1.112.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>
@@ -2322,21 +2271,23 @@
<servlet6.version>6.0.0</servlet6.version>
<simple.version>6.0.1</simple.version>
- <slf4j.version>2.0.9</slf4j.version>
- <spring6.version>6.0.13</spring6.version>
- <testng.version>7.8.0</testng.version>
- <testng6.version>6.9.13.6</testng6.version>
+ <slf4j.version>2.0.16</slf4j.version>
+ <spring6.version>6.0.18</spring6.version>
+ <testng.version>7.10.2</testng.version>
+ <testng6.version>6.14.3</testng6.version>
+ <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
<!-- Jakartified, eligible for CQ -->
<weld.api.version>5.0.SP3</weld.api.version>
- <weld.version>5.1.2.Final</weld.version>
+ <weld.version>5.1.3.Final</weld.version>
<weld3.version>3.1.9.Final</weld3.version>
<validation.impl.version>8.0.1.Final</validation.impl.version>
<!-- END of Jakartified, eligible for CQ -->
- <wiremock.version>2.27.2</wiremock.version>
+ <wiremock.jetty9.version>2.27.2</wiremock.jetty9.version>
+ <wiremock.jetty11.version>3.10.0</wiremock.jetty11.version>
<xerces.version>2.12.2</xerces.version>
<!-- Graal VM -->
- <graalvm.version>20.3.12</graalvm.version>
+ <graalvm.version>20.3.15</graalvm.version>
<!-- do not need CQs (below this line till the end of version properties)-->
<gf.impl.version>7.0.6</gf.impl.version>
@@ -2347,43 +2298,43 @@
<grizzly2.version>4.0.2</grizzly2.version>
<grizzly.client.version>1.16</grizzly.client.version>
<grizzly.npn.version>2.0.0</grizzly.npn.version>
- <hk2.version>3.0.5</hk2.version>
+ <hk2.version>3.0.6</hk2.version>
<hk2.osgi.version>org.glassfish.hk2.*;version="[3.0,4)"</hk2.osgi.version>
<hk2.jvnet.osgi.version>org.jvnet.hk2.*;version="[3.0,4)"</hk2.jvnet.osgi.version>
- <hk2.config.version>7.0.3</hk2.config.version>
+ <hk2.config.version>7.0.4</hk2.config.version>
<jsp.version>3.1.1</jsp.version>
- <jstl.version>3.0.0</jstl.version>
+ <jstl.version>3.0.2</jstl.version>
<jta.api.version>2.0.1</jta.api.version>
- <istack.commons.runtime.version>4.1.1</istack.commons.runtime.version>
- <jakarta.activation-api.version>2.1.1</jakarta.activation-api.version>
- <jakarta.activation.version>2.0.0</jakarta.activation.version>
+ <istack.commons.runtime.version>4.1.2</istack.commons.runtime.version>
+ <jakarta.activation-api.version>2.1.3</jakarta.activation-api.version>
+ <jakarta.activation.version>2.0.2</jakarta.activation.version>
<jakarta.el.version>5.0.1</jakarta.el.version>
- <jakarta.el.impl.version>5.0.0-M1</jakarta.el.impl.version>
+ <jakarta.el.impl.version>5.0.0</jakarta.el.impl.version>
<jakarta.annotation.osgi.version>jakarta.annotation.*;version="[2.0,3)"</jakarta.annotation.osgi.version>
<jakarta.annotation.version>2.1.1</jakarta.annotation.version>
<jakarta.inject.version>2.0.1</jakarta.inject.version>
<jakarta.interceptor.version>2.1.0</jakarta.interceptor.version>
- <jakarta.jsonp.version>2.1.2</jakarta.jsonp.version>
+ <jakarta.jsonp.version>2.1.3</jakarta.jsonp.version>
<jakarta.persistence.version>3.1.0</jakarta.persistence.version>
<jakarta.validation.api.version>3.0.2</jakarta.validation.api.version>
- <jakarta.jaxb.api.version>4.0.0</jakarta.jaxb.api.version>
- <jaxb.ri.version>4.0.2</jaxb.ri.version>
+ <jakarta.jaxb.api.version>4.0.2</jakarta.jaxb.api.version>
+ <jaxb.ri.version>4.0.5</jaxb.ri.version>
<jaxrs.api.spec.version>3.1</jaxrs.api.spec.version>
<jaxrs.api.impl.version>3.1.0</jaxrs.api.impl.version>
<jetty.osgi.version>org.eclipse.jetty.*;version="[11,15)"</jetty.osgi.version>
- <jetty.version>12.0.3</jetty.version>
- <jetty9.version>9.4.53.v20231009</jetty9.version>
+ <jetty.version>12.0.14</jetty.version>
+ <jetty9.version>9.4.56.v20240826</jetty9.version>
<jetty.servlet.api.version>5.0.2</jetty.servlet.api.version>
- <jetty11.version>11.0.18</jetty11.version>
- <jetty.plugin.version>12.0.3</jetty.plugin.version>
- <jsonb.api.version>3.0.0</jsonb.api.version>
- <jsonp.ri.version>1.1.1</jsonp.ri.version>
- <jsonp.jaxrs.version>1.1.1</jsonp.jaxrs.version>
- <moxy.version>4.0.2</moxy.version>
- <yasson.version>3.0.3</yasson.version>
+ <jetty11.version>11.0.24</jetty11.version>
+ <jetty.plugin.version>12.0.8</jetty.plugin.version>
+ <jsonb.api.version>3.0.1</jsonb.api.version>
+ <jsonp.ri.version>1.1.7</jsonp.ri.version>
+ <jsonp.jaxrs.version>1.1.7</jsonp.jaxrs.version>
+ <moxy.version>4.0.4</moxy.version>
+ <yasson.version>3.0.4</yasson.version>
<!-- END of Jakartified -->
<javax.annotation.version>1.3.2</javax.annotation.version> <!--Deprecated, used only for @generated annotation in perf tests -->
<mimepull.version>1.9.15</mimepull.version>
</properties>
-</project>
+</project>
\ No newline at end of file
diff --git a/security/oauth1-client/pom.xml b/security/oauth1-client/pom.xml
index dc52d0b..1d59d2e 100644
--- a/security/oauth1-client/pom.xml
+++ b/security/oauth1-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/security/oauth1-server/pom.xml b/security/oauth1-server/pom.xml
index f67b540..d038c46 100644
--- a/security/oauth1-server/pom.xml
+++ b/security/oauth1-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/security/oauth1-signature/pom.xml b/security/oauth1-signature/pom.xml
index 9bd521a..c8c2287 100644
--- a/security/oauth1-signature/pom.xml
+++ b/security/oauth1-signature/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/security/oauth2-client/pom.xml b/security/oauth2-client/pom.xml
index e5f32ab..e4e8e10 100644
--- a/security/oauth2-client/pom.xml
+++ b/security/oauth2-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/security/pom.xml b/security/pom.xml
index 3ed5e52..1e9cd93 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/core/pom.xml b/test-framework/core/pom.xml
index d292c14..9922dad 100644
--- a/test-framework/core/pom.xml
+++ b/test-framework/core/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java
index 243466c..fe85e9c 100644
--- a/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java
+++ b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseyTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -621,6 +621,7 @@
if (!isConcurrent() || activeThreadCount.getAndIncrement() == 0) {
registerLogHandlerIfEnabled();
final TestContainer testContainer = createTestContainer(context);
+ testContainer.configureContainer();
// Set current instance of test container and start it.
setTestContainer(testContainer);
diff --git a/test-framework/core/src/main/java/org/glassfish/jersey/test/spi/TestContainer.java b/test-framework/core/src/main/java/org/glassfish/jersey/test/spi/TestContainer.java
index 68a5bf8..d2a0030 100644
--- a/test-framework/core/src/main/java/org/glassfish/jersey/test/spi/TestContainer.java
+++ b/test-framework/core/src/main/java/org/glassfish/jersey/test/spi/TestContainer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -54,4 +54,13 @@
* Stop the container.
*/
public void stop();
+
+ /**
+ * optional method to configure container before it's being started
+ *
+ * @since 2.44
+ */
+ default void configureContainer() {
+
+ }
}
diff --git a/test-framework/maven/container-runner-maven-plugin/pom.xml b/test-framework/maven/container-runner-maven-plugin/pom.xml
index a012326..672ba6e 100644
--- a/test-framework/maven/container-runner-maven-plugin/pom.xml
+++ b/test-framework/maven/container-runner-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,7 +36,6 @@
</description>
<properties>
- <groovy.version>3.0.17</groovy.version>
<groovy-eclipse-compiler.version>3.7.0</groovy-eclipse-compiler.version>
<groovy-eclipse-batch.version>3.0.8-01</groovy-eclipse-batch.version>
<maven.version>3.9.2</maven.version>
@@ -116,7 +115,7 @@
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
- <version>3.3.0</version>
+ <version>${harness.testing.mvn.plugin.version}</version>
<scope>test</scope>
</dependency>
@@ -126,6 +125,14 @@
<version>${org.codehaus.gmavenplus.version}</version>
<exclusions>
<exclusion>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.ant</groupId>
+ <artifactId>ant</artifactId>
+ </exclusion>
+ <exclusion>
<groupId>org.apache.maven.shared</groupId>
<artifactId>file-management</artifactId>
</exclusion>
@@ -161,6 +168,14 @@
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-archiver</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ </exclusion>
</exclusions>
</dependency>
@@ -178,24 +193,10 @@
</dependency>
<dependency>
- <groupId>org.codehaus.groovy</groupId>
+ <groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<type>pom</type>
<version>${groovy.version}</version>
- <exclusions>
- <exclusion>
- <groupId>org.apache.ant</groupId>
- <artifactId>ant-launcher</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.ant</groupId>
- <artifactId>ant</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
index b04c36b..865afb7 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/RunnerMojo.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,7 +23,7 @@
import org.apache.maven.project.MavenProject
import java.nio.file.Files
-import java.nio.file.Paths
+import java.nio.file.Path
import java.util.regex.Pattern
/**
@@ -96,7 +96,7 @@
def command = string.split(" +(?=((.*?(?<!\\\\)'){2})*[^']*\$)")
- return command?.length > 0 && Files.exists(Paths.get(command[0])) ? command : ["sh"]
+ return command?.length > 0 && Files.exists(Path.of(command[0])) ? command : ["sh"]
}
abstract Map commonEnvironment()
@@ -184,8 +184,8 @@
sb.append(System.lineSeparator())
def matcher = Pattern.compile("(#![^\r\n]*)(.*)", Pattern.DOTALL).matcher(new String(shellContent))
def string = matcher.matches() ? matcher.replaceFirst("\$1${sb.toString()}\$2") : sb.append(shellContent).toString()
- Paths.get(scriptsDirectory).toFile().mkdirs()
- def reExecutableShell = Paths.get(scriptsDirectory, Paths.get(shell).fileName.toString())
+ Path.of(scriptsDirectory).toFile().mkdirs()
+ def reExecutableShell = Path.of(scriptsDirectory, Path.of(shell).fileName.toString())
Files.write(reExecutableShell, string.bytes)
getLog().info("Re-executable shell written to: $reExecutableShell")
} catch (Exception e) {
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
index c72b020..9d8a6ba 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/gf4/AbstractGlassfishRunnerMojo.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,7 +22,7 @@
import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
import org.glassfish.jersey.test.maven.runner.RunnerMojo
-import java.nio.file.Paths
+import java.nio.file.Path
/**
* Abstract class for all Glassfish4 related mojos.
*
@@ -58,8 +58,8 @@
@Override
void execute() throws MojoExecutionException, MojoFailureException {
- asHome = Paths.get(asHome).isAbsolute() ? asHome : Paths.get(distDir, distSubdir, asHome)
- logFile = Paths.get(logFile).isAbsolute()? logFile : Paths.get(asHome, "domains", domain, "logs", logFile)
+ asHome = Path.of(asHome).isAbsolute() ? asHome : Path.of(distDir, distSubdir, asHome)
+ logFile = Path.of(logFile).isAbsolute()? logFile : Path.of(asHome, "domains", domain, "logs", logFile)
executeRunner()
}
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
index d98b59d..2b041e8 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/tomcat/AbstractTomcatRunnerMojo.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,7 +22,7 @@
import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
import org.glassfish.jersey.test.maven.runner.RunnerMojo
-import java.nio.file.Paths
+import java.nio.file.Path
/**
* Abstract class for all Tomcat related mojos.
*
@@ -47,8 +47,8 @@
@Override
void execute() throws MojoExecutionException, MojoFailureException {
- catalinaHome = Paths.get(catalinaHome).isAbsolute() ? catalinaHome : Paths.get(distDir, distSubdir, catalinaHome)
- logFile = logFile ?: Paths.get(catalinaHome, "logs", "catalina.out").toString()
+ catalinaHome = Path.of(catalinaHome).isAbsolute() ? catalinaHome : Path.of(distDir, distSubdir, catalinaHome)
+ logFile = logFile ?: Path.of(catalinaHome, "logs", "catalina.out").toString()
executeRunner()
}
diff --git a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
index 3fa9ffd..6232472 100644
--- a/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
+++ b/test-framework/maven/container-runner-maven-plugin/src/main/groovy/org/glassfish/jersey/test/maven/runner/wls/AbstractWlsRunnerMojo.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,7 +22,7 @@
import org.codehaus.gmavenplus.mojo.AbstractGroovyMojo
import org.glassfish.jersey.test.maven.runner.RunnerMojo
-import java.nio.file.Paths
+import java.nio.file.Path
/**
* Abstract class for all Weblogic related mojos.
@@ -52,8 +52,8 @@
@Override
void execute() throws MojoExecutionException, MojoFailureException {
- mwHome = Paths.get(mwHome).isAbsolute() ? mwHome : Paths.get(distDir, distSubdir, mwHome)
- logFile = logFile ?: Paths.get(mwHome, domain, "wls.log").toString()
+ mwHome = Path.of(mwHome).isAbsolute() ? mwHome : Path.of(distDir, distSubdir, mwHome)
+ logFile = logFile ?: Path.of(mwHome, domain, "wls.log").toString()
executeRunner()
}
diff --git a/test-framework/maven/custom-enforcer-rules/pom.xml b/test-framework/maven/custom-enforcer-rules/pom.xml
index 9995912..a05ccd9 100644
--- a/test-framework/maven/custom-enforcer-rules/pom.xml
+++ b/test-framework/maven/custom-enforcer-rules/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -53,24 +53,8 @@
<artifactId>commons-io</artifactId>
</exclusion>
<exclusion>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.aether</groupId>
- <artifactId>aether-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.codehaus.plexus</groupId>
- <artifactId>plexus-classworlds</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.codehaus.plexus</groupId>
- <artifactId>plexus-utils</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven</groupId>
diff --git a/test-framework/maven/pom.xml b/test-framework/maven/pom.xml
index db30ce7..3bc930e 100644
--- a/test-framework/maven/pom.xml
+++ b/test-framework/maven/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/memleak-test-common/pom.xml b/test-framework/memleak-test-common/pom.xml
index 96b2d91..003d5bb 100644
--- a/test-framework/memleak-test-common/pom.xml
+++ b/test-framework/memleak-test-common/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java b/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
index d519d3f..ecfe68e 100644
--- a/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
+++ b/test-framework/memleak-test-common/src/main/java/org/glassfish/jersey/test/memleak/common/MemoryLeakUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,7 +23,7 @@
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
@@ -121,7 +121,7 @@
throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, IOException {
conditionallyInitHotSpotDiagnosticMXBean();
try {
- java.nio.file.Files.deleteIfExists(Paths.get(fileName));
+ java.nio.file.Files.deleteIfExists(Path.of(fileName));
} catch (IOException e) {
// do nothing and try to go further
}
diff --git a/test-framework/pom.xml b/test-framework/pom.xml
index b9034e9..d5f8c78 100644
--- a/test-framework/pom.xml
+++ b/test-framework/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -44,6 +44,12 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ </exclusion>
+ </exclusions>
<scope>compile</scope>
</dependency>
<dependency>
diff --git a/test-framework/providers/bundle/pom.xml b/test-framework/providers/bundle/pom.xml
index 2a9b77b..19a2ffb 100644
--- a/test-framework/providers/bundle/pom.xml
+++ b/test-framework/providers/bundle/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/external/pom.xml b/test-framework/providers/external/pom.xml
index 6849ec8..8575a36 100644
--- a/test-framework/providers/external/pom.xml
+++ b/test-framework/providers/external/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/grizzly2/pom.xml b/test-framework/providers/grizzly2/pom.xml
index a503c36..750fa45 100644
--- a/test-framework/providers/grizzly2/pom.xml
+++ b/test-framework/providers/grizzly2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -53,5 +53,10 @@
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/test-framework/providers/inmemory/pom.xml b/test-framework/providers/inmemory/pom.xml
index 3719c42..03516a3 100644
--- a/test-framework/providers/inmemory/pom.xml
+++ b/test-framework/providers/inmemory/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/jdk-http/pom.xml b/test-framework/providers/jdk-http/pom.xml
index d17b88f..d7edd0d 100644
--- a/test-framework/providers/jdk-http/pom.xml
+++ b/test-framework/providers/jdk-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/jetty-http2/pom.xml b/test-framework/providers/jetty-http2/pom.xml
index 76a7920..ad00f4e 100644
--- a/test-framework/providers/jetty-http2/pom.xml
+++ b/test-framework/providers/jetty-http2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -49,6 +49,11 @@
<artifactId>jersey-container-jetty-http2</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/test-framework/providers/jetty/pom.xml b/test-framework/providers/jetty/pom.xml
index cc9f4b5..7758309 100644
--- a/test-framework/providers/jetty/pom.xml
+++ b/test-framework/providers/jetty/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -108,6 +108,13 @@
<activation>
<jdk>[17,)</jdk>
</activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
<build>
<directory>${java17.build.outputDirectory}</directory>
<plugins>
diff --git a/test-framework/providers/jetty/src/main/java/org/glassfish/jersey/test/jetty/JettyTestContainerProperties.java b/test-framework/providers/jetty/src/main/java/org/glassfish/jersey/test/jetty/JettyTestContainerProperties.java
new file mode 100644
index 0000000..beabef2
--- /dev/null
+++ b/test-framework/providers/jetty/src/main/java/org/glassfish/jersey/test/jetty/JettyTestContainerProperties.java
@@ -0,0 +1,36 @@
+/*
+ * 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.test.jetty;
+
+import org.glassfish.jersey.internal.util.PropertiesClass;
+
+/**
+ * Properties which relates only to Jetty test container configuration
+ *
+ * @since 2.44
+ */
+@PropertiesClass
+public class JettyTestContainerProperties {
+
+ /**
+ * Parameter which allows settings custom header size for request and response.
+ *
+ * @since 2.44
+ */
+ public static final String HEADER_SIZE = "jersey.test.jetty.container.header.size";
+
+}
diff --git a/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java b/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
index 315c49d..b487361 100644
--- a/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
+++ b/test-framework/providers/jetty/src/main/java11/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 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,6 +16,7 @@
package org.glassfish.jersey.test.jetty;
+import java.util.Map;
import jakarta.ws.rs.ProcessingException;
import org.glassfish.jersey.test.jetty.internal.LocalizationMessages;
import org.glassfish.jersey.test.DeploymentContext;
@@ -26,6 +27,13 @@
public class JettyTestContainerFactory implements TestContainerFactory {
+ public JettyTestContainerFactory() {
+ }
+
+ public JettyTestContainerFactory(Map<String, Object> properties) {
+ }
+
+
@Override
public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
throw new ProcessingException(LocalizationMessages.NOT_SUPPORTED());
diff --git a/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java b/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
index de1ba2c..1af49d5 100644
--- a/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
+++ b/test-framework/providers/jetty/src/main/java17/org/glassfish/jersey/test/jetty/JettyTestContainerFactory.java
@@ -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
@@ -17,11 +17,13 @@
package org.glassfish.jersey.test.jetty;
import java.net.URI;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.ws.rs.core.UriBuilder;
+import org.eclipse.jetty.server.HttpConnectionFactory;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
import org.glassfish.jersey.test.DeploymentContext;
@@ -42,16 +44,21 @@
*/
public class JettyTestContainerFactory implements TestContainerFactory {
+ private final Map<String, Object> propertiesMap;
+
private static class JettyTestContainer implements TestContainer {
private static final Logger LOGGER = Logger.getLogger(JettyTestContainer.class.getName());
+ private final Map<String, Object> propertiesMap;
+
private URI baseUri;
private final Server server;
-
- private JettyTestContainer(final URI baseUri, final DeploymentContext context) {
+ private JettyTestContainer(final URI baseUri, final DeploymentContext context, final Map<String, Object> propertiesMap) {
final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
+ this.propertiesMap = propertiesMap;
+
if (!"/".equals(base.getRawPath())) {
throw new TestContainerException(String.format(
"Cannot deploy on %s. Jetty HTTP container only supports deployment on root path.",
@@ -69,6 +76,26 @@
}
@Override
+ public void configureContainer() {
+
+ if (propertiesMap == null
+ || !propertiesMap.containsKey(JettyTestContainerProperties.HEADER_SIZE)) {
+ return;
+ }
+
+ for (Connector c : server.getConnectors()) {
+ c.getConnectionFactory(HttpConnectionFactory.class)
+ .getHttpConfiguration().setRequestHeaderSize(
+ (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
+ c.getConnectionFactory(HttpConnectionFactory.class)
+ .getHttpConfiguration().setResponseHeaderSize(
+ (Integer) propertiesMap.get(JettyTestContainerProperties.HEADER_SIZE));
+ c.getConnectionFactory(HttpConnectionFactory.class);
+ }
+
+ }
+
+ @Override
public ClientConfig getClientConfig() {
return null;
}
@@ -123,6 +150,14 @@
@Override
public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
- return new JettyTestContainer(baseUri, context);
+ return new JettyTestContainer(baseUri, context, propertiesMap);
}
-}
+
+ public JettyTestContainerFactory() {
+ this(null);
+ }
+
+ public JettyTestContainerFactory(Map<String, Object> properties) {
+ this.propertiesMap = properties;
+ }
+}
\ No newline at end of file
diff --git a/test-framework/providers/jetty11-http2/pom.xml b/test-framework/providers/jetty11-http2/pom.xml
deleted file mode 100644
index 9a29a03..0000000
--- a/test-framework/providers/jetty11-http2/pom.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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
-
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>project</artifactId>
- <groupId>org.glassfish.jersey.test-framework.providers</groupId>
- <version>3.5.99-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>jersey-test-framework-provider-jetty-http2</artifactId>
- <packaging>jar</packaging>
- <name>jersey-test-framework-provider-jetty-http2</name>
-
- <description>Jersey Test Framework - Jetty HTTP2 container</description>
-
- <dependencies>
- <dependency>
- <groupId>org.glassfish.jersey.test-framework</groupId>
- <artifactId>jersey-test-framework-core</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.glassfish.jersey.containers</groupId>
- <artifactId>jersey-container-jetty-http2</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java b/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java
deleted file mode 100644
index 867db08..0000000
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/Jetty11Http2TestContainerFactory.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-package org.glassfish.jersey.test.jetty11.http2;
-
-import java.net.URI;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jakarta.ws.rs.core.UriBuilder;
-
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.jetty.http2.Jetty11Http2ContainerFactory;
-import org.glassfish.jersey.test.DeploymentContext;
-import org.glassfish.jersey.test.spi.TestContainer;
-import org.glassfish.jersey.test.spi.TestContainerException;
-import org.glassfish.jersey.test.spi.TestContainerFactory;
-import org.glassfish.jersey.test.spi.TestHelper;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-
-/**
- * Factory for testing {@link Jetty11Http2ContainerFactory}.
- *
- */
-public final class Jetty11Http2TestContainerFactory implements TestContainerFactory {
-
- private static class JettyHttp2TestContainer implements TestContainer {
-
- private static final Logger LOGGER = Logger.getLogger(JettyHttp2TestContainer.class.getName());
-
- private URI baseUri;
- private final Server server;
-
- private JettyHttp2TestContainer(final URI baseUri, final DeploymentContext context) {
- final URI base = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();
-
- if (!"/".equals(base.getRawPath())) {
- throw new TestContainerException(String.format(
- "Cannot deploy on %s. Jetty HTTP2 container only supports deployment on root path.",
- base.getRawPath()));
- }
-
- this.baseUri = base;
-
- if (LOGGER.isLoggable(Level.INFO)) {
- LOGGER.info("Creating JettyHttp2TestContainer configured at the base URI "
- + TestHelper.zeroPortToAvailablePort(baseUri));
- }
-
- this.server = Jetty11Http2ContainerFactory.createHttp2Server(this.baseUri, context.getResourceConfig(), false);
- }
-
- @Override
- public ClientConfig getClientConfig() {
- return null;
- }
-
- @Override
- public URI getBaseUri() {
- return baseUri;
- }
-
- @Override
- public void start() {
- if (server.isStarted()) {
- LOGGER.log(Level.WARNING, "Ignoring start request - JettyHttp2TestContainer is already started.");
- } else {
- LOGGER.log(Level.FINE, "Starting JettyHttp2TestContainer...");
- try {
- server.start();
-
- if (baseUri.getPort() == 0) {
- int port = 0;
- for (final Connector connector : server.getConnectors()) {
- if (connector instanceof ServerConnector) {
- port = ((ServerConnector) connector).getLocalPort();
- break;
- }
- }
-
- baseUri = UriBuilder.fromUri(baseUri).port(port).build();
-
- LOGGER.log(Level.INFO, "Started JettyHttp2TestContainer at the base URI " + baseUri);
- }
- } catch (Exception e) {
- throw new TestContainerException(e);
- }
- }
- }
-
- @Override
- public void stop() {
- if (server.isStarted()) {
- LOGGER.log(Level.FINE, "Stopping JettyHttp2TestContainer...");
- try {
- this.server.stop();
- } catch (Exception ex) {
- LOGGER.log(Level.WARNING, "Error Stopping JettyHttp2TestContainer...", ex);
- }
- } else {
- LOGGER.log(Level.WARNING, "Ignoring stop request - JettyHttp2TestContainer is already stopped.");
- }
- }
- }
-
- @Override
- public TestContainer create(final URI baseUri, final DeploymentContext context) throws IllegalArgumentException {
- return new JettyHttp2TestContainer(baseUri, context);
- }
-}
diff --git a/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory b/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
deleted file mode 100644
index 0edcf72..0000000
--- a/test-framework/providers/jetty11-http2/src/main/resources/META-INF/services/org.glassfish.jersey.test.spi.TestContainerFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.glassfish.jersey.test.jetty11.http2.Jetty11Http2TestContainerFactory
diff --git a/test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties b/test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
deleted file mode 100644
index f10b03c..0000000
--- a/test-framework/providers/jetty11-http2/src/main/resources/org/glassfish/jersey/test/jetty11/http2/localization.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
-#
-# This program and the accompanying materials are made available under the
-# terms of the Eclipse Public License v. 2.0, which is available at
-# http://www.eclipse.org/legal/epl-2.0.
-#
-# This Source Code may also be made available under the following Secondary
-# Licenses when the conditions for such availability set forth in the
-# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
-# version 2 with the GNU Classpath Exception, which is available at
-# https://www.gnu.org/software/classpath/license.html.
-#
-# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-#
-
-# {0} - status code; {1} - status reason message
-not.supported=Jetty container is not supported on JDK version less than 17.
diff --git a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java
deleted file mode 100644
index ac93ccb..0000000
--- a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/AvailablePortJetty11Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-package org.glassfish.jersey.test.jetty11.http2;
-
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.test.DeploymentContext;
-import org.glassfish.jersey.test.JerseyTest;
-import org.glassfish.jersey.test.TestProperties;
-import org.glassfish.jersey.test.spi.TestContainerFactory;
-
-import org.junit.jupiter.api.Test;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-/**
- * Tests finding an available port for container.
- *
- */
-public class AvailablePortJetty11Test extends JerseyTest {
-
- @Override
- protected TestContainerFactory getTestContainerFactory() {
- return new Jetty11Http2TestContainerFactory();
- }
-
- @Path("AvailablePortJettyTest")
- public static class TestResource {
- @GET
- public String get() {
- return "GET";
- }
- }
-
- @Override
- protected DeploymentContext configureDeployment() {
- forceSet(TestProperties.CONTAINER_PORT, "0");
-
- return DeploymentContext.builder(new ResourceConfig(TestResource.class)).build();
- }
-
- @Test
- public void testGet() {
- assertThat(target().getUri().getPort(), not(0));
- assertThat(getBaseUri().getPort(), not(0));
-
- assertThat(target("AvailablePortJettyTest").request().get(String.class), equalTo("GET"));
- }
-}
diff --git a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java b/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java
deleted file mode 100644
index 0ec4c06..0000000
--- a/test-framework/providers/jetty11-http2/src/test/java/org/glassfish/jersey/test/jetty11/http2/Jetty11ContainerTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-package org.glassfish.jersey.test.jetty11.http2;
-
-import java.net.URI;
-import java.util.List;
-
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.core.Response;
-
-import org.glassfish.jersey.inject.hk2.DelayedHk2InjectionManager;
-import org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager;
-import org.glassfish.jersey.internal.inject.InjectionManager;
-import org.glassfish.jersey.jetty.http2.Jetty11Http2ContainerFactory;
-import org.glassfish.jersey.jetty.Jetty11HttpContainer;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.test.JerseyTest;
-
-import org.glassfish.hk2.api.ServiceLocator;
-
-import org.jvnet.hk2.internal.ServiceLocatorImpl;
-
-import org.eclipse.jetty.server.Server;
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/**
- * Test class for {@link Jetty11HttpContainer}.
- *
- */
-public class Jetty11ContainerTest extends JerseyTest {
-
- /**
- * Creates new instance.
- */
- public Jetty11ContainerTest() {
- super(new Jetty11Http2TestContainerFactory());
- }
-
- @Override
- protected ResourceConfig configure() {
- return new ResourceConfig(Resource.class);
- }
-
- /**
- * Test resource class.
- */
- @Path("one")
- public static class Resource {
-
- /**
- * Test resource method.
- *
- * @return Test simple string response.
- */
- @GET
- public String getSomething() {
- return "get";
- }
- }
-
- @Test
- /**
- * Test {@link Server Jetty Server} container.
- */
- public void testJettyContainerTarget() {
- final Response response = target().path("one").request().get();
-
- assertEquals(200, response.getStatus(), "Response status unexpected.");
- assertEquals("get", response.readEntity(String.class), "Response entity unexpected.");
- }
-
- /**
- * Test that defined ServiceLocator becomes a parent of the newly created service locator.
- */
- @Test
- public void testParentServiceLocator() {
- final ServiceLocator locator = new ServiceLocatorImpl("MyServiceLocator", null);
- final Server server = Jetty11Http2ContainerFactory.createHttp2Server(URI.create("http://localhost:9876"),
- new ResourceConfig(Resource.class), false, locator);
- final Jetty11HttpContainer container = (Jetty11HttpContainer) server.getHandler();
- final InjectionManager injectionManager = container.getApplicationHandler().getInjectionManager();
-
- ServiceLocator serviceLocator;
- if (injectionManager instanceof ImmediateHk2InjectionManager) {
- serviceLocator = ((ImmediateHk2InjectionManager) injectionManager).getServiceLocator();
- } else if (injectionManager instanceof DelayedHk2InjectionManager) {
- serviceLocator = ((DelayedHk2InjectionManager) injectionManager).getServiceLocator();
- } else {
- throw new RuntimeException("Invalid Hk2 InjectionManager");
- }
- assertTrue(serviceLocator.getParent() == locator,
- "Application injection manager was expected to have defined parent locator");
- }
- @Test
- public void testHttp2Container() {
- final ServiceLocator locator = new ServiceLocatorImpl("MyServiceLocator", null);
- final Server server = Jetty11Http2ContainerFactory.createHttp2Server(URI.create("http://localhost:9876"),
- new ResourceConfig(Resource.class), true, locator);
- final List<String> protocols = server.getConnectors()[0].getProtocols();
- assertTrue(protocols.contains("h2") || protocols.contains("h2c"));
- }
-}
diff --git a/test-framework/providers/netty/pom.xml b/test-framework/providers/netty/pom.xml
index 5342501..ff41bf8 100644
--- a/test-framework/providers/netty/pom.xml
+++ b/test-framework/providers/netty/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/pom.xml b/test-framework/providers/pom.xml
index 65e175f..de2ff26 100644
--- a/test-framework/providers/pom.xml
+++ b/test-framework/providers/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/providers/simple/pom.xml b/test-framework/providers/simple/pom.xml
index fee2df4..19368a5 100644
--- a/test-framework/providers/simple/pom.xml
+++ b/test-framework/providers/simple/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/test-framework/util/pom.xml b/test-framework/util/pom.xml
index 263330f..67077f8 100644
--- a/test-framework/util/pom.xml
+++ b/test-framework/util/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -54,6 +54,11 @@
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
index b729861..8e7f5b7 100644
--- a/tests/e2e-client/pom.xml
+++ b/tests/e2e-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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>
@@ -114,20 +113,10 @@
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
- <artifactId>jersey-bean-validation</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-entity-filtering</artifactId>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.glassfish.jersey.ext</groupId>
- <artifactId>jersey-mvc-bean-validation</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<scope>test</scope>
@@ -313,29 +302,6 @@
<version>${slf4j.version}</version>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <executions>
- <execution>
- <id>default-testCompile</id>
- <phase>test-compile</phase>
- <configuration>
- <testExcludes>
- <testExclude>org/glassfish/jersey/tests/e2e/client/connector/proxy/Proxy*Test.java</testExclude>
- <testExclude>org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java</testExclude>
- </testExcludes>
- </configuration>
- <goals>
- <goal>testCompile</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
</profile>
<profile>
@@ -355,6 +321,7 @@
<configuration>
<testExcludes>
<testExclude>org/glassfish/jersey/tests/e2e/client/connector/proxy/Proxy*Test.java</testExclude>
+ <testExclude>org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java</testExclude>
<testExclude>org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java</testExclude>
</testExcludes>
</configuration>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java
index 8b54346..951de51 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.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
@@ -35,6 +35,7 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
@@ -57,7 +58,7 @@
private static final Logger LOGGER = Logger.getLogger(ResponseReadAndBufferEntityTest.class.getName());
- public static class CorruptableInputStream extends InputStream {
+ public static class CorruptableInputStream extends InputStreamWrapper {
private final AtomicInteger closeCounter = new AtomicInteger(0);
@@ -71,53 +72,16 @@
}
@Override
- public synchronized int read() throws IOException {
+ protected InputStream getWrapped() {
+ return delegate;
+ }
+
+ @Override
+ protected InputStream getWrappedIOE() throws IOException {
if (corruptRead) {
corrupt();
}
- return delegate.read();
- }
-
- @Override
- public int read(final byte[] b) throws IOException {
- if (corruptRead) {
- corrupt();
- }
- return delegate.read(b);
- }
-
- @Override
- public int read(final byte[] b, final int off, final int len) throws IOException {
- if (corruptRead) {
- corrupt();
- }
- return delegate.read(b, off, len);
- }
-
- @Override
- public long skip(final long n) throws IOException {
- if (corruptRead) {
- corrupt();
- }
- return delegate.skip(n);
- }
-
- @Override
- public int available() throws IOException {
- if (corruptRead) {
- corrupt();
- }
- return delegate.available();
- }
-
- @Override
- public boolean markSupported() {
- return delegate.markSupported();
- }
-
- @Override
- public void mark(final int readAheadLimit) {
- delegate.mark(readAheadLimit);
+ return delegate;
}
@Override
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/FutureCancelTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/FutureCancelTest.java
new file mode 100644
index 0000000..72b2d41
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/FutureCancelTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.client.connector;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
+import org.glassfish.jersey.client.AbstractRxInvoker;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.JerseyInvocation;
+import org.glassfish.jersey.client.RequestEntityProcessing;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.CompletionStageRxInvoker;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.RxInvokerProvider;
+import jakarta.ws.rs.client.SyncInvoker;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class FutureCancelTest extends JerseyTest {
+
+ public static final long SLEEP = 100L;
+
+ public static List<ConnectorProvider> testData() {
+ return Arrays.asList(
+ new ApacheConnectorProvider(),
+ new Apache5ConnectorProvider(),
+ new HttpUrlConnectorProvider(),
+ new NettyConnectorProvider()
+ );
+ }
+
+ @Path("/")
+ public static class FutureCancelResource {
+ @GET
+ public ChunkedOutput<String> sendData() {
+ ChunkedOutput<String> chunkedOutput = new ChunkedOutput<>(String.class);
+ Thread newThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i != 100; i++) {
+ try {
+ chunkedOutput.write(String.valueOf(i));
+ Thread.sleep(SLEEP);
+ } catch (Exception e) {
+ // consume
+ }
+ }
+ }
+ });
+ newThread.start();
+
+ return chunkedOutput;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(FutureCancelResource.class);
+ }
+
+ @ParameterizedTest
+ @MethodSource("testData")
+ public void testFutureCancel(ConnectorProvider connectorProvider) throws InterruptedException, ExecutionException {
+ ClientConfig config = new ClientConfig();
+ config.connectorProvider(connectorProvider);
+
+ Future<List<String>> future = ClientBuilder.newClient(config)
+ .register(new FutureCancelRxInvokerProvider())
+ .property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED)
+ .target(target().getUri()).request().rx(FutureCancelRxInvoker.class).get().toCompletableFuture();
+
+ int expectedSize = 2;
+
+ while (RX_LIST.size() < expectedSize) {
+ Thread.sleep(SLEEP);
+ }
+ future.cancel(true);
+
+ Thread.sleep(2 * SLEEP); // wait to see no new messages arrive
+ int size = RX_LIST.size(); // some might have beween RX_LIST.size() and cancel()
+ while (size > expectedSize) { // be sure no more come
+ Thread.sleep(SLEEP);
+ expectedSize = size;
+ size = RX_LIST.size();
+ }
+
+ Assertions.assertTrue(size < 10, "Received " + size + " messages");
+ }
+
+ private static List<String> RX_LIST = new LinkedList<>();
+
+ public static class FutureCancelRxInvokerProvider implements RxInvokerProvider<FutureCancelRxInvoker> {
+
+ Function<InputStream, Object> function = new Function<InputStream, Object>() {
+ @Override
+ public Object apply(InputStream inputStream) {
+ byte[] number = new byte[8];
+ int len = 0;
+ do {
+ try {
+ if ((len = inputStream.read(number)) != -1) {
+ RX_LIST.add(new String(number).substring(0, len));
+ } else {
+ break;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } while (true);
+ return RX_LIST;
+ }
+ };
+
+ @Override
+ public boolean isProviderFor(Class<?> clazz) {
+ return FutureCancelRxInvoker.class.equals(clazz);
+ }
+
+ @Override
+ public FutureCancelRxInvoker getRxInvoker(SyncInvoker syncInvoker, ExecutorService executorService) {
+ return new FutureCancelRxInvoker(syncInvoker, executorService, function);
+ }
+ }
+
+ private static class FutureCancelRxInvoker extends AbstractRxInvoker<CompletionStage> implements CompletionStageRxInvoker {
+ private final Function<InputStream, Object> consumer;
+
+ public FutureCancelRxInvoker(SyncInvoker syncInvoker, ExecutorService executor, Function<InputStream, Object> consumer) {
+ super(syncInvoker, executor);
+ this.consumer = consumer;
+ }
+
+ @Override
+ public <R> CompletionStage method(String name, Entity<?> entity, Class<R> responseType) {
+ CompletableFuture<R> completableFuture = CompletableFuture.supplyAsync(new Supplier<R>() {
+ @Override
+ public R get() {
+ Response r = getSyncInvoker().get();
+ InputStream is = r.readEntity(InputStream.class);
+ Object o = consumer.apply(is);
+ return (R) o;
+ }
+ }, getExecutorService());
+ ((JerseyInvocation.Builder) getSyncInvoker()).setCancellable(completableFuture);
+ return completableFuture;
+ }
+
+ @Override
+ public <R> CompletionStage method(String name, Entity<?> entity, GenericType<R> responseType) {
+ CompletableFuture<R> completableFuture = CompletableFuture.supplyAsync(new Supplier<R>() {
+ @Override
+ public R get() {
+ Response r = getSyncInvoker().get();
+ InputStream is = r.readEntity(InputStream.class);
+ Object o = consumer.apply(is);
+ return (R) o;
+ }
+ }, getExecutorService());
+ return completableFuture;
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
index 83a52dd..f381d5f 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java
@@ -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,11 +16,18 @@
package org.glassfish.jersey.tests.e2e.client.connector;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.client.spi.ConnectorProvider;
import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.media.multipart.FormDataBodyPart;
+import org.glassfish.jersey.media.multipart.FormDataMultiPart;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.media.multipart.BodyPart;
import org.glassfish.jersey.media.multipart.BodyPartEntity;
@@ -32,6 +39,8 @@
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.spi.TestHelper;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.Test;
@@ -40,16 +49,25 @@
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.WriterInterceptor;
+import jakarta.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.logging.Handler;
import java.util.logging.Level;
+import java.util.logging.LogManager;
import java.util.logging.Logger;
public class MultiPartTest {
@@ -129,5 +147,72 @@
}
}
}
+
+ @Test
+ public void testNettyBufferedMultipart() {
+// setDebugLevel(Level.FINEST);
+ ClientConfig config = new ClientConfig();
+
+ config.connectorProvider(new NettyConnectorProvider());
+ config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
+ config.register(org.glassfish.jersey.media.multipart.MultiPartFeature.class);
+ config.register(new LoggingHandler(LogLevel.DEBUG));
+ config.register(new LoggingInterceptor());
+ config.property(ClientProperties.ASYNC_THREADPOOL_SIZE, 10);
+ config.property("jersey.config.client.logging.verbosity", LoggingFeature.Verbosity.PAYLOAD_TEXT);
+ config.property("jersey.config.client.logging.logger.level", Level.FINEST.toString());
+
+ Client client = ClientBuilder.newClient(config);
+
+ FormDataMultiPart formData = new FormDataMultiPart();
+ FormDataBodyPart bodyPart1 = new FormDataBodyPart("hello1", "{\"first\":\"firstLine\",\"second\":\"secondLine\"}",
+ MediaType.APPLICATION_JSON_TYPE);
+ formData.bodyPart(bodyPart1);
+ formData.bodyPart(new FormDataBodyPart("hello2",
+ "{\"first\":\"firstLine\",\"second\":\"secondLine\",\"third\":\"thirdLine\"}",
+ MediaType.APPLICATION_JSON_TYPE));
+ formData.bodyPart(new FormDataBodyPart("hello3",
+ "{\"first\":\"firstLine\",\"second\":\"secondLine\",\""
+ + "second\":\"secondLine\",\"second\":\"secondLine\",\"second\":\"secondLine\"}",
+ MediaType.APPLICATION_JSON_TYPE));
+ formData.bodyPart(new FormDataBodyPart("plaintext", "hello"));
+
+ Response response1 = client.target(target().getUri()).path("upload")
+ .request()
+ .post(Entity.entity(formData, formData.getMediaType()));
+
+ MatcherAssert.assertThat(response1.getStatus(), Matchers.is(200));
+ MatcherAssert.assertThat(response1.readEntity(String.class),
+ Matchers.stringContainsInOrder("first", "firstLine", "second", "secondLine"));
+ response1.close();
+ client.close();
+ }
+
+ public static void setDebugLevel(Level newLvl) {
+ Logger rootLogger = LogManager.getLogManager().getLogger("");
+ Handler[] handlers = rootLogger.getHandlers();
+ rootLogger.setLevel(newLvl);
+ for (Handler h : handlers) {
+ h.setLevel(Level.ALL);
+ }
+ Logger nettyLogger = Logger.getLogger("io.netty");
+ nettyLogger.setLevel(Level.FINEST);
+ }
+
+ @Provider
+ public class LoggingInterceptor implements WriterInterceptor {
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context)
+ throws IOException, WebApplicationException {
+ try {
+ MultivaluedMap<String, Object> headers = context.getHeaders();
+ headers.forEach((key, val) -> System.out.println(key + ":" + val));
+ context.proceed();
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ }
}
}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java
new file mode 100644
index 0000000..e3c3caf
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.client.connector;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
+import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UncheckedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class NoContentLengthTest {
+
+ private static final String MSG = "12345678901234567890123456789012345678901234567890";
+
+ private static int port;
+ private static AtomicBoolean running = new AtomicBoolean(false);
+
+ @BeforeEach
+ void beforeEach() {
+ while (!running.compareAndSet(false, true)) {
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ String _port = System.getProperty("jersey.config.test.container.port");
+ port = Integer.parseInt(_port == null || _port.isEmpty() ? "8080" : _port);
+ ServerSocket serverSocket = new ServerSocket(port);
+ System.err.println("Starting server on port : " + port);
+
+ Socket clientSocket = serverSocket.accept();
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+ BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
+
+ String s;
+ while ((s = in.readLine()) != null) {
+ // System.out.println(s);
+ if (s.isEmpty()) {
+ break;
+ }
+ }
+
+ out.write("HTTP/1.0 200 OK\r\n");
+ out.write("Content-Type: text/plain\r\n");
+ out.write("\r\n");
+ out.write(MSG);
+
+ out.close();
+ in.close();
+ clientSocket.close();
+ serverSocket.close();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ } finally {
+ running.set(false);
+ }
+ }
+ };
+ Thread newThread = new Thread(runnable);
+ newThread.start();
+ }
+
+ public static List<ConnectorProvider> providers() {
+ return Arrays.asList(
+ new ApacheConnectorProvider(),
+ new Apache5ConnectorProvider(),
+ new HttpUrlConnectorProvider(),
+ new NettyConnectorProvider(),
+ new JettyConnectorProvider(),
+ new GrizzlyConnectorProvider(),
+ new JdkConnectorProvider()
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("providers")
+ public void testNoContentLength(ConnectorProvider connectorProvider) {
+ try (Response r = target(connectorProvider).request().get()) {
+ MatcherAssert.assertThat(r.getStatus(), Matchers.is(200));
+ MatcherAssert.assertThat(r.getHeaderString(HttpHeaders.CONTENT_LENGTH), Matchers.nullValue());
+ MatcherAssert.assertThat(r.hasEntity(), Matchers.is(true));
+ MatcherAssert.assertThat(r.readEntity(String.class), Matchers.is(MSG));
+ }
+ }
+
+ private WebTarget target(ConnectorProvider connectorProvider) {
+ ClientConfig config = new ClientConfig();
+ config.connectorProvider(connectorProvider);
+ return ClientBuilder.newClient(config).target("http://localhost:" + port);
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
index 1f18b80..ffb8b1f 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,11 +28,8 @@
import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
@@ -66,9 +63,10 @@
private static Server server;
@BeforeAll
- public static void startExpect100ContinueTestServer() {
+ private static void startExpect100ContinueTestServer() {
server = new Server(portNumber);
- server.setHandler(new Expect100ContinueTestHandler());
+ server.setDefaultHandler(new Expect100ContinueTestHandler());
+ server.setDynamic(true);
try {
server.start();
} catch (Exception e) {
@@ -77,31 +75,28 @@
}
@AfterAll
- public static void stopExpect100ContinueTestServer() {
+ private static void stopExpect100ContinueTestServer() {
try {
server.stop();
} catch (Exception e) {
}
}
- private static Client client;
- @BeforeEach
- public void beforeEach() {
+ @BeforeAll
+ private static void initClient() {
final ClientConfig config = new ClientConfig();
- this.configureClient(config);
+ config.connectorProvider(new NettyConnectorProvider());
client = ClientBuilder.newClient(config);
}
- private Client client() {
- return client;
+ @AfterAll
+ private static void stopClient() {
+ client.close();
}
+ private static Client client;
public WebTarget target(String path) {
- return client().target(String.format("http://localhost:%d", portNumber)).path(path);
- }
-
- protected void configureClient(ClientConfig config) {
- config.connectorProvider(new NettyConnectorProvider());
+ return client.target(String.format("http://localhost:%d", portNumber)).path(path);
}
@Test
@@ -234,6 +229,11 @@
callback.succeeded();
return true;
}
+ if (!expected && !failed) {
+ response.reset();
+ callback.succeeded();
+ return true;
+ }
response.write(true, ByteBuffer.wrap("\n\r".getBytes()), callback);
callback.failed(new ProcessingException(""));
diff --git a/tests/e2e-core-common/pom.xml b/tests/e2e-core-common/pom.xml
index fd65669..18dedc8 100644
--- a/tests/e2e-core-common/pom.xml
+++ b/tests/e2e-core-common/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java
index bd6e3c5..817170c 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.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
@@ -16,6 +16,9 @@
package org.glassfish.jersey.tests.e2e.common.message.internal;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
@@ -33,10 +36,13 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.RuntimeDelegate;
+import org.glassfish.jersey.io.spi.FlushedCloseable;
import org.glassfish.jersey.message.internal.CookieProvider;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.hamcrest.Matchers.contains;
@@ -271,4 +277,38 @@
newCtx.setMediaType(MediaType.APPLICATION_XML_TYPE); // new value
Assertions.assertEquals(MediaType.APPLICATION_XML_TYPE, newCtx.getMediaType());
}
+
+ @Test
+ public void OutboundMessageContextFlushTest() throws IOException {
+ FlushCountOutputStream os = new FlushCountOutputStream();
+ OutboundMessageContext ctx = new OutboundMessageContext((Configuration) null);
+ ctx.setEntity("Anything");
+ ctx.setEntityStream(os);
+ os.flush();
+ ctx.close();
+ MatcherAssert.assertThat(os.flushedCnt, Matchers.is(2));
+
+ os = new FlushedClosableOutputStream();
+ ctx = new OutboundMessageContext((Configuration) null);
+ ctx.setEntity("Anything2");
+ ctx.setEntityStream(os);
+ os.flush();
+ ctx.close();
+ MatcherAssert.assertThat(os.flushedCnt, Matchers.is(1));
+ }
+
+ private static class FlushCountOutputStream extends ByteArrayOutputStream {
+ private int flushedCnt = 0;
+
+ @Override
+ public void flush() throws IOException {
+ flushedCnt++;
+ super.flush();
+ }
+ }
+
+ private static class FlushedClosableOutputStream extends FlushCountOutputStream implements FlushedCloseable {
+
+ }
}
+
diff --git a/tests/e2e-entity/pom.xml b/tests/e2e-entity/pom.xml
index 8a869fd..3ad546e 100644
--- a/tests/e2e-entity/pom.xml
+++ b/tests/e2e-entity/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -41,7 +41,6 @@
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<enableAssertions>false</enableAssertions>
- <skipTests>${skip.e2e}</skipTests>
</configuration>
<executions>
<execution>
@@ -225,6 +224,15 @@
</properties>
</profile>
<profile>
+ <id>test-suit</id> <!--due to the broadcast test failure after update to the latest junit platform suite -->
+ <activation> <!--for JDK 11 (only in CI/CD job) it's required to used legacy junit version -->
+ <jdk>11</jdk>
+ </activation>
+ <properties>
+ <junit-platform-suite.version>${junit-platform-suite.legacy.version}</junit-platform-suite.version>
+ </properties>
+ </profile>
+ <profile>
<id>sonar</id>
<build>
<pluginManagement>
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ChunkedInputReaderTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ChunkedInputReaderTest.java
new file mode 100644
index 0000000..5c0c944
--- /dev/null
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/ChunkedInputReaderTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.entity;
+
+import org.glassfish.jersey.client.ChunkedInput;
+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.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ReaderInterceptor;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class ChunkedInputReaderTest extends JerseyTest {
+
+ @Path("/")
+ public static class ChunkedInputReaderTestResource {
+ @GET
+ public String get() {
+ return "To_be_replaced_by_client_reader";
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(ChunkedInputReaderTestResource.class);
+ }
+
+ @Test
+ public void testChunkedInputStreamIsClosed() {
+ AtomicBoolean closed = new AtomicBoolean(false);
+ InputStream inputStream = new ByteArrayInputStream("TEST".getBytes()) {
+ @Override
+ public void close() throws IOException {
+ closed.set(true);
+ super.close();
+ }
+ };
+
+ final GenericType<ChunkedInput<String>> chunkedInputGenericType = new GenericType(new ParameterizedType() {
+ @Override
+ public Type[] getActualTypeArguments() {
+ return new Type[]{String.class};
+ }
+
+ @Override
+ public Type getRawType() {
+ return ChunkedInput.class;
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return ChunkedInput.class;
+ }
+ });
+
+
+ ChunkedInput<String> response = target().register(new ReaderInterceptor() {
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ context.setInputStream(inputStream);
+ return context.proceed();
+ };
+ }).request().get(chunkedInputGenericType);
+ MatcherAssert.assertThat(response.read(), Matchers.is("TEST"));
+ response.close();
+ MatcherAssert.assertThat(closed.get(), Matchers.is(true));
+ }
+}
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
index 77a74a6..9e872fc 100644
--- a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/EntityTypesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -72,6 +72,7 @@
import org.glassfish.jersey.internal.util.collection.MultivaluedStringMap;
import org.glassfish.jersey.jettison.JettisonFeature;
import org.glassfish.jersey.message.internal.FileProvider;
+import org.glassfish.jersey.message.internal.PathProvider;
import org.glassfish.jersey.server.ResourceConfig;
import org.codehaus.jettison.json.JSONArray;
@@ -431,6 +432,20 @@
_test(in, FileResource.class);
}
+ @Path("PathResource")
+ public static class PathResource extends AResource<java.nio.file.Path> {
+ }
+
+ @Test
+ @Execution(ExecutionMode.CONCURRENT)
+ public void testPathRepresentation() throws IOException {
+ final var pp = new PathProvider();
+ final var in = pp.readFrom(java.nio.file.Path.class, java.nio.file.Path.class, null, null, null,
+ new ByteArrayInputStream("CONTENT".getBytes()));
+
+ _test(in, PathResource.class);
+ }
+
@Produces("application/x-www-form-urlencoded")
@Consumes("application/x-www-form-urlencoded")
@Path("FormResource")
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java
index 5b3d957..c97bea3 100644
--- a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/sse/BroadcasterExecutorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 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
@@ -152,6 +152,7 @@
@Test
public void test() throws InterruptedException {
final String[] onEventThreadName = {""};
+ final CountDownLatch onEventLatch = new CountDownLatch(1);
SseEventSource eventSource = SseEventSource
.target(target().path("sse/events"))
.build();
@@ -159,6 +160,7 @@
eventSource.register((event) -> {
LOGGER.info("Event: " + event + " from: " + Thread.currentThread().getName());
onEventThreadName[0] = Thread.currentThread().getName();
+ onEventLatch.countDown();
}
);
@@ -174,6 +176,7 @@
Assertions.assertTrue(sendThreadOk, "send either not invoked at all or from wrong thread");
Assertions.assertTrue(onCompleteThreadOk, "onComplete either not invoked at all or from wrong thread");
+ Assertions.assertTrue(onEventLatch.await(2_000L, TimeUnit.MILLISECONDS));
Assertions.assertTrue(onEventThreadName[0].startsWith("custom-client-executor"),
"Client event called from wrong thread ( " + onEventThreadName[0] + ")");
}
diff --git a/tests/e2e-inject/cdi-inject-weld/pom.xml b/tests/e2e-inject/cdi-inject-weld/pom.xml
index d5fc284..aa5fea5 100644
--- a/tests/e2e-inject/cdi-inject-weld/pom.xml
+++ b/tests/e2e-inject/cdi-inject-weld/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/e2e-inject/cdi2-se/pom.xml b/tests/e2e-inject/cdi2-se/pom.xml
index 514369d..51d9582 100644
--- a/tests/e2e-inject/cdi2-se/pom.xml
+++ b/tests/e2e-inject/cdi2-se/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/e2e-inject/hk2/pom.xml b/tests/e2e-inject/hk2/pom.xml
index 40fd069..f0a9c2a 100644
--- a/tests/e2e-inject/hk2/pom.xml
+++ b/tests/e2e-inject/hk2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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-inject/non-inject/pom.xml b/tests/e2e-inject/non-inject/pom.xml
new file mode 100644
index 0000000..e4d4a1b
--- /dev/null
+++ b/tests/e2e-inject/non-inject/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>e2e-inject</artifactId>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <version>3.5.99-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>e2e-inject-noninject</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-injectless-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
diff --git a/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/DisposableSuplierTest.java b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/DisposableSuplierTest.java
new file mode 100644
index 0000000..0d36f34
--- /dev/null
+++ b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/DisposableSuplierTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.noninject;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class DisposableSuplierTest {
+ private static final AtomicInteger disposeCounter = new AtomicInteger(0);
+ private static final String HOST = "http://somewhere.anywhere";
+
+ public interface ResponseObject {
+ Response getResponse();
+ }
+
+ private static class TestDisposableSupplier implements DisposableSupplier<ResponseObject> {
+ AtomicInteger counter = new AtomicInteger(300);
+
+ @Override
+ public void dispose(ResponseObject instance) {
+ disposeCounter.incrementAndGet();
+ }
+
+ @Override
+ public ResponseObject get() {
+ return new ResponseObject() {
+
+ @Override
+ public Response getResponse() {
+ return Response.ok().build();
+ }
+ };
+ }
+ }
+
+ private static class DisposableSupplierInjectingFilter implements ClientRequestFilter {
+ private final ResponseObject responseSupplier;
+
+ @Inject
+ private DisposableSupplierInjectingFilter(ResponseObject responseSupplier) {
+ this.responseSupplier = responseSupplier;
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(responseSupplier.getResponse());
+ }
+ }
+
+ @Test
+ public void testDisposeCount() {
+ disposeCounter.set(0);
+ int CNT = 4;
+ Client client = ClientBuilder.newClient()
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bindFactory(TestDisposableSupplier.class).to(ResponseObject.class)
+ .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+ }
+ }).register(DisposableSupplierInjectingFilter.class);
+
+ for (int i = 0; i != CNT; i++) {
+ try (Response response = client.target(HOST).request().get()) {
+ MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
+ }
+ }
+
+ MatcherAssert.assertThat(disposeCounter.get(), Matchers.is(CNT));
+ }
+}
diff --git a/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/InstanceListSizeTest.java b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/InstanceListSizeTest.java
new file mode 100644
index 0000000..2acb538
--- /dev/null
+++ b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/InstanceListSizeTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.noninject;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.innate.inject.NonInjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+public class InstanceListSizeTest {
+
+ private static final String TEST_HEADER = "TEST";
+ private static final String HOST = "https://anywhere.any";
+
+ @Test
+ public void leakTest() throws ExecutionException, InterruptedException {
+ int CNT = 100;
+ Client client = ClientBuilder.newClient();
+ client.register(InjectionManagerGrowChecker.class);
+ Response response = client.target(HOST).request().header(TEST_HEADER, "0").get();
+ int status = response.getStatus();
+ response.close();
+ //Create instance in NonInjectionManager$TypedInstances.threadPredestroyables
+
+ for (int i = 0; i <= CNT; i++) {
+ final String header = String.valueOf(i + 1);
+ try (Response r = client.target(HOST).request()
+ .header(TEST_HEADER, header)
+ .async()
+ .post(Entity.text("text")).get()) {
+ int stat = r.getStatus();
+ MatcherAssert.assertThat(
+ "NonInjectionManager#Types#disposableSupplierObjects is increasing", stat, Matchers.is(202));
+ }
+ }
+ //Create 10 instance in NonInjectionManager$TypedInstances.threadPredestroyables
+
+ for (int i = 0; i <= CNT; i++) {
+ final String header = String.valueOf(i + CNT + 2);
+ final Object text = CompletableFuture.supplyAsync(() -> {
+ Response test = client.target(HOST).request()
+ .header("TEST", header)
+ .post(Entity.text("text"));
+ int stat = test.getStatus();
+ test.close();
+ MatcherAssert.assertThat(
+ "NonInjectionManager#Types#disposableSupplierObjects is increasing", stat, Matchers.is(202));
+
+ return null;
+ }).join();
+ }
+ //Create 10 instance in NonInjectionManager$TypedInstances.threadPredestroyables
+
+ response = client.target(HOST).request().header(TEST_HEADER, 2 * CNT + 3).get();
+ status = response.getStatus();
+ MatcherAssert.assertThat(status, Matchers.is(202));
+ response.close();
+ }
+
+ private static class InjectionManagerGrowChecker implements ClientRequestFilter {
+ private boolean first = true;
+ private int disposableSize = 0;
+ private int threadInstancesSize = 0;
+ private HttpHeaders headers;
+ private int headerCnt = 0;
+
+ @Inject
+ public InjectionManagerGrowChecker(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ Response.Status status = Response.Status.ACCEPTED;
+ if (headerCnt++ != Integer.parseInt(headers.getHeaderString("TEST"))) {
+ status = Response.Status.BAD_REQUEST;
+ }
+
+ NonInjectionManager nonInjectionManager = getInjectionManager(requestContext);
+ Object types = getDeclaredField(nonInjectionManager, "types");
+ Object instances = getDeclaredField(nonInjectionManager, "instances");
+ if (first) {
+ first = false;
+ disposableSize = getThreadInstances(types, "disposableSupplierObjects")
+ + getThreadInstances(instances, "disposableSupplierObjects");
+ threadInstancesSize = getThreadInstances(types, "threadInstances")
+ + getThreadInstances(instances, "threadInstances");
+ } else {
+ int newPredestroyableSize = getThreadInstances(types, "disposableSupplierObjects")
+ + getThreadInstances(instances, "disposableSupplierObjects");
+ if (newPredestroyableSize > disposableSize + 1 /* a new service to get disposed */) {
+ status = Response.Status.EXPECTATION_FAILED;
+ }
+ int newThreadInstances = getThreadInstances(types, "threadInstances")
+ + getThreadInstances(instances, "threadInstances");
+ if (newThreadInstances > threadInstancesSize) {
+ status = Response.Status.PRECONDITION_FAILED;
+ }
+ }
+
+ requestContext.abortWith(Response.status(status).build());
+ }
+ }
+
+ private static NonInjectionManager getInjectionManager(ClientRequestContext context) {
+ ClientRequest request = ((ClientRequest) context);
+ try {
+ Method clientConfigMethod = ClientRequest.class.getDeclaredMethod("getClientConfig");
+ clientConfigMethod.setAccessible(true);
+ ClientConfig clientConfig = (ClientConfig) clientConfigMethod.invoke(request);
+
+ Method runtimeMethod = ClientConfig.class.getDeclaredMethod("getRuntime");
+ runtimeMethod.setAccessible(true);
+ Object clientRuntime = runtimeMethod.invoke(clientConfig);
+ Class<?> clientRuntimeClass = clientRuntime.getClass();
+
+ Method injectionManagerMethod = clientRuntimeClass.getDeclaredMethod("getInjectionManager");
+ injectionManagerMethod.setAccessible(true);
+ InjectionManager injectionManager = (InjectionManager) injectionManagerMethod.invoke(clientRuntime);
+ return (NonInjectionManager) injectionManager;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Object getDeclaredField(NonInjectionManager nonInjectionManager, String name) {
+ try {
+ Field typesField = NonInjectionManager.class.getDeclaredField(name);
+ typesField.setAccessible(true);
+ return typesField.get(nonInjectionManager);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static int getThreadInstances(Object typedInstances, String threadLocalName) {
+ try {
+ Field threadLocalField =
+ typedInstances.getClass().getSuperclass().getDeclaredField(threadLocalName);
+ threadLocalField.setAccessible(true);
+ ThreadLocal<MultivaluedMap<?,?>> threadLocal =
+ (ThreadLocal<MultivaluedMap<?, ?>>) threadLocalField.get(typedInstances);
+ MultivaluedMap<?, ?> map = threadLocal.get();
+ if (map == null) {
+ return 0;
+ } else {
+ int cnt = 0;
+ Set<? extends Map.Entry<?, ? extends List<?>>> set = map.entrySet();
+ for (Map.Entry<?, ? extends List<?>> entry : map.entrySet()) {
+ cnt += entry.getValue().size();
+ }
+ return cnt;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+}
diff --git a/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/PreDestroyTest.java b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/PreDestroyTest.java
new file mode 100644
index 0000000..0f43b44
--- /dev/null
+++ b/tests/e2e-inject/non-inject/src/test/org/glassfish/jersey/tests/e2e/inject/noninject/PreDestroyTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.noninject;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.annotation.PreDestroy;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class PreDestroyTest {
+ private static final AtomicInteger disposeCounter = new AtomicInteger(0);
+ private static final String HOST = "http://somewhere.anywhere";
+
+ public interface ResponseObject {
+ Response getResponse();
+ }
+
+ public static class ResponseObjectImpl implements ResponseObject {
+
+ public ResponseObjectImpl() {
+
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ disposeCounter.incrementAndGet();
+ }
+
+ @Override
+ public Response getResponse() {
+ return Response.ok().build();
+ }
+ }
+
+ private static class PreDestroyInjectingFilter implements ClientRequestFilter {
+ private final ResponseObject responseSupplier;
+
+ @Inject
+ private PreDestroyInjectingFilter(ResponseObject responseSupplier) {
+ this.responseSupplier = responseSupplier;
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(responseSupplier.getResponse());
+ }
+ }
+
+ @Test
+ public void testPreDestroyCount() {
+ disposeCounter.set(0);
+ int CNT = 4;
+ Client client = ClientBuilder.newClient()
+ .register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(ResponseObjectImpl.class).to(ResponseObject.class)
+ .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+ }
+ }).register(PreDestroyInjectingFilter.class);
+
+ for (int i = 0; i != CNT; i++) {
+ try (Response response = client.target(HOST).request().get()) {
+ MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
+ }
+ }
+
+ MatcherAssert.assertThat(disposeCounter.get(), Matchers.is(1));
+ }
+}
diff --git a/tests/e2e-inject/pom.xml b/tests/e2e-inject/pom.xml
index 8499ec0..024ef81 100644
--- a/tests/e2e-inject/pom.xml
+++ b/tests/e2e-inject/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -36,5 +36,6 @@
<module>cdi2-se</module>
<module>cdi-inject-weld</module>
<module>hk2</module>
+ <module>non-inject</module>
</modules>
</project>
diff --git a/tests/e2e-jdk-specifics/pom.xml b/tests/e2e-jdk-specifics/pom.xml
new file mode 100644
index 0000000..0588537
--- /dev/null
+++ b/tests/e2e-jdk-specifics/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available 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.5.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-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk21/ThreadFactoryUsageTest.java b/tests/e2e-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk21/ThreadFactoryUsageTest.java
new file mode 100644
index 0000000..6739ba9
--- /dev/null
+++ b/tests/e2e-jdk-specifics/src/test/java/org/glassfish/jersey/tests/e2e/jdk21/ThreadFactoryUsageTest.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.tests.e2e.jdk21;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.innate.VirtualThreadSupport;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+public class ThreadFactoryUsageTest {
+ @Test
+ public void testThreadFactory() throws ExecutionException, InterruptedException {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ ThreadFactory threadFactory = VirtualThreadSupport.allowVirtual(true).getThreadFactory();
+ ThreadFactory countDownThreadFactory = r -> {
+ countDownLatch.countDown();
+ return threadFactory.newThread(r);
+ };
+
+ CompletionStage<Response> r = ClientBuilder.newClient()
+ .property(CommonProperties.THREAD_FACTORY, countDownThreadFactory)
+ .property(CommonProperties.USE_VIRTUAL_THREADS, true)
+ .register((ClientRequestFilter) requestContext -> requestContext.abortWith(Response.ok().build()))
+ .target("http://localhost:58080/test").request().rx().get();
+
+ MatcherAssert.assertThat(r.toCompletableFuture().get().getStatus(), Matchers.is(200));
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ MatcherAssert.assertThat(countDownLatch.getCount(), Matchers.is(0L));
+ }
+}
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index 7285152..bfa987e 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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-server/src/test/java/org/glassfish/jersey/tests/e2e/server/Issue5783Test.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/Issue5783Test.java
new file mode 100644
index 0000000..ab7b301
--- /dev/null
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/Issue5783Test.java
@@ -0,0 +1,97 @@
+/*
+ * 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.server;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Provider;
+
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+public class Issue5783Test extends JerseyTest {
+
+ private static final String ERROR = "Intentional issue5783 exception";
+ private static volatile String exceptionMessage;
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(Resource.class, ResponseFilter.class);
+ }
+
+ @Test
+ public void closeException() throws InterruptedException {
+ target("/test").request().get();
+ assertEquals(ERROR, exceptionMessage);
+ }
+
+ @Path("/test")
+ public static class Resource {
+
+ @GET
+ public Response closeException(@Context ContainerRequest request) {
+ // Save the exception when response.getRequestContext().getResponseWriter().failure(e)
+ ContainerResponseWriter writer = request.getResponseWriter();
+ ContainerResponseWriter proxy = (ContainerResponseWriter) Proxy.newProxyInstance(
+ ContainerResponseWriter.class.getClassLoader(),
+ new Class<?>[]{ContainerResponseWriter.class}, new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if ("failure".equals(method.getName())) {
+ exceptionMessage = ((Throwable) args[0]).getCause().getMessage();
+ }
+ return method.invoke(writer, args);
+ }
+ });
+ request.setWriter(proxy);
+ return Response.ok().build();
+ }
+ }
+
+ @Provider
+ public static class ResponseFilter implements ContainerResponseFilter {
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+ throws IOException {
+ // Hack it to make ContainerResponse#close throws one exception
+ responseContext.setEntity("something");
+ responseContext.setEntityStream(new ByteArrayOutputStream() {
+ @Override
+ public void close() throws IOException {
+ throw new IOException(ERROR);
+ }
+ });
+ }
+ }
+}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
index 749eb22..899d9ca 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java
@@ -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
@@ -30,6 +30,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
@@ -108,6 +109,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -400,6 +402,20 @@
}
@Test
+ public void testLastModifiedGETOnJPLocale() {
+ Locale defaultLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(new Locale("ja", "JP"));
+ final WebTarget target = target("/application.wadl");
+
+ final Response r = target.queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true").request().get(Response.class);
+ assertDoesNotThrow(() -> r.getLastModified());
+ } finally {
+ Locale.setDefault(defaultLocale);
+ }
+ }
+
+ @Test
public void testLastModifiedOPTIONS() {
final WebTarget target = target("/widgets/3/verbose");
diff --git a/tests/e2e-testng/pom.xml b/tests/e2e-testng/pom.xml
index c871420..f0ba038 100644
--- a/tests/e2e-testng/pom.xml
+++ b/tests/e2e-testng/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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 b787877..5fd9794 100644
--- a/tests/e2e-tls/pom.xml
+++ b/tests/e2e-tls/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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>
@@ -81,7 +97,7 @@
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java-junit5</artifactId>
- <version>0.14.0</version>
+ <version>0.18.1</version>
<scope>test</scope>
</dependency>
@@ -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,8 +164,30 @@
<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>
+ <profile>
+ <id>JDK_17-</id>
+ <activation>
+ <jdk>[11,17)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- The certificate is not working with JDK 11 -->
+ <excludes><exclude>**/ConcurrentHttpsUrlConnectionTest*</exclude></excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
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..03ee91f 100644
--- a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,6 +23,7 @@
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.internal.util.JdkVersion;
import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
@@ -48,6 +49,7 @@
public class SniTest {
private static final int PORT = 8443;
private static final String LOCALHOST = "127.0.0.1";
+ private static JdkVersion jdkVersion = JdkVersion.getJdkVersion();
static {
// Debug
@@ -58,14 +60,17 @@
}
public static ConnectorProvider[] getConnectors() {
- return new ConnectorProvider[] {
- new NettyConnectorProvider(),
- new ApacheConnectorProvider(),
- new Apache5ConnectorProvider(),
- new JdkConnectorProvider(),
- new HttpUrlConnectorProvider(),
- new JavaNetHttpConnectorProvider()
- };
+ ConnectorProvider[] providers = new ConnectorProvider[jdkVersion.getMajor() < 24 ? 6 : 5];
+ providers[0] = new NettyConnectorProvider();
+ providers[1] = new ApacheConnectorProvider();
+ providers[2] = new Apache5ConnectorProvider();
+ providers[3] = new JdkConnectorProvider();
+ providers[4] = new HttpUrlConnectorProvider();
+ if (jdkVersion.getMajor() < 24) {
+ /* The trick with 127.0.0.1 instead of the host in uri to get the SNI does not work for JDK 24 any longer */
+ providers[5] = new JavaNetHttpConnectorProvider();
+ }
+ return providers;
}
@ParameterizedTest
@@ -74,10 +79,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];
@@ -103,7 +127,7 @@
.path("host")
.request();
if (!JavaNetHttpConnectorProvider.class.isInstance(provider)) {
- builder = builder.header(HttpHeaders.HOST, hostName + ":8080");
+ builder = builder.header(HttpHeaders.HOST, hostName + ":" + PORT);
}
try (Response r = builder.get()) {
// empty
@@ -121,12 +145,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/connector/ConcurrentHttpsUrlConnectionTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/connector/ConcurrentHttpsUrlConnectionTest.java
new file mode 100644
index 0000000..444cee6
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/connector/ConcurrentHttpsUrlConnectionTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.connector;
+
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.core.MediaType;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.security.KeyStore;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManagerFactory;
+
+/**
+ * Jersey client seems to be not thread-safe:
+ * When the first GET request is in progress,
+ * all parallel requests from other Jersey client instances fail
+ * with SSLHandshakeException: PKIX path building failed.
+ * <p>
+ * Once the first GET request is completed,
+ * all subsequent requests work without error.
+ * <p>
+ * BUG 5749
+ */
+public class ConcurrentHttpsUrlConnectionTest {
+ private static int THREAD_NUMBER = 5;
+
+ private static volatile int responseCounter = 0;
+
+ private static SSLContext createContext() throws Exception {
+ URL url = ConcurrentHttpsUrlConnectionTest.class.getResource("keystore.jks");
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ try (InputStream is = url.openStream()) {
+ keyStore.load(is, "password".toCharArray());
+ }
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(keyStore, "password".toCharArray());
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+ tmf.init(keyStore);
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ return context;
+ }
+
+ @Test
+ public void testSSLConnections() throws Exception {
+ if (THREAD_NUMBER == 1) {
+ System.out.println("\nThis is the working case (THREAD_NUMBER==1). Set THREAD_NUMBER > 1 to reproduce the error! \n");
+ }
+
+ final HttpsServer server = new HttpsServer(createContext());
+ Executors.newFixedThreadPool(1).submit(server);
+
+ // set THREAD_NUMBER > 1 to reproduce an issue
+ ExecutorService executorService2clients = Executors.newFixedThreadPool(THREAD_NUMBER);
+
+ final ClientBuilder builder = ClientBuilder.newBuilder().sslContext(createContext())
+ .hostnameVerifier(new HostnameVerifier() {
+ public boolean verify(String arg0, SSLSession arg1) {
+ return true;
+ }
+ });
+
+ AtomicInteger counter = new AtomicInteger(0);
+
+ for (int i = 0; i < THREAD_NUMBER; i++) {
+ executorService2clients.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Client client = builder.build();
+ String ret = client.target("https://127.0.0.1:" + server.getPort() + "/" + new Random().nextInt())
+ .request(MediaType.TEXT_HTML)
+ .get(new GenericType<String>() {
+ });
+ System.out.print(++responseCounter + ". Server returned: " + ret);
+ } catch (Exception e) {
+ //get an exception here, if jersey lib is buggy and THREAD_NUMBER > 1:
+ //jakarta.ws.rs.ProcessingException: jakarta.net.ssl.SSLHandshakeException: PKIX path building failed:
+ e.printStackTrace();
+ } finally {
+ System.out.println(counter.incrementAndGet());
+ }
+ }
+ });
+ }
+
+ while (counter.get() != THREAD_NUMBER) {
+ Thread.sleep(100L);
+ }
+ server.stop();
+ }
+}
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/connector/HttpsServer.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/connector/HttpsServer.java
new file mode 100644
index 0000000..31214f1
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/connector/HttpsServer.java
@@ -0,0 +1,87 @@
+/*
+ * 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.connector;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+
+class HttpsServer implements Runnable {
+ private final SSLServerSocket sslServerSocket;
+ private boolean closed = false;
+
+ public HttpsServer(SSLContext context) throws Exception {
+ sslServerSocket = (SSLServerSocket) context.getServerSocketFactory().createServerSocket(0);
+ }
+
+ public int getPort() {
+ return sslServerSocket.getLocalPort();
+ }
+
+ @Override
+ public void run() {
+ System.out.printf("Server started on port %d%n", getPort());
+ while (!closed) {
+ SSLSocket s;
+ try {
+ s = (SSLSocket) sslServerSocket.accept();
+ } catch (IOException e2) {
+ s = null;
+ }
+ final SSLSocket socket = s;
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ if (socket != null) {
+ InputStream is = new BufferedInputStream(socket.getInputStream());
+ byte[] data = new byte[2048];
+ int len = is.read(data);
+ if (len <= 0) {
+ throw new IOException("no data received");
+ }
+ //System.out.printf("Server received: %s\n", new String(data, 0, len));
+ PrintWriter writer = new PrintWriter(socket.getOutputStream());
+ writer.println("HTTP/1.1 200 OK");
+ writer.println("Content-Type: text/html");
+ writer.println();
+ writer.println("Hello from server!");
+ writer.flush();
+ writer.close();
+ socket.close();
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ }
+ }).start();
+ }
+ }
+
+ void stop() {
+ try {
+ closed = true;
+ sslServerSocket.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
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-tls/src/test/resources/org/glassfish/jersey/tests/e2e/tls/connector/keystore.jks b/tests/e2e-tls/src/test/resources/org/glassfish/jersey/tests/e2e/tls/connector/keystore.jks
new file mode 100644
index 0000000..130aa71
--- /dev/null
+++ b/tests/e2e-tls/src/test/resources/org/glassfish/jersey/tests/e2e/tls/connector/keystore.jks
Binary files differ
diff --git a/tests/e2e/pom.xml b/tests/e2e/pom.xml
index 05083e4..2fbbd20 100644
--- a/tests/e2e/pom.xml
+++ b/tests/e2e/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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/api/ContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
index c4bcd53..138466e 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/ContentDispositionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -66,7 +66,7 @@
contentDisposition = new ContentDisposition(header);
assertNotNull(contentDisposition);
assertEquals(contentDispositionType, contentDisposition.getType());
- final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
header = contentDispositionType + ";filename=\"test.file\";creation-date=\""
+ dateString + "\";modification-date=\"" + dateString + "\";read-date=\""
+ dateString + "\";size=1222";
@@ -89,11 +89,19 @@
}
@Test
+ void testContentDispositionEncoded() {
+ final Date date = new Date();
+ final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("\"rm\\ -rf\".sh")
+ .creationDate(date).modificationDate(date).readDate(date).size(312).build();
+ assertEquals("\\\"rm\\\\ -rf\\\".sh", contentDisposition.getFileName());
+ }
+
+ @Test
public void testToString() {
final Date date = new Date();
final ContentDisposition contentDisposition = ContentDisposition.type(contentDispositionType).fileName("test.file")
.creationDate(date).modificationDate(date).readDate(date).size(1222).build();
- final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\""
+ dateString + "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222";
assertEquals(header, contentDisposition.toString());
@@ -244,7 +252,7 @@
final boolean decode
) throws ParseException {
final Date date = new Date();
- final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
final String prefixHeader = contentDispositionType + ";filename=\"" + actualFileName + "\";"
+ "creation-date=\"" + dateString + "\";modification-date=\"" + dateString + "\";read-date=\""
+ dateString + "\";size=1222" + ";name=\"testData\";" + "filename*=\"";
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
index c931809..0595890 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/FormDataContentDispositionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -45,7 +45,7 @@
.modificationDate(date).readDate(date).size(1222).build();
assertFormDataContentDisposition(contentDisposition, date);
try {
- final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
final String header = contentDispositionType + ";filename=\"test.file\";creation-date=\"" + dateString
+ "\";modification-date=\"" + dateString + "\";read-date=\"" + dateString + "\";size=1222"
+ ";name=\"testData\"";
@@ -92,7 +92,7 @@
final FormDataContentDisposition contentDisposition = FormDataContentDisposition.name("testData")
.fileName("test.file").creationDate(date).modificationDate(date)
.readDate(date).size(1222).build();
- final String dateString = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String dateString = HttpDateFormat.getPreferredDateFormatter().format(date);
final String header = contentDispositionType + "; filename=\"test.file\"; creation-date=\"" + dateString
+ "\"; modification-date=\"" + dateString + "\"; read-date=\"" + dateString + "\"; size=1222"
+ "; name=\"testData\"";
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
index 63305db..4e1bfd3 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/HttpHeaderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -100,8 +100,8 @@
@Test
public void testDateParsing() throws ParseException {
final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
- final String date_RFC1036 = "Sunday, 06-Nov-94 08:49:37 GMT";
- final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
+ final String date_RFC1036 = "Sunday, 07-Nov-04 08:49:37 GMT";
+ final String date_ANSI_C = "Sun Nov 6 08:49:37 1994";
HttpHeaderReader.readDate(date_RFC1123);
HttpHeaderReader.readDate(date_RFC1036);
@@ -113,7 +113,7 @@
final String date_RFC1123 = "Sun, 06 Nov 1994 08:49:37 GMT";
final Date date = HttpHeaderReader.readDate(date_RFC1123);
- final String date_formatted = HttpDateFormat.getPreferredDateFormat().format(date);
+ final String date_formatted = HttpDateFormat.getPreferredDateFormatter().format(date);
assertEquals(date_RFC1123, date_formatted);
}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/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/e2e/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/NoJAXBNoWadlTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/NoJAXBNoWadlTest.java
index 70ee14d..e068287 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/NoJAXBNoWadlTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/NoJAXBNoWadlTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,6 +35,9 @@
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
public class NoJAXBNoWadlTest extends JerseyTest {
@@ -72,7 +75,9 @@
try (Response r = target("dummy").request(MediaTypes.WADL_TYPE).options()) {
String headers = r.getHeaderString(HttpHeaders.ALLOW);
- Assertions.assertEquals("OPTIONS,PUT", headers);
+ List<String> methods = Arrays.asList(headers.split(","));
+ Collections.sort(methods);
+ Assertions.assertEquals(Arrays.asList("OPTIONS", "PUT"), methods);
}
System.out.println(readableStream.toString());
Assertions.assertTrue(
diff --git a/tests/integration/asm/pom.xml b/tests/integration/asm/pom.xml
index 30eef7b..b58b4bf 100644
--- a/tests/integration/asm/pom.xml
+++ b/tests/integration/asm/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/async-jersey-filter/pom.xml b/tests/integration/async-jersey-filter/pom.xml
index b7ff2f0..4a027e6 100644
--- a/tests/integration/async-jersey-filter/pom.xml
+++ b/tests/integration/async-jersey-filter/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -66,6 +66,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/tests/integration/async-jersey-filter/src/test/java/module-info.java b/tests/integration/async-jersey-filter/src/test/java/module-info.java
index cd60c38..f6cc40c 100644
--- a/tests/integration/async-jersey-filter/src/test/java/module-info.java
+++ b/tests/integration/async-jersey-filter/src/test/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -29,6 +29,7 @@
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
+ requires org.junit.platform.engine;
exports org.glassfish.jersey.tests.integration.async;
exports org.glassfish.jersey.tests.integration.jersey2730;
diff --git a/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml b/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
index 7de5ef3..aa595c5 100644
--- a/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-beanvalidation-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -31,6 +31,16 @@
<description>Jersey CDI/Bean Validation test web application</description>
+ <properties>
+ <surefire.coverage.argline>
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-reads org.jboss.logging=org.hibernate.validator
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
+ </properties>
+
<dependencies>
<dependency>
<groupId>jakarta.ws.rs</groupId>
@@ -73,7 +83,13 @@
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
- <scope>provided</scope>
+<!-- <scope>provided</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.environment</groupId>
+ <artifactId>weld-environment-common</artifactId>
+ <version>${weld.version}</version>
+<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -121,6 +137,11 @@
<artifactId>jersey-container-grizzly2-http</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/tests/integration/cdi-integration/cdi-client-on-server/pom.xml b/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
index f270d0b..07f2c31 100644
--- a/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
+++ b/tests/integration/cdi-integration/cdi-client-on-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-client/pom.xml b/tests/integration/cdi-integration/cdi-client/pom.xml
index 3d640a6..1c0fe73 100644
--- a/tests/integration/cdi-integration/cdi-client/pom.xml
+++ b/tests/integration/cdi-integration/cdi-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -92,4 +92,13 @@
</plugin>
</plugins>
</build>
+ <properties>
+ <surefire.coverage.argline>
+ --add-opens weld.core.impl/org.jboss.weld.logging=org.jboss.logging
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
+ </properties>
</project>
diff --git a/tests/integration/cdi-integration/cdi-client/src/test/java/module-info.java b/tests/integration/cdi-integration/cdi-client/src/test/java/module-info.java
index 6ff1a4b..0567a2c 100644
--- a/tests/integration/cdi-integration/cdi-client/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/cdi-client/src/test/java/module-info.java
@@ -25,6 +25,8 @@
requires weld.core.impl;
requires weld.se.core;
+ requires org.jboss.logging;
+
requires org.glassfish.jersey.core.common;
requires org.glassfish.jersey.inject.hk2;
requires org.glassfish.jersey.ext.cdi1x ;
diff --git a/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
index 6a23e1b..43f7d13 100644
--- a/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-ejb-test-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
index db5320a..d20cc9d 100644
--- a/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-iface-with-non-jaxrs-impl-test-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-log-check/pom.xml b/tests/integration/cdi-integration/cdi-log-check/pom.xml
index be6ebb1..f0ba288 100644
--- a/tests/integration/cdi-integration/cdi-log-check/pom.xml
+++ b/tests/integration/cdi-integration/cdi-log-check/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-manually-bound/pom.xml b/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
index e62d76d..0ae6627 100644
--- a/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
+++ b/tests/integration/cdi-integration/cdi-manually-bound/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -118,5 +118,21 @@
</exclusions>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+
+ <properties>
+ <surefire.coverage.argline>
+ --add-opens weld.core.impl/org.jboss.weld.logging=org.jboss.logging
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
+ </properties>
+
</project>
diff --git a/tests/integration/cdi-integration/cdi-manually-bound/src/test/java/module-info.java b/tests/integration/cdi-integration/cdi-manually-bound/src/test/java/module-info.java
index 4479aa6..4365145 100644
--- a/tests/integration/cdi-integration/cdi-manually-bound/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/cdi-manually-bound/src/test/java/module-info.java
@@ -34,6 +34,7 @@
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
+ requires org.junit.platform.engine;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.external;
diff --git a/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
index 8a01ce9..e64b9e2 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/ear/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
index 15b8d1c..b0068ed 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/lib/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-multimodule/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/pom.xml
index 7eca36f..595318d 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
index 1b803b7..03cea2b 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/war1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml b/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
index 84ab7c8..040fb6e 100644
--- a/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multimodule/war2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml b/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
index 92e6bb5..1736945 100644
--- a/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-multipart-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
index ea440ac..c1bfc72 100644
--- a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -95,6 +95,21 @@
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <properties>
+ <surefire.coverage.argline>
+ --add-opens weld.core.impl/org.jboss.weld.logging=org.jboss.logging
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
+ </properties>
+
</project>
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/module-info.java b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/module-info.java
index 6a38acb..d3276bf 100644
--- a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/module-info.java
@@ -32,6 +32,7 @@
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
+ requires org.junit.platform.engine;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.integration.cdi.resource.context;
diff --git a/tests/integration/cdi-integration/cdi-singleton/pom.xml b/tests/integration/cdi-integration/cdi-singleton/pom.xml
index 6cf2624..acb9551 100644
--- a/tests/integration/cdi-integration/cdi-singleton/pom.xml
+++ b/tests/integration/cdi-integration/cdi-singleton/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -99,6 +99,11 @@
</exclusions>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/tests/integration/cdi-integration/cdi-singleton/src/test/java/module-info.java b/tests/integration/cdi-integration/cdi-singleton/src/test/java/module-info.java
index e70f9f8..fdb0bc3 100644
--- a/tests/integration/cdi-integration/cdi-singleton/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/cdi-singleton/src/test/java/module-info.java
@@ -33,6 +33,7 @@
requires org.glassfish.jersey.tests.framework.provider.grizzly;
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
+ requires org.junit.platform.engine;
exports org.glassfish.jersey.tests.cdi.singleton.test;
}
\ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
new file mode 100644
index 0000000..2da1124
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2024, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>cdi-integration-project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
+ <version>3.5.99-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cdi-skipping-analyzer</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.ws.rs</groupId>
+ <artifactId>jakarta.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.enterprise</groupId>
+ <artifactId>jakarta.enterprise.cdi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.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.incubator</groupId>
+ <artifactId>jersey-injectless-client</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.java
similarity index 77%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.java
index 0fdbe9d..44d56d2 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.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
@@ -14,7 +14,8 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
- */
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.tests.cdi.skippinganalyzer;
+
+public interface CdiService<T> {
+ void doService(T t);
+}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java
new file mode 100644
index 0000000..a7e5130
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.skippinganalyzer;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.event.Observes;
+import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
+import jakarta.enterprise.inject.spi.Extension;
+import java.io.IOException;
+
+public class CdiServiceExtension implements Extension {
+ public void observe(@Observes AfterBeanDiscovery event) throws IOException, ClassNotFoundException {
+ event.addBean()
+ .addType(CdiService.class)
+ .beanClass(CdiService.class)
+ .scope(ApplicationScoped.class)
+ .createWith(context -> new CdiServiceImpl());
+ }
+
+}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java
new file mode 100644
index 0000000..6406346
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cdi.skippinganalyzer;
+
+import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.inject.Inject;
+
+public class CdiServiceImpl implements CdiService<StringBuilder> {
+
+ @Inject
+ BeanManager beanManager;
+
+ @Override
+ public void doService(StringBuilder sb) {
+ sb.append(getClass().getSimpleName());
+ }
+}
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.java
similarity index 72%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.java
index 0fdbe9d..ce459d6 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.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
@@ -14,7 +14,11 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
- */
-package org.glassfish.jersey.test.jetty11.http2;
+package org.glassfish.jersey.tests.cdi.skippinganalyzer;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class WeldDiscoveredBean {
+
+}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..0850fd8
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,25 @@
+<?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
+
+-->
+
+
+<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
+ version="4.0" bean-discovery-mode="annotated">
+</beans>
\ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..7bfc71c
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.glassfish.jersey.tests.cdi.skippinganalyzer.CdiServiceExtension
\ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.java
new file mode 100644
index 0000000..698e496
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.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.tests.cdi.skippinganalyzer;
+
+import org.glassfish.hk2.api.ClassAnalyzer;
+import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
+import org.glassfish.jersey.ext.cdi1x.internal.InjecteeSkippingAnalyzer;
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.enterprise.inject.spi.CDI;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+
+public class SkippingAnalyzerTest {
+ private Weld weld;
+
+ @BeforeEach
+ public void setup() {
+ Assumptions.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld = new Weld();
+ weld.initialize();
+ }
+ }
+
+ @AfterEach
+ public void tearDown() throws Exception {
+ weld.shutdown();
+ }
+
+ @Test
+ public void testInjecteeSkippingAnalyzerWithZeroFieldsToSkip() throws Exception {
+ BeanManager beanManager = CDI.current().getBeanManager();
+ CdiComponentProvider provider = beanManager.getExtension(CdiComponentProvider.class);
+ Method method = provider.getClass().getDeclaredMethod("getFieldsToSkip");
+ method.setAccessible(true);
+ Map fieldMap = (Map) method.invoke(provider);
+ MatcherAssert.assertThat(0, Matchers.is(fieldMap.size()));
+
+ InjectionManager injectionManager = Injections.createInjectionManager();
+ provider.initialize(injectionManager);
+ injectionManager.completeRegistration();
+ ClassAnalyzer analyzer = injectionManager.getInstance(ClassAnalyzer.class, CdiComponentProvider.CDI_CLASS_ANALYZER);
+ MatcherAssert.assertThat(InjecteeSkippingAnalyzer.class, Matchers.is(analyzer.getClass()));
+
+ Set<Field> fieldSet = analyzer.getFields(CdiServiceImpl.class);
+ MatcherAssert.assertThat(0, Matchers.is(fieldSet.size()));
+ }
+}
diff --git a/tests/integration/cdi-integration/cdi-test-webapp/pom.xml b/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
index a024fcd..3d9a471 100644
--- a/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-test-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -93,6 +93,11 @@
<version>${jboss.logging.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/tests/integration/cdi-integration/cdi-test-webapp/src/test/java/module-info.java b/tests/integration/cdi-integration/cdi-test-webapp/src/test/java/module-info.java
index 37b7d03..00ac6c5 100644
--- a/tests/integration/cdi-integration/cdi-test-webapp/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/cdi-test-webapp/src/test/java/module-info.java
@@ -48,6 +48,7 @@
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
requires org.junit.jupiter.params;
+ requires org.junit.platform.engine;
exports org.glassfish.jersey.tests.cdi.resources.test;
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
index 7c8c352..47b43ba 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-cfg-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
index 81b8b32..d9c44ee 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-custom-hk2-banned-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml b/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
index c5d0c0a..8664757 100644
--- a/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
+++ b/tests/integration/cdi-integration/cdi-with-jersey-injection-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/context-inject-on-server/pom.xml b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
index 735217f..d2f9544 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/pom.xml
+++ b/tests/integration/cdi-integration/context-inject-on-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -84,6 +84,11 @@
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
<profile>
diff --git a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/module-info.java b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/module-info.java
index 90c500e..ac34e67 100644
--- a/tests/integration/cdi-integration/context-inject-on-server/src/test/java/module-info.java
+++ b/tests/integration/cdi-integration/context-inject-on-server/src/test/java/module-info.java
@@ -40,6 +40,7 @@
requires org.glassfish.jersey.ext.cdi1x;
requires org.junit.jupiter.api;
+ requires org.junit.platform.engine;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.grizzly;
diff --git a/tests/integration/cdi-integration/gf-cdi-inject/pom.xml b/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
index e571024..870b9fa 100644
--- a/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
+++ b/tests/integration/cdi-integration/gf-cdi-inject/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml
index 126835f..5109b3c 100644
--- a/tests/integration/cdi-integration/pom.xml
+++ b/tests/integration/cdi-integration/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -31,6 +31,18 @@
<groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
<artifactId>cdi-integration-project</artifactId>
<name>cdi-integration-project</name>
+
+ <properties>
+ <surefire.coverage.argline>
+ --add-opens weld.core.impl/org.jboss.weld.logging=org.jboss.logging
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-modules=ALL-MODULE-PATH
+ </surefire.coverage.argline>
+ </properties>
+
+
<modules>
<module>cdi-beanvalidation-webapp</module>
<module>cdi-client</module>
@@ -43,6 +55,7 @@
<module>cdi-multipart-webapp</module>
<module>cdi-resource-with-at-context</module>
<module>cdi-singleton</module>
+ <module>cdi-skipping-analyzer</module>
<module>cdi-test-webapp</module>
<module>cdi-with-jersey-injection-custom-cfg-webapp</module>
<module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>
@@ -65,7 +78,7 @@
<profile>
<id>gf-inject</id>
<activation>
- <jdk>[11,)</jdk>
+ <jdk>[11,24)</jdk>
</activation>
<modules>
<module>gf-cdi-inject</module>
diff --git a/tests/integration/client-connector-provider/pom.xml b/tests/integration/client-connector-provider/pom.xml
index 16e85e7..ce4bc94 100644
--- a/tests/integration/client-connector-provider/pom.xml
+++ b/tests/integration/client-connector-provider/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -57,6 +57,11 @@
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
diff --git a/tests/integration/client-connector-provider/src/test/java/module-info.java b/tests/integration/client-connector-provider/src/test/java/module-info.java
index 7fa0966..6981a38 100644
--- a/tests/integration/client-connector-provider/src/test/java/module-info.java
+++ b/tests/integration/client-connector-provider/src/test/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,6 +24,7 @@
requires org.junit.jupiter.api;
requires org.junit.jupiter.engine;
+ requires org.junit.platform.engine;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.grizzly;
diff --git a/tests/integration/ejb-multimodule-reload/ear/pom.xml b/tests/integration/ejb-multimodule-reload/ear/pom.xml
index 01ee899..d39eeb5 100644
--- a/tests/integration/ejb-multimodule-reload/ear/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/ear/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule-reload/lib/pom.xml b/tests/integration/ejb-multimodule-reload/lib/pom.xml
index 268162a..554a006 100644
--- a/tests/integration/ejb-multimodule-reload/lib/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/lib/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule-reload/pom.xml b/tests/integration/ejb-multimodule-reload/pom.xml
index 4a74f1e..272cab9 100644
--- a/tests/integration/ejb-multimodule-reload/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule-reload/war1/pom.xml b/tests/integration/ejb-multimodule-reload/war1/pom.xml
index ad07088..9e0a367 100644
--- a/tests/integration/ejb-multimodule-reload/war1/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/war1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule-reload/war2/pom.xml b/tests/integration/ejb-multimodule-reload/war2/pom.xml
index 0f81a34..21f63e3 100644
--- a/tests/integration/ejb-multimodule-reload/war2/pom.xml
+++ b/tests/integration/ejb-multimodule-reload/war2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule/ear/pom.xml b/tests/integration/ejb-multimodule/ear/pom.xml
index 4309927..b73482a 100644
--- a/tests/integration/ejb-multimodule/ear/pom.xml
+++ b/tests/integration/ejb-multimodule/ear/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule/lib/pom.xml b/tests/integration/ejb-multimodule/lib/pom.xml
index 819dd25..a2d877b 100644
--- a/tests/integration/ejb-multimodule/lib/pom.xml
+++ b/tests/integration/ejb-multimodule/lib/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule/pom.xml b/tests/integration/ejb-multimodule/pom.xml
index 80bb8b4..e88fa93 100644
--- a/tests/integration/ejb-multimodule/pom.xml
+++ b/tests/integration/ejb-multimodule/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-multimodule/war/pom.xml b/tests/integration/ejb-multimodule/war/pom.xml
index cb17fa1..3990311 100644
--- a/tests/integration/ejb-multimodule/war/pom.xml
+++ b/tests/integration/ejb-multimodule/war/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/ejb-test-webapp/pom.xml b/tests/integration/ejb-test-webapp/pom.xml
index 9463141..f27d750 100644
--- a/tests/integration/ejb-test-webapp/pom.xml
+++ b/tests/integration/ejb-test-webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/externalproperties/pom.xml b/tests/integration/externalproperties/pom.xml
index b993500..8feec0d 100644
--- a/tests/integration/externalproperties/pom.xml
+++ b/tests/integration/externalproperties/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-376/pom.xml b/tests/integration/j-376/pom.xml
index 822521d..4a56aa2 100644
--- a/tests/integration/j-376/pom.xml
+++ b/tests/integration/j-376/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-441/ear/pom.xml b/tests/integration/j-441/ear/pom.xml
index 57cb1f2..e5bd5a1 100644
--- a/tests/integration/j-441/ear/pom.xml
+++ b/tests/integration/j-441/ear/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-441/pom.xml b/tests/integration/j-441/pom.xml
index 3c1b410..6107c63 100644
--- a/tests/integration/j-441/pom.xml
+++ b/tests/integration/j-441/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-441/war1/pom.xml b/tests/integration/j-441/war1/pom.xml
index acd35ef..eaba647 100644
--- a/tests/integration/j-441/war1/pom.xml
+++ b/tests/integration/j-441/war1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-441/war2/pom.xml b/tests/integration/j-441/war2/pom.xml
index 6a339dd..4aa9230 100644
--- a/tests/integration/j-441/war2/pom.xml
+++ b/tests/integration/j-441/war2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-59/ear/pom.xml b/tests/integration/j-59/ear/pom.xml
index 77a50ea..5fa0d35 100644
--- a/tests/integration/j-59/ear/pom.xml
+++ b/tests/integration/j-59/ear/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-59/lib/pom.xml b/tests/integration/j-59/lib/pom.xml
index b544349..168d2b6 100644
--- a/tests/integration/j-59/lib/pom.xml
+++ b/tests/integration/j-59/lib/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-59/pom.xml b/tests/integration/j-59/pom.xml
index fa40b4a..92a7525 100644
--- a/tests/integration/j-59/pom.xml
+++ b/tests/integration/j-59/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/j-59/war/pom.xml b/tests/integration/j-59/war/pom.xml
index 8a0d9a6..df6801a 100644
--- a/tests/integration/j-59/war/pom.xml
+++ b/tests/integration/j-59/war/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jackson-14/pom.xml b/tests/integration/jackson-14/pom.xml
index da51eda..0d56f72 100644
--- a/tests/integration/jackson-14/pom.xml
+++ b/tests/integration/jackson-14/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jaxrs-component-inject/pom.xml b/tests/integration/jaxrs-component-inject/pom.xml
index a1dbe30..c6c5b0d 100644
--- a/tests/integration/jaxrs-component-inject/pom.xml
+++ b/tests/integration/jaxrs-component-inject/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1107/pom.xml b/tests/integration/jersey-1107/pom.xml
index e5d7b6e..69c5698 100644
--- a/tests/integration/jersey-1107/pom.xml
+++ b/tests/integration/jersey-1107/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1223/pom.xml b/tests/integration/jersey-1223/pom.xml
index 9552df2..5f3c3b1 100644
--- a/tests/integration/jersey-1223/pom.xml
+++ b/tests/integration/jersey-1223/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1604/pom.xml b/tests/integration/jersey-1604/pom.xml
index d2ce39c..e940edb 100644
--- a/tests/integration/jersey-1604/pom.xml
+++ b/tests/integration/jersey-1604/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -67,6 +67,8 @@
</plugins>
</build>
<properties>
- <failsafe.coverage.argline>--add-opens org.glassfish.jersey.core.client/org.glassfish.jersey.client.innate=ALL-UNNAMED --add-modules=ALL-MODULE-PATH</failsafe.coverage.argline>
+ <failsafe.coverage.argline>
+ --add-opens org.glassfish.jersey.core.client/org.glassfish.jersey.client.innate=ALL-UNNAMED
+ --add-exports org.glassfish.jersey.core.common/org.glassfish.jersey.innate.io=ALL-UNNAMED --add-modules=ALL-MODULE-PATH</failsafe.coverage.argline>
</properties>
</project>
diff --git a/tests/integration/jersey-1667/pom.xml b/tests/integration/jersey-1667/pom.xml
index cc1b88a..f91e94e 100644
--- a/tests/integration/jersey-1667/pom.xml
+++ b/tests/integration/jersey-1667/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1829/pom.xml b/tests/integration/jersey-1829/pom.xml
index 6e905b3..2775fcf 100644
--- a/tests/integration/jersey-1829/pom.xml
+++ b/tests/integration/jersey-1829/pom.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
diff --git a/tests/integration/jersey-1883/pom.xml b/tests/integration/jersey-1883/pom.xml
index 421d3a5..21de9f6 100644
--- a/tests/integration/jersey-1883/pom.xml
+++ b/tests/integration/jersey-1883/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1928/pom.xml b/tests/integration/jersey-1928/pom.xml
index 0a3c594..1f7faba 100644
--- a/tests/integration/jersey-1928/pom.xml
+++ b/tests/integration/jersey-1928/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1960/pom.xml b/tests/integration/jersey-1960/pom.xml
index b1f3eaf..6b3b0ad 100644
--- a/tests/integration/jersey-1960/pom.xml
+++ b/tests/integration/jersey-1960/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-1964/pom.xml b/tests/integration/jersey-1964/pom.xml
index 5bad123..2246809 100644
--- a/tests/integration/jersey-1964/pom.xml
+++ b/tests/integration/jersey-1964/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2031/pom.xml b/tests/integration/jersey-2031/pom.xml
index 3ca74ac..0a0a67c 100644
--- a/tests/integration/jersey-2031/pom.xml
+++ b/tests/integration/jersey-2031/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2136/pom.xml b/tests/integration/jersey-2136/pom.xml
index 0fdd1bf..f4e4923 100644
--- a/tests/integration/jersey-2136/pom.xml
+++ b/tests/integration/jersey-2136/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2137/pom.xml b/tests/integration/jersey-2137/pom.xml
index 0e496b2..b89875b 100644
--- a/tests/integration/jersey-2137/pom.xml
+++ b/tests/integration/jersey-2137/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2154/pom.xml b/tests/integration/jersey-2154/pom.xml
index ecd45ed..99af403 100644
--- a/tests/integration/jersey-2154/pom.xml
+++ b/tests/integration/jersey-2154/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2160/pom.xml b/tests/integration/jersey-2160/pom.xml
index 3e9d6a0..6b88259 100644
--- a/tests/integration/jersey-2160/pom.xml
+++ b/tests/integration/jersey-2160/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2164/pom.xml b/tests/integration/jersey-2164/pom.xml
index faa0eed..8a2650d 100644
--- a/tests/integration/jersey-2164/pom.xml
+++ b/tests/integration/jersey-2164/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2167/pom.xml b/tests/integration/jersey-2167/pom.xml
index ed7fec7..79623ef 100644
--- a/tests/integration/jersey-2167/pom.xml
+++ b/tests/integration/jersey-2167/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2176/pom.xml b/tests/integration/jersey-2176/pom.xml
index c262750..a89c35f 100644
--- a/tests/integration/jersey-2176/pom.xml
+++ b/tests/integration/jersey-2176/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2184/pom.xml b/tests/integration/jersey-2184/pom.xml
index cddf8f9..1917710 100644
--- a/tests/integration/jersey-2184/pom.xml
+++ b/tests/integration/jersey-2184/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2255/pom.xml b/tests/integration/jersey-2255/pom.xml
index 114c363..848f85b 100644
--- a/tests/integration/jersey-2255/pom.xml
+++ b/tests/integration/jersey-2255/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -57,6 +57,11 @@
<version>${jaxb.ri.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/tests/integration/jersey-2255/src/test/java/module-info.java b/tests/integration/jersey-2255/src/test/java/module-info.java
index cdb0cb5..57c76c2 100644
--- a/tests/integration/jersey-2255/src/test/java/module-info.java
+++ b/tests/integration/jersey-2255/src/test/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
requires jakarta.xml.bind;
requires org.junit.jupiter.api;
+ requires org.junit.platform.engine;
requires org.hamcrest;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.external;
diff --git a/tests/integration/jersey-2322/pom.xml b/tests/integration/jersey-2322/pom.xml
index beda6ba..6f022fd 100644
--- a/tests/integration/jersey-2322/pom.xml
+++ b/tests/integration/jersey-2322/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2335/pom.xml b/tests/integration/jersey-2335/pom.xml
index 1d1d4e4..2b753ed 100644
--- a/tests/integration/jersey-2335/pom.xml
+++ b/tests/integration/jersey-2335/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2421/pom.xml b/tests/integration/jersey-2421/pom.xml
index 6215400..1d7a655 100644
--- a/tests/integration/jersey-2421/pom.xml
+++ b/tests/integration/jersey-2421/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
index bae7758..79be107 100644
--- a/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
+++ b/tests/integration/jersey-2421/src/test/java/org/glassfish/jersey/tests/integration/jersey2421/Jersey2421Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -38,7 +38,6 @@
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
-import org.glassfish.jersey.message.internal.NullOutputStream;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
import org.junit.jupiter.api.Test;
@@ -61,7 +60,7 @@
request.setStreamProvider(new OutboundMessageContext.StreamProvider() {
@Override
public OutputStream getOutputStream(final int contentLength) throws IOException {
- return new NullOutputStream();
+ return OutputStream.nullOutputStream();
}
});
request.writeEntity();
diff --git a/tests/integration/jersey-2551/pom.xml b/tests/integration/jersey-2551/pom.xml
index f8ea154..d3318cb 100644
--- a/tests/integration/jersey-2551/pom.xml
+++ b/tests/integration/jersey-2551/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2612/pom.xml b/tests/integration/jersey-2612/pom.xml
index a02df34..5c49c19 100644
--- a/tests/integration/jersey-2612/pom.xml
+++ b/tests/integration/jersey-2612/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2637/pom.xml b/tests/integration/jersey-2637/pom.xml
index 1e359f6..485cad5 100644
--- a/tests/integration/jersey-2637/pom.xml
+++ b/tests/integration/jersey-2637/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2654/pom.xml b/tests/integration/jersey-2654/pom.xml
index 70e6076..7ff21a6 100644
--- a/tests/integration/jersey-2654/pom.xml
+++ b/tests/integration/jersey-2654/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2673/pom.xml b/tests/integration/jersey-2673/pom.xml
index f276b15..8c04b5b 100644
--- a/tests/integration/jersey-2673/pom.xml
+++ b/tests/integration/jersey-2673/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2689/pom.xml b/tests/integration/jersey-2689/pom.xml
index ba494d6..5176497 100644
--- a/tests/integration/jersey-2689/pom.xml
+++ b/tests/integration/jersey-2689/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2704/pom.xml b/tests/integration/jersey-2704/pom.xml
index 51b1225..3bbbe91 100644
--- a/tests/integration/jersey-2704/pom.xml
+++ b/tests/integration/jersey-2704/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2776/pom.xml b/tests/integration/jersey-2776/pom.xml
index 7135902..fb99ae9 100644
--- a/tests/integration/jersey-2776/pom.xml
+++ b/tests/integration/jersey-2776/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -42,7 +42,7 @@
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
- <version>3.0.3</version>
+ <version>3.5.8</version>
<scope>test</scope>
</dependency>
diff --git a/tests/integration/jersey-2794/pom.xml b/tests/integration/jersey-2794/pom.xml
index e26de85..5b5e41d 100644
--- a/tests/integration/jersey-2794/pom.xml
+++ b/tests/integration/jersey-2794/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
index 80eca2d..ce9ccdc 100644
--- a/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
+++ b/tests/integration/jersey-2794/src/test/java/org/glassfish/jersey/tests/integration/jersey2794/Jersey2794ITCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,7 +23,6 @@
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.atomic.AtomicInteger;
@@ -104,7 +103,7 @@
private int matchingTempFiles(final String tempDir) throws IOException {
AtomicInteger count = new AtomicInteger(0);
- Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+ Files.walkFileTree(Path.of(tempDir), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.getFileName().startsWith("MIME") && file.getFileName().endsWith("tmp")) {
diff --git a/tests/integration/jersey-2846/pom.xml b/tests/integration/jersey-2846/pom.xml
index bb930e1..fdb90d6 100644
--- a/tests/integration/jersey-2846/pom.xml
+++ b/tests/integration/jersey-2846/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
index 4286aef..6b37da0 100644
--- a/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
+++ b/tests/integration/jersey-2846/src/test/java/org/glassfish/jersey/tests/integration/jersey2846/Jersey2846ITCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,7 +20,6 @@
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
@@ -124,7 +123,7 @@
private int matchingTempFiles(final String tempDir) throws IOException {
AtomicInteger count = new AtomicInteger(0);
- Files.walkFileTree(Paths.get(tempDir), new SimpleFileVisitor<Path>() {
+ Files.walkFileTree(Path.of(tempDir), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path name = file.getFileName();
diff --git a/tests/integration/jersey-2878/pom.xml b/tests/integration/jersey-2878/pom.xml
index 360675b..09f94cf 100644
--- a/tests/integration/jersey-2878/pom.xml
+++ b/tests/integration/jersey-2878/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-2892/pom.xml b/tests/integration/jersey-2892/pom.xml
index 7d0354f..ed77ae1 100644
--- a/tests/integration/jersey-2892/pom.xml
+++ b/tests/integration/jersey-2892/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-3662/pom.xml b/tests/integration/jersey-3662/pom.xml
index 48dde66..ba4e744 100644
--- a/tests/integration/jersey-3662/pom.xml
+++ b/tests/integration/jersey-3662/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-3670/pom.xml b/tests/integration/jersey-3670/pom.xml
index a94375e..43d69bb 100644
--- a/tests/integration/jersey-3670/pom.xml
+++ b/tests/integration/jersey-3670/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-3796/pom.xml b/tests/integration/jersey-3796/pom.xml
index 8ad6e30..ea71991 100644
--- a/tests/integration/jersey-3796/pom.xml
+++ b/tests/integration/jersey-3796/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2018, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2018, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-3992/pom.xml b/tests/integration/jersey-3992/pom.xml
index 6ffef92..68c5217 100644
--- a/tests/integration/jersey-3992/pom.xml
+++ b/tests/integration/jersey-3992/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
diff --git a/tests/integration/jersey-4003/pom.xml b/tests/integration/jersey-4003/pom.xml
index 4fcec64..5f97a69 100644
--- a/tests/integration/jersey-4003/pom.xml
+++ b/tests/integration/jersey-4003/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-4099/pom.xml b/tests/integration/jersey-4099/pom.xml
index 2a13e4d..d30a157 100644
--- a/tests/integration/jersey-4099/pom.xml
+++ b/tests/integration/jersey-4099/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019 Christian Kaltepoth. All rights reserved.
This program and the accompanying materials are made available under the
@@ -85,6 +85,11 @@
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
@@ -97,7 +102,11 @@
</build>
<properties>
<surefire.coverage.argline>
- --add-reads org.jboss.logging=java.logging --add-modules=ALL-MODULE-PATH
+ --add-opens weld.core.impl/org.jboss.weld.logging=org.jboss.logging
+ --add-reads org.jboss.logging=weld.core.impl
+ --add-reads org.jboss.logging=weld.environment.common
+ --add-reads org.jboss.logging=weld.se.core
+ --add-modules=ALL-MODULE-PATH
</surefire.coverage.argline>
</properties>
</project>
diff --git a/tests/integration/jersey-4099/src/test/java/module-info.java b/tests/integration/jersey-4099/src/test/java/module-info.java
index 428bc79..7135e70 100644
--- a/tests/integration/jersey-4099/src/test/java/module-info.java
+++ b/tests/integration/jersey-4099/src/test/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,6 +26,7 @@
requires org.glassfish.jersey.core.server;
requires org.junit.jupiter.api;
+ requires org.junit.platform.engine;
requires org.glassfish.jersey.tests.framework.core;
requires org.glassfish.jersey.tests.framework.provider.grizzly;
diff --git a/tests/integration/jersey-4321/pom.xml b/tests/integration/jersey-4321/pom.xml
index d273d79..72c275c 100644
--- a/tests/integration/jersey-4321/pom.xml
+++ b/tests/integration/jersey-4321/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019 Christian Kaltepoth. All rights reserved.
This program and the accompanying materials are made available under the
diff --git a/tests/integration/jersey-4507/pom.xml b/tests/integration/jersey-4507/pom.xml
index 883ce16..0a5e6bc 100644
--- a/tests/integration/jersey-4507/pom.xml
+++ b/tests/integration/jersey-4507/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-4542/pom.xml b/tests/integration/jersey-4542/pom.xml
index 9941ed9..ba0db35 100644
--- a/tests/integration/jersey-4542/pom.xml
+++ b/tests/integration/jersey-4542/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-4697/pom.xml b/tests/integration/jersey-4697/pom.xml
index 6674d5f..bfd7b05 100644
--- a/tests/integration/jersey-4697/pom.xml
+++ b/tests/integration/jersey-4697/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-4722/pom.xml b/tests/integration/jersey-4722/pom.xml
index 962bd15..5dd0445 100644
--- a/tests/integration/jersey-4722/pom.xml
+++ b/tests/integration/jersey-4722/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-4949/pom.xml b/tests/integration/jersey-4949/pom.xml
index c3f0dce..88e26df 100644
--- a/tests/integration/jersey-4949/pom.xml
+++ b/tests/integration/jersey-4949/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/jersey-5087/pom.xml b/tests/integration/jersey-5087/pom.xml
index 7b51fae..b82f788 100644
--- a/tests/integration/jersey-5087/pom.xml
+++ b/tests/integration/jersey-5087/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -81,6 +81,12 @@
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-jetty-connector</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
@@ -330,4 +336,15 @@
<maven.test.skip>true</maven.test.skip> <!-- do not run any tests here, it's useless,
dependencies clash is being tested even before compilation. -->
</properties>
+ <profiles>
+ <profile>
+ <id>jdk_11_17</id>
+ <activation>
+ <jdk>[11,17)</jdk>
+ </activation>
+ <properties>
+ <slf4j.version>2.0.13</slf4j.version>
+ </properties>
+ </profile>
+ </profiles>
</project>
\ No newline at end of file
diff --git a/tests/integration/jersey-780/pom.xml b/tests/integration/jersey-780/pom.xml
index 5dc94ef..f375d10 100644
--- a/tests/integration/jersey-780/pom.xml
+++ b/tests/integration/jersey-780/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/microprofile/config/helidon/pom.xml b/tests/integration/microprofile/config/helidon/pom.xml
index 85ad69d..674c9a5 100644
--- a/tests/integration/microprofile/config/helidon/pom.xml
+++ b/tests/integration/microprofile/config/helidon/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/microprofile/config/pom.xml b/tests/integration/microprofile/config/pom.xml
index 93c8534..b44cddd 100644
--- a/tests/integration/microprofile/config/pom.xml
+++ b/tests/integration/microprofile/config/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/microprofile/config/webapp/pom.xml b/tests/integration/microprofile/config/webapp/pom.xml
index 81d1df7..519e2da 100644
--- a/tests/integration/microprofile/config/webapp/pom.xml
+++ b/tests/integration/microprofile/config/webapp/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/microprofile/pom.xml b/tests/integration/microprofile/pom.xml
index a7abb48..d9dff8b 100644
--- a/tests/integration/microprofile/pom.xml
+++ b/tests/integration/microprofile/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -34,6 +34,7 @@
<module>config</module>
<module>rest-client</module>
<module>rest-client-tck</module>
+ <module>rest-client-tck3</module>
</modules>
<build>
diff --git a/tests/integration/microprofile/rest-client-tck/pom.xml b/tests/integration/microprofile/rest-client-tck/pom.xml
index 7f8a829..60bb5a0 100644
--- a/tests/integration/microprofile/rest-client-tck/pom.xml
+++ b/tests/integration/microprofile/rest-client-tck/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -35,6 +35,24 @@
<artifactId>jersey-mp-rest-client</artifactId>
<version>${project.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.microprofile.rest.client</groupId>
+ <artifactId>microprofile-rest-client-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.rest.client</groupId>
+ <artifactId>microprofile-rest-client-api</artifactId>
+ <version>${microprofile.rest.client.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.rest.client</groupId>
+ <artifactId>microprofile-rest-client-tck</artifactId>
+ <version>${microprofile.rest.client.version}</version>
+ <scope>test</scope>
</dependency>
<!-- Overrides CDI from parent pom -->
<dependency>
@@ -51,9 +69,8 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>4.0.1</version>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
@@ -62,21 +79,15 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.eclipse.microprofile.rest.client</groupId>
- <artifactId>microprofile-rest-client-tck</artifactId>
- <version>${microprofile.rest.client.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
- <version>${testng6.version}</version>
+ <version>${testng.version}</version>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>com.github.tomakehurst</groupId>
+ <groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
- <version>${wiremock.version}</version>
+ <version>${wiremock.jetty11.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -171,6 +182,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-weld2-se</artifactId>
<scope>test</scope>
@@ -239,11 +255,20 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>securityOff</id>
+ <activation>
+ <jdk>[24,)</jdk>
+ </activation>
+ <properties>
+ <surefire.security.argline />
+ </properties>
+ </profile>
</profiles>
<properties>
<surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>
- <jetty.version>${jetty9.version}</jetty.version>
+ <jetty.version>${jetty11.version}</jetty.version>
</properties>
diff --git a/tests/integration/microprofile/rest-client-tck3/pom.xml b/tests/integration/microprofile/rest-client-tck3/pom.xml
new file mode 100644
index 0000000..c98a715
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/pom.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>microprofile-integration-project</artifactId>
+ <groupId>org.glassfish.jersey.tests.integration.microprofile</groupId>
+ <version>3.5.99-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>jersey-rest-client-tck3</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.microprofile</groupId>
+ <artifactId>jersey-mp-rest-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- Overrides CDI from parent pom -->
+ <dependency>
+ <groupId>jakarta.enterprise</groupId>
+ <artifactId>jakarta.enterprise.cdi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.ejb</groupId>
+ <artifactId>jakarta.ejb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>4.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>io.smallrye.config</groupId>
+ <artifactId>smallrye-config</artifactId>
+ <version>${smallrye.config.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.rest.client</groupId>
+ <artifactId>microprofile-rest-client-tck</artifactId>
+ <version>${microprofile.rest.client.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>${testng6.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock</artifactId>
+ <version>${wiremock.jetty9.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-proxy</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-proxy</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.testng</groupId>
+ <artifactId>arquillian-testng-container</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-test-spi</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-weld-embedded</artifactId>
+ <version>${arquillian.weld.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit4.version}</version>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>testRunner</id>
+<!-- DO NOT ACTIVATE BY DEFAULT, tests are run by rest-client-tck (4) -->
+<!-- Kept for case of an error found in version 3 -->
+<!-- <activation>-->
+<!-- <property>-->
+<!-- <name>skipTests</name>-->
+<!-- <value>!true</value>-->
+<!-- </property>-->
+<!-- <jdk>[17,)</jdk>-->
+<!-- </activation>-->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.mvn.plugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-testng</artifactId>
+ <version>${surefire.mvn.plugin.version}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <threadCount>1</threadCount>
+ <suiteXmlFiles>
+ <suiteXmlFile>tck-suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+<!-- <argLine>-verbose:class</argLine>-->
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>uk.co.deliverymind</groupId>
+ <artifactId>wiremock-maven-plugin</artifactId>
+ <version>${wiremock.mvn.plugin.version}</version>
+ <executions>
+ <execution>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <dir>target/classes</dir>
+ <params>--port=8765</params>
+ <!-- Enable verbose for more detailed output-->
+ <!-- <params>--verbose</params>-->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>securityOff</id>
+ <activation>
+ <jdk>[24,)</jdk>
+ </activation>
+ <properties>
+ <surefire.security.argline />
+ </properties>
+ </profile>
+ </profiles>
+
+ <properties>
+ <surefire.security.argline>-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/server.policy</surefire.security.argline>
+ <jetty.version>${jetty9.version}</jetty.version>
+ <microprofile.rest.client.version>${microprofile.rest.client3.version}</microprofile.rest.client.version>
+ </properties>
+
+
+</project>
diff --git a/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml b/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..fffd8c9
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/src/test/resources/arquillian.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<arquillian xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+ <engine>
+ <property name="deploymentExportPath">target/deployments</property>
+ </engine>
+</arquillian>
diff --git a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java b/tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
similarity index 76%
copy from test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
copy to tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
index 0fdbe9d..d448842 100644
--- a/test-framework/providers/jetty11-http2/src/main/java/org/glassfish/jersey/test/jetty11/http2/package-info.java
+++ b/tests/integration/microprofile/rest-client-tck3/src/test/resources/server.policy
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -14,7 +14,6 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-/**
- * Jersey test framework for Jetty 11 HTTP/2 Container.
- */
-package org.glassfish.jersey.test.jetty11.http2;
+grant {
+ permission java.security.AllPermission;
+};
diff --git a/tests/integration/microprofile/rest-client-tck3/tck-suite.xml b/tests/integration/microprofile/rest-client-tck3/tck-suite.xml
new file mode 100644
index 0000000..c83fae3
--- /dev/null
+++ b/tests/integration/microprofile/rest-client-tck3/tck-suite.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<!--
+
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<suite name="microprofile-rest-client-TCK" verbose="2" configfailurepolicy="continue">
+
+ <test name="microprofile-rest-client TCK">
+ <packages>
+ <package name="org.eclipse.microprofile.rest.client.tck.*">
+ </package>
+ </packages>
+ </test>
+
+</suite>
diff --git a/tests/integration/microprofile/rest-client/pom.xml b/tests/integration/microprofile/rest-client/pom.xml
index 55516a7..001014e 100644
--- a/tests/integration/microprofile/rest-client/pom.xml
+++ b/tests/integration/microprofile/rest-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -107,6 +107,15 @@
</dependency>
</dependencies>
</profile>
+ <profile>
+ <id>securityOff</id>
+ <activation>
+ <jdk>[24,)</jdk>
+ </activation>
+ <properties>
+ <surefire.security.argline />
+ </properties>
+ </profile>
</profiles>
<properties>
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java
new file mode 100644
index 0000000..fd31fe8
--- /dev/null
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/HttpHeaderTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.test.microprofile.restclient;
+
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class HttpHeaderTest {
+ @Path("/")
+ public interface HeaderResource {
+ @GET
+ public String get();
+ }
+
+ @Test
+ public void restclientBuilderWithHeadersTest() {
+ String headerName = "BUILDER_HEADER";
+ String headerValue = "BUILDER_VALUE";
+ HeaderResource resource = RestClientBuilder.newBuilder()
+ .baseUri("http://localhost:8080")
+ .register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ if (requestContext.getHeaders().containsKey(headerName)) {
+ requestContext.abortWith(Response.ok(requestContext.getHeaders().getFirst(headerName)).build());
+ } else {
+ requestContext.abortWith(Response.ok("no_header").build());
+ }
+ }
+ })
+ .header(headerName, headerValue)
+ .build(HeaderResource.class);
+ Assertions.assertEquals(headerValue, resource.get());
+ }
+
+ @ClientHeaderParam(name = "InterfaceAndBuilderHeader", value = "interface")
+ @Path("/")
+ public interface ClientBuilderHeaderClient {
+
+ @GET
+ JsonObject getAllHeaders(@HeaderParam("HeaderParam") String param);
+ }
+
+ public static class ReturnWithAllDuplicateClientHeadersFilter implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext clientRequestContext) throws IOException {
+ JsonObjectBuilder allClientHeaders = Json.createObjectBuilder();
+ MultivaluedMap<String, Object> clientHeaders = clientRequestContext.getHeaders();
+ for (String headerName : clientHeaders.keySet()) {
+ List<Object> header = clientHeaders.get(headerName);
+ final JsonArrayBuilder headerValues = Json.createArrayBuilder();
+ header.forEach(h -> headerValues.add(h.toString()));
+ allClientHeaders.add(headerName, headerValues);
+ }
+ clientRequestContext.abortWith(Response.ok(allClientHeaders.build()).build());
+ }
+
+ }
+
+ @Test
+ public void testHeaderBuilderInterface() {
+
+ RestClientBuilder builder = RestClientBuilder.newBuilder().baseUri("http://localhost:8080/");
+ builder.register(ReturnWithAllDuplicateClientHeadersFilter.class);
+ builder.header("InterfaceAndBuilderHeader", "builder");
+ ClientBuilderHeaderClient client = builder.build(ClientBuilderHeaderClient.class);
+
+ checkHeaders(client.getAllHeaders("headerparam"), "interface");
+ }
+
+ private static void checkHeaders(final JsonObject headers, final String clientHeaderParamName) {
+ final List<String> clientRequestHeaders = headerValues(headers, "InterfaceAndBuilderHeader");
+
+ assertTrue(clientRequestHeaders.contains("builder"),
+ "Header InterfaceAndBuilderHeader did not container \"builder\": " + clientRequestHeaders);
+ assertTrue(clientRequestHeaders.contains(clientHeaderParamName),
+ "Header InterfaceAndBuilderHeader did not container \"" + clientHeaderParamName + "\": "
+ + clientRequestHeaders);
+
+ final List<String> headerParamHeaders = headerValues(headers, "HeaderParam");
+ assertTrue(headerParamHeaders.contains("headerparam"),
+ "Header HeaderParam did not container \"headerparam\": " + headerParamHeaders);
+ }
+
+ private static List<String> headerValues(final JsonObject headers, final String headerName) {
+ final JsonArray headerValues = headers.getJsonArray(headerName);
+ Assertions.assertNotNull(headerValues,
+ String.format("Expected header '%s' to be present in %s", headerName, headers));
+ return headerValues.stream().map(
+ v -> (v.getValueType() == JsonValue.ValueType.STRING ? ((JsonString) v).getString() : v.toString()))
+ .collect(Collectors.toList());
+ }
+
+}
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
index 3d75a50..f2870ca 100644
--- a/tests/integration/pom.xml
+++ b/tests/integration/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
@@ -159,6 +159,7 @@
<module>jersey-2892</module>
<module>jersey-3796</module>
<module>jersey-4949</module>
+ <module>resteasy-client</module>
<module>security-digest</module>
<module>servlet-2.5-autodiscovery-1</module>
<module>servlet-2.5-autodiscovery-2</module>
diff --git a/tests/integration/property-check/pom.xml b/tests/integration/property-check/pom.xml
index 42c9810..47d4eb4 100644
--- a/tests/integration/property-check/pom.xml
+++ b/tests/integration/property-check/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -74,6 +74,16 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache5-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jnh-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.glassfish.jersey.security</groupId>
<artifactId>oauth1-server</artifactId>
<version>${project.version}</version>
@@ -109,28 +119,4 @@
</plugin>
</plugins>
</build>
-
- <profiles>
- <profile>
- <id>jdk19+</id>
- <activation>
- <jdk>[19,)</jdk>
- </activation>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>**/SystemPropertiesConfigurationModelTest.java</exclude>
- </excludes>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
- </profile>
- </profiles>
</project>
diff --git a/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java b/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
index ddb8e08..00701ff 100644
--- a/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
+++ b/tests/integration/property-check/src/test/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModelTest.java
@@ -1,5 +1,5 @@
/*
- * 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
@@ -32,12 +32,14 @@
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.apache.connector.ApacheClientProperties;
+import org.glassfish.jersey.apache5.connector.Apache5ClientProperties;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.internal.InternalProperties;
import org.glassfish.jersey.internal.util.JdkVersion;
import org.glassfish.jersey.internal.util.PropertiesClass;
import org.glassfish.jersey.internal.util.Property;
import org.glassfish.jersey.jetty.connector.JettyClientProperties;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpClientProperties;
import org.glassfish.jersey.media.multipart.MultiPartProperties;
import org.glassfish.jersey.message.MessageProperties;
import org.glassfish.jersey.server.ServerProperties;
@@ -79,8 +81,13 @@
@Test
public void propertyLoadedWhenSecurityException() {
final String TEST_STRING = "test";
- SecurityManager sm = System.getSecurityManager();
- String policy = System.getProperty("java.security.policy");
+ final boolean isSm = JdkVersion.getJdkVersion().getMajor() < 19;
+ SecurityManager sm = null;
+ String policy = null;
+ if (isSm) {
+ sm = System.getSecurityManager();
+ policy = System.getProperty("java.security.policy");
+ }
try {
System.setProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.TRUE.toString());
System.setProperty(ServerProperties.APPLICATION_NAME, TEST_STRING);
@@ -88,15 +95,21 @@
System.setProperty(ServletProperties.JAXRS_APPLICATION_CLASS, TEST_STRING);
System.setProperty(MessageProperties.IO_BUFFER_SIZE, TEST_STRING);
System.setProperty(ApacheClientProperties.DISABLE_COOKIES, TEST_STRING);
+ System.setProperty(Apache5ClientProperties.DISABLE_COOKIES, TEST_STRING);
System.setProperty(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, TEST_STRING);
+ System.setProperty(JavaNetHttpClientProperties.DISABLE_COOKIES, TEST_STRING);
System.setProperty(MultiPartProperties.TEMP_DIRECTORY, TEST_STRING);
System.setProperty(OAuth1ServerProperties.REALM, TEST_STRING);
JerseySystemPropertiesConfigurationModel model = new JerseySystemPropertiesConfigurationModel();
assertTrue(model.as(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.class));
- String securityPolicy = SystemPropertiesConfigurationModelTest.class.getResource("/server.policy").getFile();
- System.setProperty("java.security.policy", securityPolicy);
- SecurityManager manager = new SecurityManager();
- System.setSecurityManager(manager);
+
+ if (isSm) {
+ String securityPolicy = SystemPropertiesConfigurationModelTest.class.getResource("/server.policy").getFile();
+ System.setProperty("java.security.policy", securityPolicy);
+ SecurityManager manager = new SecurityManager();
+ System.setSecurityManager(manager);
+ }
+
Map<String, Object> properties = model.getProperties();
assertEquals(TEST_STRING, properties.get(ServerProperties.APPLICATION_NAME));
assertEquals(Boolean.TRUE.toString(), properties.get(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER));
@@ -109,9 +122,13 @@
assertEquals(TEST_STRING, properties.get(MessageProperties.IO_BUFFER_SIZE));
assertFalse(properties.containsKey(MessageProperties.DEFLATE_WITHOUT_ZLIB));
assertEquals(TEST_STRING, properties.get(ApacheClientProperties.DISABLE_COOKIES));
+ assertEquals(TEST_STRING, properties.get(Apache5ClientProperties.DISABLE_COOKIES));
assertFalse(properties.containsKey(ApacheClientProperties.CONNECTION_MANAGER));
+ assertFalse(properties.containsKey(Apache5ClientProperties.CONNECTION_MANAGER));
assertEquals(TEST_STRING, properties.get(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION));
assertFalse(properties.containsKey(JettyClientProperties.DISABLE_COOKIES));
+ assertEquals(TEST_STRING, properties.get(JavaNetHttpClientProperties.DISABLE_COOKIES));
+ assertFalse(properties.containsKey(JavaNetHttpClientProperties.SSL_PARAMETERS));
assertEquals(TEST_STRING, properties.get(MultiPartProperties.TEMP_DIRECTORY));
assertFalse(properties.containsKey(MultiPartProperties.BUFFER_THRESHOLD));
assertEquals(TEST_STRING, properties.get(OAuth1ServerProperties.REALM));
@@ -120,7 +137,9 @@
if (policy != null) {
System.setProperty("java.security.policy", policy);
}
- System.setSecurityManager(sm);
+ if (isSm) {
+ System.setSecurityManager(sm);
+ }
}
}
diff --git a/tests/integration/reactive-streams/pom.xml b/tests/integration/reactive-streams/pom.xml
index 63992b4..6692a4f 100644
--- a/tests/integration/reactive-streams/pom.xml
+++ b/tests/integration/reactive-streams/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/reactive-streams/sse/pom.xml b/tests/integration/reactive-streams/sse/pom.xml
index 5636c6a..35f8814 100644
--- a/tests/integration/reactive-streams/sse/pom.xml
+++ b/tests/integration/reactive-streams/sse/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/resteasy-client/pom.xml b/tests/integration/resteasy-client/pom.xml
new file mode 100644
index 0000000..a4be16e
--- /dev/null
+++ b/tests/integration/resteasy-client/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration</groupId>
+ <artifactId>project</artifactId>
+ <version>3.5.99-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>spring-boot</artifactId>
+
+ <packaging>war</packaging>
+ <name>jersey-tests-integration-spring6</name>
+
+ <description>
+ Jersey tests for Spring.Boot / Resteasy integration
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-client</artifactId>
+ <version>6.2.11.Final</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-logging</artifactId>
+ <groupId>commons-logging</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java b/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java
new file mode 100644
index 0000000..de1461f
--- /dev/null
+++ b/tests/integration/resteasy-client/src/test/java/org/glassfish/jersey/tests/springboot/RestEasyClientTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.springboot;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.concurrent.CountDownLatch;
+
+public class RestEasyClientTest extends JerseyTest {
+
+ private static final CountDownLatch readFromLatch = new CountDownLatch(1);
+
+ @Path("/")
+ public static class RestEasyClientTestResource {
+ @POST
+ @Path("/test")
+ @Produces(MediaType.APPLICATION_JSON)
+ public String testPost(String echo) {
+ return echo;
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new ResourceConfig(RestEasyClientTestResource.class);
+ }
+
+ @Test
+ public void test() throws InterruptedException {
+ try (final ResteasyClient client = new ResteasyClientBuilderImpl().build()) {
+ client.register(TestDefaultJacksonJaxbJsonProvider.class);
+
+ try (final Response r = client.target(target().getUri()).path("/test")
+ .request().post(Entity.entity("{\"test\": \"test\"}", MediaType.APPLICATION_JSON))) {
+ Object o = r.readEntity(Object.class);
+ Assertions.assertTrue(o.toString().contains("test"));
+ readFromLatch.await();
+ Assertions.assertEquals(0, readFromLatch.getCount(), "DefaultJacksonJaxbJsonProvider has not been used");
+ }
+ }
+ }
+
+ public static class TestDefaultJacksonJaxbJsonProvider extends DefaultJacksonJaxbJsonProvider {
+ public TestDefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
+ super(providers, config);
+ }
+
+ @Override
+ public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
+ readFromLatch.countDown();
+ return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
+ }
+ }
+
+}
diff --git a/tests/integration/security-digest/pom.xml b/tests/integration/security-digest/pom.xml
index 9ce4369..e2183c5 100644
--- a/tests/integration/security-digest/pom.xml
+++ b/tests/integration/security-digest/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-autodiscovery-1/pom.xml b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
index 6d6f354..6b3fd7a 100644
--- a/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
+++ b/tests/integration/servlet-2.5-autodiscovery-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-autodiscovery-2/pom.xml b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
index 741f4d1..63eeca1 100644
--- a/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
+++ b/tests/integration/servlet-2.5-autodiscovery-2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-filter/pom.xml b/tests/integration/servlet-2.5-filter/pom.xml
index 82469b3..4c1b516 100644
--- a/tests/integration/servlet-2.5-filter/pom.xml
+++ b/tests/integration/servlet-2.5-filter/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-inflector-1/pom.xml b/tests/integration/servlet-2.5-inflector-1/pom.xml
index 05cf37d..3e9b3a9 100644
--- a/tests/integration/servlet-2.5-inflector-1/pom.xml
+++ b/tests/integration/servlet-2.5-inflector-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-1/pom.xml b/tests/integration/servlet-2.5-init-1/pom.xml
index 9cd5579..85c8a56 100644
--- a/tests/integration/servlet-2.5-init-1/pom.xml
+++ b/tests/integration/servlet-2.5-init-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-2/pom.xml b/tests/integration/servlet-2.5-init-2/pom.xml
index 4c24000..3d49904 100644
--- a/tests/integration/servlet-2.5-init-2/pom.xml
+++ b/tests/integration/servlet-2.5-init-2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-3/pom.xml b/tests/integration/servlet-2.5-init-3/pom.xml
index b2fd51b..cb77660 100644
--- a/tests/integration/servlet-2.5-init-3/pom.xml
+++ b/tests/integration/servlet-2.5-init-3/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-4/pom.xml b/tests/integration/servlet-2.5-init-4/pom.xml
index cbdbce6..cf43ab4 100644
--- a/tests/integration/servlet-2.5-init-4/pom.xml
+++ b/tests/integration/servlet-2.5-init-4/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-5/pom.xml b/tests/integration/servlet-2.5-init-5/pom.xml
index 373cd69..746a9ea 100644
--- a/tests/integration/servlet-2.5-init-5/pom.xml
+++ b/tests/integration/servlet-2.5-init-5/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-6/pom.xml b/tests/integration/servlet-2.5-init-6/pom.xml
index 86876ae..834d402 100644
--- a/tests/integration/servlet-2.5-init-6/pom.xml
+++ b/tests/integration/servlet-2.5-init-6/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-7/pom.xml b/tests/integration/servlet-2.5-init-7/pom.xml
index 779892e..f389c49 100644
--- a/tests/integration/servlet-2.5-init-7/pom.xml
+++ b/tests/integration/servlet-2.5-init-7/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-init-8/pom.xml b/tests/integration/servlet-2.5-init-8/pom.xml
index 6dbfe77..2136c32 100644
--- a/tests/integration/servlet-2.5-init-8/pom.xml
+++ b/tests/integration/servlet-2.5-init-8/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-mvc-1/pom.xml b/tests/integration/servlet-2.5-mvc-1/pom.xml
index eb37fb0..4616d42 100644
--- a/tests/integration/servlet-2.5-mvc-1/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-mvc-2/pom.xml b/tests/integration/servlet-2.5-mvc-2/pom.xml
index 49a7fef..0de5f1f 100644
--- a/tests/integration/servlet-2.5-mvc-2/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-mvc-3/pom.xml b/tests/integration/servlet-2.5-mvc-3/pom.xml
index a3f322c..cf94ea6 100644
--- a/tests/integration/servlet-2.5-mvc-3/pom.xml
+++ b/tests/integration/servlet-2.5-mvc-3/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-2.5-reload/pom.xml b/tests/integration/servlet-2.5-reload/pom.xml
index 2ed4d84..279350f 100644
--- a/tests/integration/servlet-2.5-reload/pom.xml
+++ b/tests/integration/servlet-2.5-reload/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-async/pom.xml b/tests/integration/servlet-3-async/pom.xml
index 62c7f45..cdea9f1 100644
--- a/tests/integration/servlet-3-async/pom.xml
+++ b/tests/integration/servlet-3-async/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-chunked-io/pom.xml b/tests/integration/servlet-3-chunked-io/pom.xml
index 1672ebd..49d4cb6 100644
--- a/tests/integration/servlet-3-chunked-io/pom.xml
+++ b/tests/integration/servlet-3-chunked-io/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-filter/pom.xml b/tests/integration/servlet-3-filter/pom.xml
index b45643a..a7dbd3f 100644
--- a/tests/integration/servlet-3-filter/pom.xml
+++ b/tests/integration/servlet-3-filter/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-gf-async/pom.xml b/tests/integration/servlet-3-gf-async/pom.xml
index 421dd08..5d60547 100644
--- a/tests/integration/servlet-3-gf-async/pom.xml
+++ b/tests/integration/servlet-3-gf-async/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-inflector-1/pom.xml b/tests/integration/servlet-3-inflector-1/pom.xml
index 0e53e0f..41c3b16 100644
--- a/tests/integration/servlet-3-inflector-1/pom.xml
+++ b/tests/integration/servlet-3-inflector-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-1/pom.xml b/tests/integration/servlet-3-init-1/pom.xml
index f1eeabb..194f133 100644
--- a/tests/integration/servlet-3-init-1/pom.xml
+++ b/tests/integration/servlet-3-init-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-2/pom.xml b/tests/integration/servlet-3-init-2/pom.xml
index 2253185..1bd444c 100644
--- a/tests/integration/servlet-3-init-2/pom.xml
+++ b/tests/integration/servlet-3-init-2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-3/pom.xml b/tests/integration/servlet-3-init-3/pom.xml
index db1a130..f5c4b6d 100644
--- a/tests/integration/servlet-3-init-3/pom.xml
+++ b/tests/integration/servlet-3-init-3/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-4/pom.xml b/tests/integration/servlet-3-init-4/pom.xml
index 66bc383..80c33cb 100644
--- a/tests/integration/servlet-3-init-4/pom.xml
+++ b/tests/integration/servlet-3-init-4/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-5/pom.xml b/tests/integration/servlet-3-init-5/pom.xml
index de604ef..6f3a387 100644
--- a/tests/integration/servlet-3-init-5/pom.xml
+++ b/tests/integration/servlet-3-init-5/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-6/pom.xml b/tests/integration/servlet-3-init-6/pom.xml
index 205dde7..ce34d7c 100644
--- a/tests/integration/servlet-3-init-6/pom.xml
+++ b/tests/integration/servlet-3-init-6/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-7/pom.xml b/tests/integration/servlet-3-init-7/pom.xml
index d826dce..6a36003 100644
--- a/tests/integration/servlet-3-init-7/pom.xml
+++ b/tests/integration/servlet-3-init-7/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-8/pom.xml b/tests/integration/servlet-3-init-8/pom.xml
index 7e42880..db5e92f 100644
--- a/tests/integration/servlet-3-init-8/pom.xml
+++ b/tests/integration/servlet-3-init-8/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-9/pom.xml b/tests/integration/servlet-3-init-9/pom.xml
index 2162a9c..9754ed8 100644
--- a/tests/integration/servlet-3-init-9/pom.xml
+++ b/tests/integration/servlet-3-init-9/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-init-provider/pom.xml b/tests/integration/servlet-3-init-provider/pom.xml
index 93dd20f..9e37c0f 100644
--- a/tests/integration/servlet-3-init-provider/pom.xml
+++ b/tests/integration/servlet-3-init-provider/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-params/pom.xml b/tests/integration/servlet-3-params/pom.xml
index f5dc93c..e21cbc0 100644
--- a/tests/integration/servlet-3-params/pom.xml
+++ b/tests/integration/servlet-3-params/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-3-sse-1/pom.xml b/tests/integration/servlet-3-sse-1/pom.xml
index 6d90cc9..25ee9f5 100644
--- a/tests/integration/servlet-3-sse-1/pom.xml
+++ b/tests/integration/servlet-3-sse-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-4.0-mvc-1/pom.xml b/tests/integration/servlet-4.0-mvc-1/pom.xml
index 99d8251..7b9f095 100644
--- a/tests/integration/servlet-4.0-mvc-1/pom.xml
+++ b/tests/integration/servlet-4.0-mvc-1/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-request-wrapper-binding-2/pom.xml b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
index 4c78d5a..3a5ed71 100644
--- a/tests/integration/servlet-request-wrapper-binding-2/pom.xml
+++ b/tests/integration/servlet-request-wrapper-binding-2/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-request-wrapper-binding/pom.xml b/tests/integration/servlet-request-wrapper-binding/pom.xml
index 237fe5e..644f560 100644
--- a/tests/integration/servlet-request-wrapper-binding/pom.xml
+++ b/tests/integration/servlet-request-wrapper-binding/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/servlet-tests/pom.xml b/tests/integration/servlet-tests/pom.xml
index a9ef073..417d910 100644
--- a/tests/integration/servlet-tests/pom.xml
+++ b/tests/integration/servlet-tests/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -48,6 +48,7 @@
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-external</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java
new file mode 100644
index 0000000..856e2ef
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorFilter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+import java.io.IOException;
+
+import static org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource.ERROR_MESSAGE;
+
+public class PostProcessingErrorFilter implements Filter {
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ Filter.super.init(filterConfig);
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException {
+
+ try {
+ chain.doFilter(request, response);
+ } catch (ServletException ex) {
+ //post-processing attempt
+ final Throwable orig = ex.getRootCause();
+ if (orig.getMessage().equalsIgnoreCase(ERROR_MESSAGE)) {
+ response.getWriter().print(ERROR_MESSAGE);
+ response.getWriter().flush();
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ Filter.super.destroy();
+ }
+}
diff --git a/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java
new file mode 100644
index 0000000..b9d3451
--- /dev/null
+++ b/tests/integration/servlet-tests/src/main/java/org/glassfish/jersey/tests/integration/servlettests/PostProcessingErrorResource.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import jakarta.servlet.http.HttpServlet;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+
+@Path("postprocessing")
+public class PostProcessingErrorResource extends HttpServlet {
+
+ static final String ERROR_MESSAGE = "Must be post processed";
+ @GET
+ public Response getException() {
+ throw new ProcessingException(ERROR_MESSAGE);
+ }
+
+}
diff --git a/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
index 5d9d99e..813b221 100644
--- a/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
+++ b/tests/integration/servlet-tests/src/main/webapp/WEB-INF/web.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -157,4 +157,31 @@
<filter-name>custom404</filter-name>
<url-pattern>/custom404/*</url-pattern>
</filter-mapping>
+
+ <!-- post process errors (40*, 50*) -->
+ <filter>
+ <filter-name>PostProcessFilter</filter-name>
+ <filter-class>org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorFilter</filter-class>
+ </filter>
+ <servlet>
+ <servlet-name>PostProcessServlet</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.classnames</param-name>
+ <param-value>org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource</param-value>
+ </init-param>
+ <init-param>
+ <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>PostProcessServlet</servlet-name>
+ <url-pattern>/postProcess/*</url-pattern>
+ </servlet-mapping>
+ <filter-mapping>
+ <filter-name>PostProcessFilter</filter-name>
+ <url-pattern>/postProcess/*</url-pattern>
+ </filter-mapping>
</web-app>
diff --git a/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java
new file mode 100644
index 0000000..dbab315
--- /dev/null
+++ b/tests/integration/servlet-tests/src/test/java/org/glassfish/jersey/tests/integration/servlettests/PostProcesingITCase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.servlettests;
+
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.jupiter.api.Test;
+
+import java.util.Locale;
+
+import static org.glassfish.jersey.tests.integration.servlettests.PostProcessingErrorResource.ERROR_MESSAGE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class PostProcesingITCase extends JerseyTest {
+
+ @Override
+ protected Application configure() {
+ // dummy resource config
+ return new ResourceConfig();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new ExternalTestContainerFactory();
+ }
+
+ @Test
+ public void testPostProcessingLocale() {
+ final Response response = target()
+ .path("postProcess/postprocessing")
+ .request().get();
+ assertEquals(ERROR_MESSAGE, response.readEntity(String.class));
+ }
+
+}
diff --git a/tests/integration/sonar-test/pom.xml b/tests/integration/sonar-test/pom.xml
index 31445d8..87a9430 100644
--- a/tests/integration/sonar-test/pom.xml
+++ b/tests/integration/sonar-test/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/spring6/pom.xml b/tests/integration/spring6/pom.xml
index b472582..5b26bc5 100644
--- a/tests/integration/spring6/pom.xml
+++ b/tests/integration/spring6/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/thin-server/pom.xml b/tests/integration/thin-server/pom.xml
index aa82717..9b3604b 100644
--- a/tests/integration/thin-server/pom.xml
+++ b/tests/integration/thin-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/integration/tracing-support/pom.xml b/tests/integration/tracing-support/pom.xml
index 8ea0e49..a11659b 100644
--- a/tests/integration/tracing-support/pom.xml
+++ b/tests/integration/tracing-support/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -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>
@@ -87,4 +102,34 @@
</plugin>
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>jdk11+</id>
+ <activation>
+ <jdk>[11,)</jdk>
+ </activation>
+ <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/jmockit/pom.xml b/tests/jmockit/pom.xml
index 501669a..afaa01b 100644
--- a/tests/jmockit/pom.xml
+++ b/tests/jmockit/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/pom.xml b/tests/mem-leaks/pom.xml
index 75823db..d0bafa5 100644
--- a/tests/mem-leaks/pom.xml
+++ b/tests/mem-leaks/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/redeployment/pom.xml b/tests/mem-leaks/redeployment/pom.xml
index 35efd8b..d0cc7fb 100644
--- a/tests/mem-leaks/redeployment/pom.xml
+++ b/tests/mem-leaks/redeployment/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
index 6b1cc45..ba9e93f 100644
--- a/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-hello-world-app-ref/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
index f2de6c3..3c2a4e4 100644
--- a/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-leaking-test-app/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
index 77f6831..1e103cb 100644
--- a/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-no-jersey-app/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
index e46342a..d578f03 100644
--- a/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
+++ b/tests/mem-leaks/redeployment/redeployment-threadlocals-app/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/test-cases/bean-param-leak/pom.xml b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
index e5ebac5..d8fcc6c 100644
--- a/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
+++ b/tests/mem-leaks/test-cases/bean-param-leak/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/test-cases/leaking-test-app/pom.xml b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
index 2add399..010d1e7 100644
--- a/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
+++ b/tests/mem-leaks/test-cases/leaking-test-app/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/test-cases/pom.xml b/tests/mem-leaks/test-cases/pom.xml
index 530b992..91d537b 100644
--- a/tests/mem-leaks/test-cases/pom.xml
+++ b/tests/mem-leaks/test-cases/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
index e48b626..76c2dbe 100644
--- a/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
index f158135..9495248 100644
--- a/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
+++ b/tests/mem-leaks/test-cases/shutdown-hook-leak/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/osgi/functional/pom.xml b/tests/osgi/functional/pom.xml
index 7f38592..a497c35 100644
--- a/tests/osgi/functional/pom.xml
+++ b/tests/osgi/functional/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -151,6 +151,12 @@
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-forked</artifactId>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
@@ -170,7 +176,13 @@
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
- <version>2.6.2</version>
+ <version>2.6.14</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </exclusion>
+ </exclusions>
<scope>test</scope>
</dependency>
<dependency>
@@ -204,7 +216,7 @@
<groupId>org.ops4j.pax.logging</groupId>
<artifactId>pax-logging-api</artifactId>
<scope>test</scope>
- <version>1.11.5</version>
+ <version>1.11.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
@@ -305,8 +317,8 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>jakarta.el</artifactId>
+ <groupId>org.glassfish.expressly</groupId>
+ <artifactId>expressly</artifactId>
<scope>test</scope>
</dependency>
<dependency>
@@ -371,6 +383,12 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+
</dependencies>
<profiles>
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
index 7486f72..2c4ba83 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/BeanValidationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -72,7 +72,7 @@
mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
mavenBundle().groupId("jakarta.el").artifactId("jakarta.el-api").versionAsInProject(),
- mavenBundle().groupId("org.glassfish").artifactId("jakarta.el").versionAsInProject()
+ mavenBundle().groupId("org.glassfish.expressly").artifactId("expressly").versionAsInProject()
));
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
index 7aebd55..785e883 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonJacksonTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -51,6 +51,7 @@
mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-core").versionAsInProject(),
mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-databind").versionAsInProject(),
mavenBundle().groupId("com.fasterxml.jackson.core").artifactId("jackson-annotations").versionAsInProject(),
+
mavenBundle().groupId("com.fasterxml.jackson.module").artifactId("jackson-module-jakarta-xmlbind-annotations")
.versionAsInProject()
));
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
index 4b2876b..2ca286c 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/JsonMoxyTest.java
@@ -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
@@ -56,14 +56,14 @@
mavenBundle().groupId("org.glassfish.jersey.ext").artifactId("jersey-entity-filtering").versionAsInProject(),
mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.moxy").versionAsInProject(),
mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.core").versionAsInProject(),
- mavenBundle().groupId("org.ow2.asm").artifactId("asm").versionAsInProject(),
- mavenBundle().groupId("jakarta.json").artifactId("jakarta.json-api").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.persistence").artifactId("org.eclipse.persistence.asm").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.parsson").artifactId("parsson").versionAsInProject(),
// validation
mavenBundle().groupId("org.hibernate.validator").artifactId("hibernate-validator").versionAsInProject(),
mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject(),
mavenBundle().groupId("com.fasterxml").artifactId("classmate").versionAsInProject(),
- mavenBundle().groupId("org.glassfish").artifactId("jakarta.el").versionAsInProject()
+ mavenBundle().groupId("org.glassfish.expressly").artifactId("expressly").versionAsInProject()
));
return Helper.asArray(options);
diff --git a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java
index c3a2fca..369c2b1 100644
--- a/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.java
+++ b/tests/osgi/functional/src/test/java/org/glassfish/jersey/osgi/test/basic/PackageScanningTest.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
@@ -79,7 +79,8 @@
.versionAsInProject(),
// MBR/MBW for JSON-P is on the classpath.
- mavenBundle().groupId("jakarta.json").artifactId("jakarta.json-api").versionAsInProject()
+ mavenBundle().groupId("jakarta.json").artifactId("jakarta.json-api").versionAsInProject(),
+ mavenBundle().groupId("org.eclipse.parsson").artifactId("parsson").versionAsInProject()
));
options = Helper.addPaxExamMavenLocalRepositoryProperty(options);
diff --git a/tests/osgi/pom.xml b/tests/osgi/pom.xml
index d397626..7744326 100644
--- a/tests/osgi/pom.xml
+++ b/tests/osgi/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/benchmarks/pom.xml b/tests/performance/benchmarks/pom.xml
index 2d92174..388b742 100644
--- a/tests/performance/benchmarks/pom.xml
+++ b/tests/performance/benchmarks/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
index 05391bc..ba18aae 100644
--- a/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
+++ b/tests/performance/jmx-client/src/main/java/org/glassfish/jersey/tests/performance/jmxclient/Main.java
@@ -80,6 +80,6 @@
private static void writeResult(double resultValue, String propertiesFile) throws IOException {
Properties resultProps = new Properties();
resultProps.put("YVALUE", Double.toString(resultValue));
- resultProps.store(Files.newOutputStream(Paths.get(propertiesFile)), null);
+ resultProps.store(Files.newOutputStream(Path.of(propertiesFile)), null);
}
}
diff --git a/tests/performance/pom.xml b/tests/performance/pom.xml
index 48af219..a311af9 100644
--- a/tests/performance/pom.xml
+++ b/tests/performance/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/runners/jersey-grizzly-runner/pom.xml b/tests/performance/runners/jersey-grizzly-runner/pom.xml
index eda85ad..25c54e1 100644
--- a/tests/performance/runners/jersey-grizzly-runner/pom.xml
+++ b/tests/performance/runners/jersey-grizzly-runner/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -49,7 +49,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
+ <version>${jar.mvn.plugin.version}</version>
<configuration>
<archive>
<index>true</index>
diff --git a/tests/performance/runners/pom.xml b/tests/performance/runners/pom.xml
index 04cce19..56b1568 100644
--- a/tests/performance/runners/pom.xml
+++ b/tests/performance/runners/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/assemblies/pom.xml b/tests/performance/test-cases/assemblies/pom.xml
index a3d0212..f4c7f2b 100644
--- a/tests/performance/test-cases/assemblies/pom.xml
+++ b/tests/performance/test-cases/assemblies/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/filter-dynamic/pom.xml b/tests/performance/test-cases/filter-dynamic/pom.xml
index f60005d..563d7fc 100644
--- a/tests/performance/test-cases/filter-dynamic/pom.xml
+++ b/tests/performance/test-cases/filter-dynamic/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/filter-global/pom.xml b/tests/performance/test-cases/filter-global/pom.xml
index 5374209..31d816f 100644
--- a/tests/performance/test-cases/filter-global/pom.xml
+++ b/tests/performance/test-cases/filter-global/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/filter-name/pom.xml b/tests/performance/test-cases/filter-name/pom.xml
index 0c89bf9..560caea 100644
--- a/tests/performance/test-cases/filter-name/pom.xml
+++ b/tests/performance/test-cases/filter-name/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/interceptor-dynamic/pom.xml b/tests/performance/test-cases/interceptor-dynamic/pom.xml
index 694ddf7..7b1a3f2 100644
--- a/tests/performance/test-cases/interceptor-dynamic/pom.xml
+++ b/tests/performance/test-cases/interceptor-dynamic/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/interceptor-global/pom.xml b/tests/performance/test-cases/interceptor-global/pom.xml
index 1180920..289be67 100644
--- a/tests/performance/test-cases/interceptor-global/pom.xml
+++ b/tests/performance/test-cases/interceptor-global/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/interceptor-name/pom.xml b/tests/performance/test-cases/interceptor-name/pom.xml
index c558662..9f41ad2 100644
--- a/tests/performance/test-cases/interceptor-name/pom.xml
+++ b/tests/performance/test-cases/interceptor-name/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-custom-provider/pom.xml b/tests/performance/test-cases/mbw-custom-provider/pom.xml
index b8b5106..055d1a0 100644
--- a/tests/performance/test-cases/mbw-custom-provider/pom.xml
+++ b/tests/performance/test-cases/mbw-custom-provider/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-json-jackson/pom.xml b/tests/performance/test-cases/mbw-json-jackson/pom.xml
index 29200a0..d8b838a 100644
--- a/tests/performance/test-cases/mbw-json-jackson/pom.xml
+++ b/tests/performance/test-cases/mbw-json-jackson/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-json-moxy/pom.xml b/tests/performance/test-cases/mbw-json-moxy/pom.xml
index 165884a..5ee1a77 100644
--- a/tests/performance/test-cases/mbw-json-moxy/pom.xml
+++ b/tests/performance/test-cases/mbw-json-moxy/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-kryo/pom.xml b/tests/performance/test-cases/mbw-kryo/pom.xml
index d2a9146..5e05ad9 100644
--- a/tests/performance/test-cases/mbw-kryo/pom.xml
+++ b/tests/performance/test-cases/mbw-kryo/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-text-plain/pom.xml b/tests/performance/test-cases/mbw-text-plain/pom.xml
index 7a21d4f..c83cd73 100644
--- a/tests/performance/test-cases/mbw-text-plain/pom.xml
+++ b/tests/performance/test-cases/mbw-text-plain/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-xml-jaxb/pom.xml b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
index 89936f7..128f398 100644
--- a/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
+++ b/tests/performance/test-cases/mbw-xml-jaxb/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/mbw-xml-moxy/pom.xml b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
index 255ebe6..d19a4d2 100644
--- a/tests/performance/test-cases/mbw-xml-moxy/pom.xml
+++ b/tests/performance/test-cases/mbw-xml-moxy/pom.xml
@@ -1,6 +1,6 @@
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/monitoring/pom.xml b/tests/performance/test-cases/monitoring/pom.xml
index c4076c2..d5b84bd 100644
--- a/tests/performance/test-cases/monitoring/pom.xml
+++ b/tests/performance/test-cases/monitoring/pom.xml
@@ -37,13 +37,13 @@
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-core</artifactId>
- <version>2.1.2</version>
+ <version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
- <version>5.9.1</version>
+ <version>5.10.2</version>
<scope>test</scope>
</dependency>
@@ -56,13 +56,13 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.5</version>
+ <version>1.17.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
- <version>1.6.1</version>
+ <version>2.0.13</version>
</dependency>
<dependency>
@@ -97,11 +97,11 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
+ <version>3.13.0</version>
<inherited>true</inherited>
<configuration>
- <source>1.7</source>
- <target>1.7</target>
+ <source>1.8</source>
+ <target>1.8</target>
<showWarnings>false</showWarnings>
<fork>false</fork>
</configuration>
diff --git a/tests/performance/test-cases/param-srl/pom.xml b/tests/performance/test-cases/param-srl/pom.xml
index ca6afbf..2eec4c2 100644
--- a/tests/performance/test-cases/param-srl/pom.xml
+++ b/tests/performance/test-cases/param-srl/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/pom.xml b/tests/performance/test-cases/pom.xml
index 5430a1c..cc32b89 100644
--- a/tests/performance/test-cases/pom.xml
+++ b/tests/performance/test-cases/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/test-cases/proxy-injection/pom.xml b/tests/performance/test-cases/proxy-injection/pom.xml
index 6684683..d1032b9 100644
--- a/tests/performance/test-cases/proxy-injection/pom.xml
+++ b/tests/performance/test-cases/proxy-injection/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/performance/tools/pom.xml b/tests/performance/tools/pom.xml
index fe8ea97..6dc03a4 100644
--- a/tests/performance/tools/pom.xml
+++ b/tests/performance/tools/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2014, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/pom.xml b/tests/pom.xml
index 7445824..f38d9bd 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -42,11 +42,11 @@
<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>
<module>integration</module>
- <module>jmockit</module>
<module>mem-leaks</module>
<module>osgi</module>
<module>stress</module>
@@ -132,5 +132,14 @@
<module>version-agnostic</module>
</modules>
</profile>
+ <profile>
+ <id>JMOCKIT-MODULE-FOR-PRE-JDK24</id>
+ <activation>
+ <jdk>[11,24)</jdk>
+ </activation>
+ <modules>
+ <module>jmockit</module>
+ </modules>
+ </profile>
</profiles>
</project>
diff --git a/tests/release-test/pom.xml b/tests/release-test/pom.xml
index d705728..deb69f8 100644
--- a/tests/release-test/pom.xml
+++ b/tests/release-test/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -47,7 +47,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>3.0.0-M7</version>
+ <version>${surefire.mvn.plugin.version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
@@ -117,7 +117,7 @@
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
- <version>3.3.0</version>
+ <version>${harness.testing.mvn.plugin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -156,7 +156,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>3.0.0-M7</version>
+ <version>${surefire.mvn.plugin.version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java
index 743d609..8a97941 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.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
@@ -27,7 +27,14 @@
class ClassVersionChecker {
static TestResult checkClassVersion(JarFile jar, JarEntry entry, Properties properties) throws IOException {
final String jerseyVersion = MavenUtil.getJerseyVersion(properties);
- final int minVersion = jerseyVersion.startsWith("3.1") ? 11 : 8;
+ final int minVersion;
+ if (jerseyVersion.startsWith("4")) {
+ minVersion = 17;
+ } else if (jerseyVersion.startsWith("3.1")) {
+ minVersion = 11;
+ } else {
+ minVersion = 8;
+ }
return checkClassVersion(jar.getInputStream(entry), jar.getName() + File.separator + entry.getName(), minVersion);
}
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java
index b1a7ee3..eeea982 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.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
@@ -42,4 +42,28 @@
request.setRepositories(remoteRepos);
return repoSystem.resolveArtifact(repoSession, request).getArtifact();
}
+
+ static Artifact resolveSource(org.apache.maven.model.Dependency d, List<RemoteRepository> remoteRepos,
+ RepositorySystem repoSystem, RepositorySystemSession repoSession)
+ throws ArtifactResolutionException {
+ DefaultArtifact artifact = new DefaultArtifact(
+ d.getGroupId(), d.getArtifactId(), "sources", d.getType(), d.getVersion()
+ );
+ ArtifactRequest request = new ArtifactRequest();
+ request.setArtifact(artifact);
+ request.setRepositories(remoteRepos);
+ return repoSystem.resolveArtifact(repoSession, request).getArtifact();
+ }
+
+ static Artifact resolveJavadoc(org.apache.maven.model.Dependency d, List<RemoteRepository> remoteRepos,
+ RepositorySystem repoSystem, RepositorySystemSession repoSession)
+ throws ArtifactResolutionException {
+ DefaultArtifact artifact = new DefaultArtifact(
+ d.getGroupId(), d.getArtifactId(), "javadoc", d.getType(), d.getVersion()
+ );
+ ArtifactRequest request = new ArtifactRequest();
+ request.setArtifact(artifact);
+ request.setRepositories(remoteRepos);
+ return repoSystem.resolveArtifact(repoSession, request).getArtifact();
+ }
}
\ No newline at end of file
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java
index 20e7737..98d4616 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.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
@@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Properties;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class MavenUtil {
@@ -37,7 +38,7 @@
private static final String PROJECT_VERSION = "project.version";
static File getArtifactJar(File repositoryRoot, Dependency dependency, Properties properties) {
- return getArtifactFile(repositoryRoot, dependency, properties, "jar");
+ return getArtifactFile(repositoryRoot, dependency, properties, dependency.getType());
}
private static File getArtifactFile(File repositoryRoot, Dependency dependency, Properties properties, String extension) {
@@ -52,7 +53,11 @@
}
String version = MavenUtil.getDependencyVersion(dependency, properties);
fileSuffix.append(version).append(File.separator);
- fileSuffix.append(dependency.getArtifactId()).append('-').append(version).append(".").append(extension);
+ fileSuffix.append(dependency.getArtifactId()).append('-').append(version);
+ if (dependency.getClassifier() != null) {
+ fileSuffix.append('-').append(dependency.getClassifier());
+ }
+ fileSuffix.append(".").append(extension);
return new File(repositoryRoot, fileSuffix.toString());
}
@@ -103,7 +108,16 @@
static Stream<Dependency> streamJerseyJars() throws IOException, XmlPullParserException {
Model model = getModelFromFile("pom.xml");
List<Dependency> deps = getBomPomDependencies(model);
+ return streamJerseyJars(deps);
+ }
+ static Stream<Dependency> streamJerseySources() throws IOException, XmlPullParserException {
+ Model model = getModelFromFile("pom.xml");
+ List<Dependency> deps = getBomPomSources(model);
+ return streamJerseyJars(deps);
+ }
+
+ private static Stream<Dependency> streamJerseyJars(List<Dependency> deps) throws IOException, XmlPullParserException {
return deps.stream()
.filter(dep -> dep.getGroupId().startsWith("org.glassfish.jersey"))
.filter(dep -> dep.getType().equals("jar"));
@@ -139,6 +153,15 @@
return bomPomModel.getDependencyManagement().getDependencies();
}
+ private static List<Dependency> getBomPomSources(Model model) throws XmlPullParserException, IOException {
+ return getBomPomDependencies(model).stream()
+ .map(dependency -> {
+ dependency.setClassifier("sources");
+ return dependency;
+ })
+ .collect(Collectors.toList());
+ }
+
static String getJerseyVersion(Properties properties) {
String property = properties.getProperty(JERSEY_VERSION); // when it is in the pom.file
if (property == null || property.startsWith("${")) {
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java
index b42830b..5be312c 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.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
@@ -52,16 +52,21 @@
continue;
}
// Update the names with the ones in Jersey
- Map.Entry<Object, Object> updatedEntry = updateEntry(pomEntry);
// Check the properties are there
- if (properties.getProperty(updatedEntry.getKey().toString()) == null) {
+ final String key = pomEntry.getKey().toString();
+
+ if (properties.getProperty(key) == null) {
testResult.ok().append("Property ")
.append(pomEntry.getKey().toString())
.append(" from ").append(pom).println(" not in Jersey");
failed = true;
}
// check the values
- else if (!properties.getProperty(updatedEntry.getKey().toString()).equals(updatedEntry.getValue())) {
+ else if (
+ //archetype property value can be a variable from the main pom.xml - check and exclude if so
+ !(properties.containsKey(key) && pomEntry.getValue().toString().contains(key))
+ && !properties.getProperty(key).equals(pomEntry.getValue())
+ ) {
testResult.exception().append("The property ")
.append(pomEntry.getKey().toString())
.append(" in archetype pom ")
@@ -81,25 +86,4 @@
}
}
- private Map.Entry<Object, Object> updateEntry(Map.Entry<Object, Object> pomEntry) {
- if (pomEntry.getKey().equals("junit-jupiter.version")) {
- return new Map.Entry<Object, Object>() {
- @Override
- public Object getKey() {
- return "junit5.version";
- }
-
- @Override
- public Object getValue() {
- return pomEntry.getValue();
- }
-
- @Override
- public Object setValue(Object value) {
- return value;
- }
- };
- }
- return pomEntry;
- }
}
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java
index 99c94ee..6a74f07 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.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
@@ -58,6 +58,12 @@
Artifact m = mavenEnvironment.resolveArtifact(member);
System.out.append("Resolved ").append(member.getGroupId()).append(":").append(member.getArtifactId()).append(":")
.append(member.getVersion()).append(" to ").println(m.getFile().getName());
+ m = mavenEnvironment.resolveSource(member);
+ System.out.append("Resolved sources ").append(member.getGroupId()).append(":").append(member.getArtifactId())
+ .append(":").append(member.getVersion()).append(" to ").println(m.getFile().getName());
+ m = mavenEnvironment.resolveJavadoc(member);
+ System.out.append("Resolved javadoc ").append(member.getGroupId()).append(":").append(member.getArtifactId())
+ .append(":").append(member.getVersion()).append(" to ").println(m.getFile().getName());
}
}
@@ -74,6 +80,14 @@
System.out.append("Resolved ").append(dependency.getGroupId()).append(":")
.append(dependency.getArtifactId()).append(":")
.append(dependency.getVersion()).append(" to ").println(m.getFile().getName());
+ m = mavenEnvironment.resolveSource(dependency);
+ System.out.append("Resolved source ").append(dependency.getGroupId()).append(":")
+ .append(dependency.getArtifactId()).append(":")
+ .append(dependency.getVersion()).append(" to ").println(m.getFile().getName());
+ m = mavenEnvironment.resolveJavadoc(dependency);
+ System.out.append("Resolved javadoc ").append(dependency.getGroupId()).append(":")
+ .append(dependency.getArtifactId()).append(":")
+ .append(dependency.getVersion()).append(" to ").println(m.getFile().getName());
}
}
@@ -102,6 +116,16 @@
return DependencyResolver.resolveArtifact(dependency, remoteRepos, repositorySystem, repoSession);
}
+ Artifact resolveSource(Dependency dependency) throws ArtifactResolutionException {
+ dependency.setVersion(jerseyVersion);
+ return DependencyResolver.resolveSource(dependency, remoteRepos, repositorySystem, repoSession);
+ }
+
+ Artifact resolveJavadoc(Dependency dependency) throws ArtifactResolutionException {
+ dependency.setVersion(jerseyVersion);
+ return DependencyResolver.resolveJavadoc(dependency, remoteRepos, repositorySystem, repoSession);
+ }
+
private List<RemoteRepository> getRemoteRepositories() throws Exception {
MavenProject project = getMavenProjectForResourceFile("/release-test-pom.xml");
List<RemoteRepository> remoteArtifactRepositories = project.getRemoteProjectRepositories();
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java
index 74e0281..8c784af 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.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
@@ -41,7 +41,15 @@
List<File> jars = MavenUtil.streamJerseyJars()
.map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties))
.collect(Collectors.toList());
+ testLegalFiles(jars, testResult);
+ jars = MavenUtil.streamJerseySources()
+ .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties))
+ .collect(Collectors.toList());
+ testLegalFiles(jars, testResult);
+ }
+
+ private void testLegalFiles(List<File> jars, TestResult testResult) throws IOException {
for (File jar : jars) {
for (String filename : new String[]{LICENSE_FILE, NOTICE_FILE}) {
JarFile jarFile = new JarFile(jar);
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java
index 0c77d69..a520868 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.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
@@ -25,6 +25,7 @@
import java.util.Properties;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
public class ManifestTest {
private static final File localRepository = MavenUtil.getLocalMavenRepository();
@@ -63,6 +64,25 @@
}
}
+ for (File jar : jars) {
+ JarFile jarFile = new JarFile(jar);
+ String value = jarFile.getManifest().getMainAttributes().getValue("Multi-Release");
+// System.out.append("Accessing META-INF/versions").append(" of ").println(jar.getName());
+ ZipEntry versions = jarFile.getEntry("META-INF/versions/");
+ if (versions != null) {
+ if (!"true".equals(value)) {
+ testResult.exception().append("'Multi-Release: true' not set for ").println(jar.getName());
+ } else {
+ testResult.ok().append("'Multi-Release: true' set for ").println(jar.getName());
+ }
+ } else {
+ if ("true".equals(value)) {
+ testResult.exception().append("'Multi-Release: true' SET for ").println(jar.getName());
+ }
+ }
+
+ }
+
//Assertions.assertTrue(testResult.result(), "Some error occurred, see previous messages");
Assert.assertTrue("Some error occurred, see previous messages", testResult.result());
}
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
index 08be020..11a417e 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
@@ -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
@@ -40,12 +40,14 @@
private static final DependencyPair[] jdk11multiRelease = jdk11multiRelease(properties);
private static final DependencyPair[] jdk12multiRelease = jdk12multiRelease(properties);
private static final DependencyPair[] jdk17multiRelease = jdk17multiRelease(properties);
+ private static final DependencyPair[] jdk21multiRelease = jdk21multiRelease(properties);
@Test
public void testIsJdkMultiRelease() throws IOException, XmlPullParserException {
TestResult result = testJdkVersions("11", jdk11multiRelease);
result.append(testJdkVersions("12", jdk12multiRelease));
result.append(testJdkVersions("17", jdk17multiRelease));
+ result.append(testJdkVersions("21", jdk21multiRelease));
//Assertions.assertTrue(result.result(), "Some error occurred, see previous messages");
Assert.assertTrue("Some error occurred, see previous messages", result.result());
}
@@ -54,6 +56,7 @@
throws XmlPullParserException, IOException {
final TestResult result = new TestResult();
if (dependencies == null || dependencies.length == 0) {
+ System.out.append("No dependencies found for jdk ").println(version);
return result;
}
@@ -81,6 +84,7 @@
result.exception().append("Not a multirelease jar ").append(jar.getName()).println("!");
}
ZipEntry versions = jarFile.getEntry("META-INF/versions/" + version);
+ System.out.append("Accessing META-INF/versions/").append(version).append(" of ").println(jar.getName());
if (versions == null) {
result.exception().append("No classes for JDK ").append(version).append(" for ").println(jar.getName());
}
@@ -95,6 +99,26 @@
result.append(ClassVersionChecker.checkClassVersion(jarFile, jarEntry, properties));
}
+ // Verify that number of multirelease jars matches the expected dependencies
+ StringBuilder multi = new StringBuilder();
+ int multiCnt = 0;
+ List<File> allFiles = MavenUtil.streamJerseyJars()
+ .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties))
+ .collect(Collectors.toList());
+ for (File jar : files) {
+ JarFile jarFile = new JarFile(jar);
+ if (jarFile.isMultiRelease()) {
+ multiCnt++;
+ multi.append("Multirelease jar ").append(jar.getName()).append('\n');
+ }
+ }
+ if (files.size() == multiCnt) {
+ result.ok().println("There is expected number of multirelease jars");
+ } else {
+ result.exception().println("There is unexpected number of multirelease jars:");
+ result.exception().append(multi).println("");
+ }
+
return result;
}
@@ -136,14 +160,40 @@
private static DependencyPair[] jdk17multiRelease(Properties properties) {
String jerseyVersion = MavenUtil.getJerseyVersion(properties);
- if (jerseyVersion.startsWith("3")) {
+ if (jerseyVersion.startsWith("3.0")) {
return new DependencyPair[] {
new DependencyPair("org.glassfish.jersey.connectors", "jersey-helidon-connector"),
new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-connector"),
new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http"),
new DependencyPair("org.glassfish.jersey.ext", "jersey-spring6")
};
+ } else if (jerseyVersion.startsWith("3")) {
+ return new DependencyPair[] {
+ new DependencyPair("org.glassfish.jersey.connectors", "jersey-helidon-connector"),
+ new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-connector"),
+ new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-http2-connector"),
+ new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http"),
+ new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http2"),
+ new DependencyPair("org.glassfish.jersey.test-framework.providers", "jersey-test-framework-provider-jetty"),
+ new DependencyPair("org.glassfish.jersey.test-framework.providers",
+ "jersey-test-framework-provider-jetty-http2"),
+ new DependencyPair("org.glassfish.jersey.ext", "jersey-spring6")
+ };
}
return new DependencyPair[]{};
}
+
+ private static DependencyPair[] jdk21multiRelease(Properties properties) {
+ String jerseyVersion = MavenUtil.getJerseyVersion(properties);
+ if (jerseyVersion.startsWith("4")) {
+ return new DependencyPair[]{
+ new DependencyPair("org.glassfish.jersey.core", "jersey-common")
+ };
+ } else {
+ return new DependencyPair[]{
+ new DependencyPair("org.glassfish.jersey.bundles", "jaxrs-ri"),
+ new DependencyPair("org.glassfish.jersey.core", "jersey-common")
+ };
+ }
+ }
}
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/tests/stress/pom.xml b/tests/stress/pom.xml
index 7d12649..31b1ddb 100644
--- a/tests/stress/pom.xml
+++ b/tests/stress/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/tests/version-agnostic/pom.xml b/tests/version-agnostic/pom.xml
index aad0411..552ac47 100644
--- a/tests/version-agnostic/pom.xml
+++ b/tests/version-agnostic/pom.xml
@@ -38,7 +38,7 @@
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<hk2.version>3.0.3</hk2.version>
- <jersey.version>3.5.99-SNAPSHOT</jersey.version>
+ <jersey.version>3.1.6</jersey.version>
</properties>
<build>
diff --git a/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java b/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java
index e720080..4eddfe4 100644
--- a/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java
+++ b/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.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
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 e1f8091..1522089 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>
@@ -67,19 +67,19 @@
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
- <version>3.3.0</version>
+ <version>${harness.testing.mvn.plugin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.11.0</version>
+ <version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
- <version>3.8.1</version>
+ <version>${maven.version}</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java b/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
index eec3df2..1ddf887 100644
--- a/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
+++ b/tools/jersey-release-notes-maven-plugin/src/main/java/org/glassfish/jersey/tools/plugins/releasenotes/ReleaseNotesMojo.java
@@ -33,7 +33,7 @@
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -172,12 +172,12 @@
String releaseVersion, String releaseDate,
String releaseNotesFilePath,
Boolean dryRun, Log log) throws IOException {
- if (Files.notExists(Paths.get(templateFilePath))) {
+ if (Files.notExists(Path.of(templateFilePath))) {
log.warn(String.format("There is no source template file at the given location:%s", templateFilePath));
return;
}
final List<String> notesLines = new ArrayList<>();
- final List<String> lines = Files.readAllLines(Paths.get(templateFilePath), Charset.defaultCharset());
+ final List<String> lines = Files.readAllLines(Path.of(templateFilePath), Charset.defaultCharset());
for (final String line : lines) {
if (line.contains(RELEASE_DATE_PATTERN)) {
notesLines.add(line.replace(RELEASE_DATE_PATTERN, releaseDate));
@@ -197,8 +197,8 @@
}
if (Boolean.FALSE.equals(dryRun)) {
log.info(String.format("Storing release notes to file %s/%s.html", releaseNotesFilePath, releaseVersion));
- Files.createDirectories(Paths.get(releaseNotesFilePath));
- Files.write(Paths.get(String.format("%s/%s.html", releaseNotesFilePath, releaseVersion)), notesLines, Charset.defaultCharset());
+ Files.createDirectories(Path.of(releaseNotesFilePath));
+ Files.write(Path.of(String.format("%s/%s.html", releaseNotesFilePath, releaseVersion)), notesLines, Charset.defaultCharset());
} else {
log.info("Prepared release notes are not stored to file due to dryRun mode");
log.info(String.format("File path to store release notes is: %s/%s.html", releaseNotesFilePath, releaseVersion));