From 509ede1d8587372dbbd8acf9ee4a2145269bd6c4 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Wed, 21 Feb 2024 22:00:07 +0100 Subject: [PATCH] Add jersey test module (#11423) Add jersey test module Signed-off-by: Ludovic Orban Signed-off-by: Simone Bordet Co-authored-by: Simone Bordet --- .../jetty/server/internal/HttpConnection.java | 3 +- .../jetty-ee10-test-jersey/pom.xml | 65 +++++++ .../ee10/jersey/tests/EmbeddedJerseyTest.java | 160 ++++++++++++++++++ .../ee10/jersey/tests/endpoints/Resource.java | 46 +++++ .../ee10/jersey/tests/endpoints/Security.java | 56 ++++++ .../test/resources/jetty-logging.properties | 2 + jetty-ee10/jetty-ee10-tests/pom.xml | 1 + jetty-ee10/pom.xml | 16 ++ 8 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/pom.xml create mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/EmbeddedJerseyTest.java create mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Resource.java create mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Security.java create mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/resources/jetty-logging.properties diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java index ac189270bd6..0a3dafedf50 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java @@ -1505,7 +1505,8 @@ public class HttpConnection extends AbstractMetaDataConnection implements Runnab // If we are fill interested, then a read is pending and we must abort if (isFillInterested()) { - LOG.warn("Read pending {} {}", this, getEndPoint()); + if (LOG.isDebugEnabled()) + LOG.debug("abort due to pending read {} {} ", this, getEndPoint()); abort(new IOException("Pending read in onCompleted")); return; } diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/pom.xml b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/pom.xml new file mode 100644 index 00000000000..a256f6fa171 --- /dev/null +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/pom.xml @@ -0,0 +1,65 @@ + + + + 4.0.0 + + org.eclipse.jetty.ee10 + jetty-ee10-tests + 12.0.7-SNAPSHOT + + jetty-ee10-test-jersey + jar + EE10 :: Tests :: Jersey + + + ${project.groupId}.jersey.tests + + + + + org.eclipse.jetty.ee10 + jetty-ee10-webapp + + + org.eclipse.jetty.toolchain + jetty-test-helper + + + org.glassfish.jersey.containers + jersey-container-servlet + + + org.glassfish.jersey.inject + jersey-hk2 + + + org.glassfish.jersey.media + jersey-media-json-binding + + + org.slf4j + slf4j-api + + + jakarta.servlet + jakarta.servlet-api + provided + + + org.eclipse.jetty + jetty-client + test + + + org.eclipse.jetty + jetty-slf4j-impl + test + + + org.slf4j + jul-to-slf4j + test + + + + diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/EmbeddedJerseyTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/EmbeddedJerseyTest.java new file mode 100644 index 00000000000..5a60f4e44e3 --- /dev/null +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/EmbeddedJerseyTest.java @@ -0,0 +1,160 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd 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 +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.ee10.jersey.tests; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.client.AsyncRequestContent; +import org.eclipse.jetty.client.CompletableResponseListener; +import org.eclipse.jetty.client.ContentResponse; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.StringRequestContent; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class EmbeddedJerseyTest +{ + @BeforeAll + public static void beforeAll() + { + // Wire up java.util.logging to slf4j. + org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger(); + org.slf4j.bridge.SLF4JBridgeHandler.install(); + } + + @AfterAll + public static void afterAll() + { + org.slf4j.bridge.SLF4JBridgeHandler.uninstall(); + } + + private Server server; + private ServerConnector connector; + private HttpClient httpClient; + + private void start() throws Exception + { + startServer(); + startClient(); + } + + private void startServer() throws Exception + { + server = new Server(); + connector = new ServerConnector(server, 1, 1); + server.addConnector(connector); + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + server.setHandler(context); + + ServletHolder servletHolder = new ServletHolder(org.glassfish.jersey.servlet.ServletContainer.class); + servletHolder.setInitOrder(1); + servletHolder.setInitParameter("jersey.config.server.provider.packages", "org.eclipse.jetty.ee10.jersey.tests.endpoints"); + context.addServlet(servletHolder, "/webapi/*"); + + server.start(); + } + + private void startClient() throws Exception + { + httpClient = new HttpClient(); + httpClient.start(); + } + + @AfterEach + public void tearDown() + { + LifeCycle.stop(httpClient); + LifeCycle.stop(server); + } + + @Test + public void testPutJSON() throws Exception + { + start(); + + Request.Content content = new StringRequestContent(""" + { + "principal" : "foo", + "roles" : ["admin", "user"] + } + """ + ); + ContentResponse response = httpClient.newRequest("localhost", connector.getLocalPort()) + .method(HttpMethod.PUT) + .path("/webapi/resource/security/") + .headers(httpFields -> httpFields.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString())) + .body(content) + .timeout(5, TimeUnit.SECONDS) + .send(); + + assertThat(response.getStatus(), is(200)); + assertThat(response.getHeaders().get(HttpHeader.CONTENT_TYPE), is(MimeTypes.Type.APPLICATION_JSON.asString())); + assertThat(response.getContentAsString(), is(""" + { + "response" : "ok" + } + """) + ); + } + + @Test + public void testPutNoJSONThenTimeout() throws Exception + { + start(); + long idleTimeout = 1000; + connector.setIdleTimeout(idleTimeout); + + AsyncRequestContent content = new AsyncRequestContent(); + + CountDownLatch responseLatch = new CountDownLatch(1); + CompletableFuture completable = new CompletableResponseListener( + httpClient.newRequest("localhost", connector.getLocalPort()) + .method(HttpMethod.PUT) + .path("/webapi/resource/security/") + .timeout(3 * idleTimeout, TimeUnit.SECONDS) + .headers(httpFields -> httpFields.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString())) + .body(content) + .onResponseSuccess(r -> responseLatch.countDown()) + ).send(); + + // Do not add content to the request, the server should time out and send the response. + assertTrue(responseLatch.await(2 * idleTimeout, TimeUnit.MILLISECONDS)); + + // Terminate the request too. + content.close(); + + ContentResponse response = completable.get(idleTimeout, TimeUnit.MILLISECONDS); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, response.getStatus()); + } +} diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Resource.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Resource.java new file mode 100644 index 00000000000..904df7968f5 --- /dev/null +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Resource.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd 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 +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.ee10.jersey.tests.endpoints; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.container.Suspended; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; + +@Path("resource") +public class Resource +{ + @PUT + @Path("/security") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public void putSecurity(@Context HttpServletRequest httpRequest, Security security, @Suspended final AsyncResponse asyncResponse) + { + if (security.getPrincipal() == null) + throw new NullPointerException("principal must no be null"); + if (security.getRoles() == null) + throw new NullPointerException("roles must no be null"); + + asyncResponse.resume(""" + { + "response" : "ok" + } + """); + } +} diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Security.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Security.java new file mode 100644 index 00000000000..5aff17c0ecf --- /dev/null +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/java/org/eclipse/jetty/ee10/jersey/tests/endpoints/Security.java @@ -0,0 +1,56 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd 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 +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.ee10.jersey.tests.endpoints; + +import java.util.ArrayList; +import java.util.List; + +public class Security +{ + private String principal; + private List roles = new ArrayList<>(); + + public Security() + { + } + + public String getPrincipal() + { + return principal; + } + + public void setPrincipal(String principal) + { + this.principal = principal; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + @Override + public String toString() + { + return "Security{" + + "principal='" + principal + '\'' + + ", roles=" + roles + + '}'; + } +} diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/resources/jetty-logging.properties b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/resources/jetty-logging.properties new file mode 100644 index 00000000000..3e8f0232e8d --- /dev/null +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-jersey/src/test/resources/jetty-logging.properties @@ -0,0 +1,2 @@ +#org.eclipse.jetty.LEVEL=DEBUG +#org.eclipse.jetty.ee10.servlet.LEVEL=DEBUG diff --git a/jetty-ee10/jetty-ee10-tests/pom.xml b/jetty-ee10/jetty-ee10-tests/pom.xml index 507bd557149..d3e64ca0472 100644 --- a/jetty-ee10/jetty-ee10-tests/pom.xml +++ b/jetty-ee10/jetty-ee10-tests/pom.xml @@ -21,6 +21,7 @@ jetty-ee10-test-felix-webapp jetty-ee10-test-http2-webapp jetty-ee10-test-integration + jetty-ee10-test-jersey jetty-ee10-test-jmx jetty-ee10-test-jndi jetty-ee10-test-loginservice diff --git a/jetty-ee10/pom.xml b/jetty-ee10/pom.xml index 6d73575a460..30aa2afba5a 100644 --- a/jetty-ee10/pom.xml +++ b/jetty-ee10/pom.xml @@ -59,6 +59,7 @@ 4.0.1 4.0.0 4.0.0 + 3.1.5 10.1.16 2.0.1 @@ -372,6 +373,21 @@ jaxb-runtime ${jakarta.xml.bind.impl.version} + + org.glassfish.jersey.containers + jersey-container-servlet + ${jersey.version} + + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey.version} + + + org.glassfish.jersey.media + jersey-media-json-binding + ${jersey.version} + org.glassfish.web jakarta.servlet.jsp.jstl