diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpClientProvider.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpClientProvider.java
index e2c89dab64d..cc7a5fa9d08 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpClientProvider.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpClientProvider.java
@@ -35,15 +35,13 @@ public final class HttpClientProvider
Class> xmlClazz = Class.forName("org.eclipse.jetty.websocket.client.XmlBasedHttpClientProvider");
Method getMethod = xmlClazz.getMethod("get", WebSocketContainerScope.class);
Object ret = getMethod.invoke(null, scope);
- if ((ret != null) && (ret instanceof HttpClient))
- {
+ if (ret instanceof HttpClient)
return (HttpClient)ret;
- }
}
}
- catch (Throwable ignore)
+ catch (Throwable t)
{
- Log.getLogger(HttpClientProvider.class).ignore(ignore);
+ Log.getLogger(HttpClientProvider.class).ignore(t);
}
return DefaultHttpClientProvider.newHttpClient(scope);
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/XmlBasedHttpClientProvider.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/XmlBasedHttpClientProvider.java
index e4a7a09199f..a90a944efbc 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/XmlBasedHttpClientProvider.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/XmlBasedHttpClientProvider.java
@@ -22,6 +22,7 @@ import java.net.URL;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.xml.XmlConfiguration;
@@ -31,13 +32,11 @@ class XmlBasedHttpClientProvider
{
URL resource = Thread.currentThread().getContextClassLoader().getResource("jetty-websocket-httpclient.xml");
if (resource == null)
- {
return null;
- }
try
{
- XmlConfiguration configuration = new XmlConfiguration(resource);
+ XmlConfiguration configuration = new XmlConfiguration(Resource.newResource(resource));
return (HttpClient)configuration.configure();
}
catch (Throwable t)
diff --git a/tests/test-distribution/pom.xml b/tests/test-distribution/pom.xml
index 04d73c9fcb9..d247df72629 100644
--- a/tests/test-distribution/pom.xml
+++ b/tests/test-distribution/pom.xml
@@ -102,6 +102,18 @@
${project.version}
test
+
+ org.eclipse.jetty.websocket
+ websocket-api
+ ${project.version}
+ test
+
+
+ org.eclipse.jetty.websocket
+ websocket-client
+ ${project.version}
+ test
+
org.eclipse.jetty.tests
test-felix-webapp
diff --git a/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/DistributionTests.java b/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/DistributionTests.java
index 72bd88c0bd6..2b2fc91e358 100644
--- a/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/DistributionTests.java
+++ b/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/DistributionTests.java
@@ -19,9 +19,11 @@
package org.eclipse.jetty.tests.distribution;
import java.io.File;
+import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
@@ -31,12 +33,18 @@ import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
import org.eclipse.jetty.unixsocket.UnixSocketConnector;
import org.eclipse.jetty.unixsocket.client.HttpClientTransportOverUnixSockets;
+import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.WebSocketListener;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.JRE;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@@ -301,4 +309,95 @@ public class DistributionTests extends AbstractDistributionTest
IO.delete(jettyBase.toFile());
}
}
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", "--jpms"})
+ @DisabledOnJre({JRE.JAVA_14, JRE.JAVA_15})
+ public void testWebsocketClientInWebapp(String arg) throws Exception
+ {
+ Path jettyBase = Files.createTempDirectory("jetty_base");
+ String jettyVersion = System.getProperty("jettyVersion");
+ DistributionTester distribution = DistributionTester.Builder.newInstance()
+ .jettyVersion(jettyVersion)
+ .jettyBase(jettyBase)
+ .mavenLocalRepository(System.getProperty("mavenRepoPath"))
+ .build();
+
+ String[] args1 = {
+ "--create-startd",
+ "--approve-all-licenses",
+ "--add-to-start=resources,server,http,webapp,deploy,jsp,jmx,servlet,servlets,websocket"
+ };
+ try (DistributionTester.Run run1 = distribution.start(args1))
+ {
+ assertTrue(run1.awaitFor(5, TimeUnit.SECONDS));
+ assertEquals(0, run1.getExitValue());
+
+ File webApp = distribution.resolveArtifact("org.eclipse.jetty.tests:test-websocket-client-webapp:war:" + jettyVersion);
+ distribution.installWarFile(webApp, "test");
+
+ int port = distribution.freePort();
+ String[] args2 = {
+ arg,
+ "jetty.http.port=" + port,
+ // "jetty.server.dumpAfterStart=true",
+ // "jetty.webapp.addSystemClasses+=,org.eclipse.jetty.client.",
+ // "jetty.webapp.addServerClasses+=,-org.eclipse.jetty.client.",
+ // "jetty.webapp.addSystemClasses+=,org.eclipse.jetty.util.ssl.",
+ // "jetty.webapp.addServerClasses+=,-org.eclipse.jetty.util.ssl.",
+ // "jetty.webapp.addSystemClasses+=,org.eclipse.jetty.util.component.",
+ // "jetty.webapp.addServerClasses+=,-org.eclipse.jetty.util.component."
+ };
+
+ try (DistributionTester.Run run2 = distribution.start(args2))
+ {
+ assertTrue(run2.awaitConsoleLogsFor("Started @", 10, TimeUnit.SECONDS));
+
+ // We should get the correct configuration from the jetty-websocket-httpclient.xml file.
+ startHttpClient();
+ URI serverUri = URI.create("ws://localhost:" + port + "/test");
+ ContentResponse response = client.GET(serverUri);
+ assertEquals(HttpStatus.OK_200, response.getStatus());
+ String content = response.getContentAsString();
+ System.err.println(content);
+ assertThat(content, containsString("ConnectTimeout: 4999"));
+ assertThat(content, containsString("WebSocketEcho: success"));
+ }
+ }
+ }
+
+ public static class WsListener implements WebSocketListener
+ {
+ public BlockingArrayQueue textMessages = new BlockingArrayQueue<>();
+ public final CountDownLatch closeLatch = new CountDownLatch(1);
+ public int closeCode;
+
+ @Override
+ public void onWebSocketClose(int statusCode, String reason)
+ {
+ this.closeCode = statusCode;
+ closeLatch.countDown();
+ }
+
+ @Override
+ public void onWebSocketConnect(Session session)
+ {
+ }
+
+ @Override
+ public void onWebSocketError(Throwable cause)
+ {
+ }
+
+ @Override
+ public void onWebSocketBinary(byte[] payload, int offset, int len)
+ {
+ }
+
+ @Override
+ public void onWebSocketText(String message)
+ {
+ textMessages.add(message);
+ }
+ }
}
diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml
index f7b81a61182..e57b053ca11 100644
--- a/tests/test-webapps/pom.xml
+++ b/tests/test-webapps/pom.xml
@@ -44,5 +44,6 @@
test-cdi-common-webapp
test-weld-cdi-webapp
test-owb-cdi-webapp
+ test-websocket-client-webapp
diff --git a/tests/test-webapps/test-websocket-client-webapp/pom.xml b/tests/test-webapps/test-websocket-client-webapp/pom.xml
new file mode 100644
index 00000000000..6bd4a5cb9e3
--- /dev/null
+++ b/tests/test-webapps/test-websocket-client-webapp/pom.xml
@@ -0,0 +1,33 @@
+
+
+
+ org.eclipse.jetty.tests
+ test-webapps-parent
+ 9.4.32-SNAPSHOT
+
+
+ 4.0.0
+ test-websocket-client-webapp
+ war
+
+ Test :: Jetty Websocket Simple Webapp with WebSocketClient
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+ javax.websocket
+ javax.websocket-api
+ provided
+
+
+ org.eclipse.jetty.websocket
+ websocket-client
+ ${project.version}
+ provided
+
+
+
diff --git a/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/EchoEndpoint.java b/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/EchoEndpoint.java
new file mode 100644
index 00000000000..2120c5d7cca
--- /dev/null
+++ b/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/EchoEndpoint.java
@@ -0,0 +1,32 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.tests.webapp.websocket;
+
+import javax.websocket.OnMessage;
+import javax.websocket.server.ServerEndpoint;
+
+@ServerEndpoint(value = "/echo")
+public class EchoEndpoint
+{
+ @OnMessage
+ public String echo(String message)
+ {
+ return message;
+ }
+}
diff --git a/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/WebSocketClientServlet.java b/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/WebSocketClientServlet.java
new file mode 100644
index 00000000000..2b026ac5a80
--- /dev/null
+++ b/tests/test-webapps/test-websocket-client-webapp/src/main/java/org/eclipse/jetty/tests/webapp/websocket/WebSocketClientServlet.java
@@ -0,0 +1,104 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.tests.webapp.websocket;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
+import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
+import org.eclipse.jetty.websocket.api.annotations.WebSocket;
+import org.eclipse.jetty.websocket.api.util.WSURI;
+import org.eclipse.jetty.websocket.client.WebSocketClient;
+
+@WebServlet("/")
+public class WebSocketClientServlet extends HttpServlet
+{
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
+ {
+
+ WebSocketClient client = null;
+ try
+ {
+ client = new WebSocketClient();
+ LifeCycle.start(client);
+ resp.setContentType("text/html");
+ resp.getWriter().println("ConnectTimeout: " + client.getHttpClient().getConnectTimeout());
+
+ ClientSocket clientSocket = new ClientSocket();
+ URI wsUri = WSURI.toWebsocket(req.getRequestURL()).resolve("echo");
+ client.connect(clientSocket, wsUri);
+ clientSocket.openLatch.await(5, TimeUnit.SECONDS);
+ clientSocket.session.getRemote().sendString("test message");
+ String response = clientSocket.textMessages.poll(5, TimeUnit.SECONDS);
+ if (!"test message".equals(response))
+ throw new RuntimeException("incorrect response");
+ clientSocket.session.close();
+ clientSocket.closeLatch.await(5, TimeUnit.SECONDS);
+ resp.getWriter().println("WebSocketEcho: success");
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ LifeCycle.stop(client);
+ }
+ }
+
+ @WebSocket
+ public static class ClientSocket
+ {
+ public Session session;
+ public CountDownLatch openLatch = new CountDownLatch(1);
+ public CountDownLatch closeLatch = new CountDownLatch(1);
+ public ArrayBlockingQueue textMessages = new ArrayBlockingQueue<>(10);
+
+ @OnWebSocketConnect
+ public void onOpen(Session session)
+ {
+ this.session = session;
+ openLatch.countDown();
+ }
+
+ @OnWebSocketMessage
+ public void onMessage(String message)
+ {
+ textMessages.add(message);
+ }
+
+ @OnWebSocketClose
+ public void onClose(int statusCode, String reason)
+ {
+ closeLatch.countDown();
+ }
+ }
+}
diff --git a/tests/test-webapps/test-websocket-client-webapp/src/main/resources/jetty-websocket-httpclient.xml b/tests/test-webapps/test-websocket-client-webapp/src/main/resources/jetty-websocket-httpclient.xml
new file mode 100644
index 00000000000..469550c5b5a
--- /dev/null
+++ b/tests/test-webapps/test-websocket-client-webapp/src/main/resources/jetty-websocket-httpclient.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+ false
+
+
+
+ - TLS/1.3
+
+
+
+
+
+
+
+
+
+
+ 4999
+
diff --git a/tests/test-webapps/test-websocket-client-webapp/src/main/webapp/WEB-INF/web.xml b/tests/test-webapps/test-websocket-client-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000000..99907fad52a
--- /dev/null
+++ b/tests/test-webapps/test-websocket-client-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,8 @@
+
+
+