diff --git a/pom.xml b/pom.xml
index d1acba3fc8..8dea2c6d55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2195,7 +2195,7 @@
1.19.3
${jersey1.version}
1.3.7
- 1.10.2
+ 1.35
1.44
5.6.0
4.0.2
diff --git a/tests/performance/benchmarks/pom.xml b/tests/performance/benchmarks/pom.xml
index 07cbc44237..1c7567964d 100644
--- a/tests/performance/benchmarks/pom.xml
+++ b/tests/performance/benchmarks/pom.xml
@@ -46,6 +46,14 @@
org.glassfish.jersey.media
jersey-media-json-jackson
+
+ org.glassfish.jersey.media
+ jersey-media-jaxb
+
+
+ com.sun.xml.bind
+ jaxb-osgi
+
org.glassfish.jersey.ext
jersey-entity-filtering
@@ -58,6 +66,10 @@
org.glassfish.jersey.connectors
jersey-grizzly-connector
+
+ org.glassfish.jersey.connectors
+ jersey-jnh-connector
+
jakarta.annotation
jakarta.annotation-api
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JNHConnectorBenchmark.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JNHConnectorBenchmark.java
new file mode 100644
index 0000000000..42e212f10b
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/JNHConnectorBenchmark.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.StreamingOutput;
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
+import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.jackson.JacksonFeature;
+import org.glassfish.jersey.jnh.connector.JavaNetHttpConnectorProvider;
+import org.glassfish.jersey.tests.performance.benchmark.server.jnh.Book;
+import org.glassfish.jersey.tests.performance.benchmark.server.jnh.BookShelfApplication;
+import org.glassfish.jersey.tests.performance.benchmark.server.jnh.BookShelfResource;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * jersey-jnh-connector {@link org.glassfish.jersey.jnh.connector.JavaNetHttpConnector} benchmark.
+ *
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 1, time = 1)
+@Measurement(iterations = 16, time = 1)
+@Fork(1)
+@State(Scope.Benchmark)
+public class JNHConnectorBenchmark {
+
+ private static final URI BASE_URI = URI.create("http://localhost:8080/");
+
+ private static final String REQUEST_TARGET = "HttpMethod";
+ private volatile HttpServer server;
+
+ private volatile Client client;
+ private volatile Client defaultClient;
+
+ private final Book postBook = new Book("The Bonfire of the Vanities", "Tom Wolfe", 11);
+ private final Book postDefaultBook = new Book("More Die of Heartbreak", "Saul Bellow", 22);
+ private final Book putBook = new Book("Silmarillion", "J. R. R. Tolkien", 110);
+ private final Book putDefaultBook = new Book("The Lord of the Rings", "John Tolkien", 220);
+
+ @Setup
+ public void start() throws Exception {
+ server =
+ GrizzlyHttpServerFactory.createHttpServer(BASE_URI, new BookShelfApplication(), false);
+ final TCPNIOTransport transport = server.getListener("grizzly").getTransport();
+ transport.setSelectorRunnersCount(4);
+ transport.setWorkerThreadPoolConfig(ThreadPoolConfig.defaultConfig().setCorePoolSize(8).setMaxPoolSize(8));
+
+ server.start();
+ client = ClientBuilder.newClient(
+ new ClientConfig()
+ .connectorProvider(new JavaNetHttpConnectorProvider())
+ .register(JacksonFeature.class)
+ );
+ defaultClient = ClientBuilder.newClient(
+ new ClientConfig()
+ .register(JacksonFeature.class)
+ );
+
+ }
+
+ @Setup(Level.Iteration)
+ public void request() {
+ }
+
+ @TearDown
+ public void shutdown() {
+ server.shutdownNow();
+ }
+
+ @Benchmark
+ public void measureGetStringResource() {
+ client.target(BASE_URI).path(REQUEST_TARGET).request(MediaType.TEXT_PLAIN).get(String.class);
+ }
+
+ @Benchmark
+ public void measureGetStringDefaultResource() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).request(MediaType.TEXT_PLAIN).get(String.class);
+ }
+
+ @Benchmark
+ public void measureEntityGetResource() {
+ client.target(BASE_URI).path(REQUEST_TARGET).path("books")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+ }
+ @Benchmark
+ public void measureEntityGetXmlResource() throws IOException {
+ final InputStream stream = client.target(BASE_URI).path(REQUEST_TARGET).path("books")
+ .request(MediaType.APPLICATION_XML_TYPE).get(InputStream.class);
+ try {
+ System.out.print(new String(stream.readAllBytes()).charAt(0));
+ } finally {
+ stream.close();
+ }
+ }
+
+ @Benchmark
+ public void measureEntityGetOneXmlResource() throws IOException {
+ final Book book = client.target(BASE_URI).path(REQUEST_TARGET).path("book")
+ .request(MediaType.APPLICATION_XML_TYPE).get(Book.class);
+ System.out.print(book.getId());
+ }
+ @Benchmark
+ public void measureEntityGetDefaultResource() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("books")
+ .request(MediaType.APPLICATION_JSON_TYPE).get();
+ }
+
+ @Benchmark
+ public void measureEntityGetXmlDefaultResource() throws IOException {
+ final InputStream stream = defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("books")
+ .request(MediaType.APPLICATION_XML_TYPE).get(InputStream.class);
+ try {
+ System.out.print(new String(stream.readAllBytes()).charAt(0));
+ } finally {
+ stream.close();
+ }
+ }
+ @Benchmark
+ public void measureEntityGetOneXmlDefaultResource() {
+ final Book book = defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("book")
+ .request(MediaType.APPLICATION_XML_TYPE).get(Book.class);
+ System.out.print(book.getId());
+ }
+
+ @Benchmark
+ public void measurePost() {
+ client.target(BASE_URI).path(REQUEST_TARGET).path("postBook")
+ .request().post(Entity.json(postBook));
+ }
+
+ @Benchmark
+ public void measurePostDefault() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("postBook")
+ .request().post(Entity.json(postDefaultBook));
+ }
+
+ @Benchmark
+ public void measureBigPost() {
+ client.target(BASE_URI).path(REQUEST_TARGET).path("postBooks")
+ .request().post(Entity.entity(convertLongEntity(BookShelfResource.bookList), MediaType.TEXT_PLAIN_TYPE));
+ }
+
+ @Benchmark
+ public void measureBigPostDefault() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("postBooks")
+ .request().post(Entity.entity(convertLongEntity(BookShelfResource.bookList), MediaType.TEXT_PLAIN_TYPE));
+ }
+
+ private static final StreamingOutput convertLongEntity(List books) {
+ return out -> {
+ int offset = 0;
+ while (offset < books.size()) {
+ out.write(books.get(offset).toByteArray());
+ out.write('\n');
+ offset++;
+ }
+ };
+ }
+
+
+ @Benchmark
+ public void measurePut() {
+ client.target(BASE_URI).path(REQUEST_TARGET).path("putBook")
+ .request().put(Entity.json(putBook));
+ }
+
+ @Benchmark
+ public void measurePutDefault() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("putBook")
+ .request().put(Entity.json(putDefaultBook));
+ }
+
+ @Benchmark
+ public void measureDelete() {
+ client.target(BASE_URI).path(REQUEST_TARGET).path("deleteBook")
+ .request().delete();
+ }
+
+ @Benchmark
+ public void measureDeleteDefault() {
+ defaultClient.target(BASE_URI).path(REQUEST_TARGET).path("deleteBook")
+ .request().delete();
+ }
+
+
+ public static void main(final String[] args) throws Exception {
+ final Options opt = new OptionsBuilder()
+ // Register our benchmarks.
+ .include(JNHConnectorBenchmark.class.getSimpleName())
+ .build();
+
+ new Runner(opt).run();
+ }
+}
\ No newline at end of file
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/Book.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/Book.java
new file mode 100644
index 0000000000..93e1d39de6
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/Book.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server.jnh;
+
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Book {
+
+ private String title;
+ private String author;
+ private int id;
+
+
+ public Book(String title, String author, int id) {
+ this.title = title;
+ this.author = author;
+ this.id = id;
+ }
+
+ public Book() {
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public byte[] toByteArray() {
+ return String.format("%s, %s, %d", title, author, id).getBytes();
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfApplication.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfApplication.java
new file mode 100644
index 0000000000..d5569d0460
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfApplication.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server.jnh;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+public class BookShelfApplication extends ResourceConfig {
+ public BookShelfApplication() {
+ register(BookShelfResource.class);
+ }
+}
diff --git a/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfResource.java b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfResource.java
new file mode 100644
index 0000000000..03f6c4402d
--- /dev/null
+++ b/tests/performance/benchmarks/src/main/java/org/glassfish/jersey/tests/performance/benchmark/server/jnh/BookShelfResource.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.performance.benchmark.server.jnh;
+
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.glassfish.grizzly.http.util.HttpStatus;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Path("HttpMethod")
+public class BookShelfResource {
+
+ private static final int BOOK_LIST_SIZE = 1000;
+
+ public static final List bookList = generateBooks();
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getStatus() {
+ return HttpStatus.OK_200.getReasonPhrase();
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ @Path("books")
+ public List getBooks() {
+ return bookList;
+ }
+
+ @GET
+ @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
+ @Path("book")
+ public Book getBook() {
+ return new Book("1", "2", 3);
+ }
+
+ @POST
+ @Path("postBook")
+ public void postBook(Book book) {
+ /*System.out.println(String.format("Just got a book by: %s, which is called: %s, giving it an id: %d",
+ book.getAuthor(),
+ book.getTitle(),
+ book.getId()));*/
+ }
+ @POST
+ @Path("postBooks")
+ public Response postBooks(InputStream data) throws IOException {
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(data));
+ long linesReceived = reader.lines().count();
+ reader.close();
+ return linesReceived == bookList.size() ? Response.ok().build() : Response.serverError().build();
+ }
+
+ @PUT
+ @Path("putBook")
+ public void putBook(Book book) {
+ /*System.out.println(String.format("A book by: %s, with name: %s, is putted back under the id: %d",
+ book.getAuthor(),
+ book.getTitle(),
+ book.getId()));*/
+ }
+
+ @DELETE
+ @Path("deleteBook")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String deleteBook() {
+ return "HttpStatus.OK_200";
+
+ }
+
+ private static final List generateBooks() {
+ final List books = new ArrayList<>();
+ for (int i = 0; i < BOOK_LIST_SIZE; i++) {
+ books.add(new Book("Title: " + i, "Author: " + i, i));
+ }
+ return Collections.unmodifiableList(books);
+ }
+}