Add jersey test module (#11423)

Add jersey test module

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Co-authored-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Ludovic Orban 2024-02-21 22:00:07 +01:00 committed by GitHub
parent f3b37bc277
commit 509ede1d85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 348 additions and 1 deletions

View File

@ -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;
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-tests</artifactId>
<version>12.0.7-SNAPSHOT</version>
</parent>
<artifactId>jetty-ee10-test-jersey</artifactId>
<packaging>jar</packaging>
<name>EE10 :: Tests :: Jersey</name>
<properties>
<bundle-symbolic-name>${project.groupId}.jersey.tests</bundle-symbolic-name>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -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<ContentResponse> 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());
}
}

View File

@ -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"
}
""");
}
}

View File

@ -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<String> roles = new ArrayList<>();
public Security()
{
}
public String getPrincipal()
{
return principal;
}
public void setPrincipal(String principal)
{
this.principal = principal;
}
public List<String> getRoles()
{
return roles;
}
public void setRoles(List<String> roles)
{
this.roles = roles;
}
@Override
public String toString()
{
return "Security{" +
"principal='" + principal + '\'' +
", roles=" + roles +
'}';
}
}

View File

@ -0,0 +1,2 @@
#org.eclipse.jetty.LEVEL=DEBUG
#org.eclipse.jetty.ee10.servlet.LEVEL=DEBUG

View File

@ -21,6 +21,7 @@
<module>jetty-ee10-test-felix-webapp</module>
<module>jetty-ee10-test-http2-webapp</module>
<module>jetty-ee10-test-integration</module>
<module>jetty-ee10-test-jersey</module>
<module>jetty-ee10-test-jmx</module>
<module>jetty-ee10-test-jndi</module>
<module>jetty-ee10-test-loginservice</module>

View File

@ -59,6 +59,7 @@
<jakarta.xml.bind.impl.version>4.0.1</jakarta.xml.bind.impl.version>
<jakarta.xml.jaxws.impl.version>4.0.0</jakarta.xml.jaxws.impl.version>
<jakarta.xml.ws.api.version>4.0.0</jakarta.xml.ws.api.version>
<jersey.version>3.1.5</jersey.version>
<jsp.impl.version>10.1.16</jsp.impl.version>
<mail.impl.version>2.0.1</mail.impl.version>
@ -372,6 +373,21 @@
<artifactId>jaxb-runtime</artifactId>
<version>${jakarta.xml.bind.impl.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>