Skip to content

Commit 11d575a

Browse files
authored
fix: Reuse jetty client (#1658)
Signed-off-by: jandadav <janda.david@gmail.com>
1 parent b83ec3e commit 11d575a

File tree

6 files changed

+76
-45
lines changed

6 files changed

+76
-45
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* This program and the accompanying materials are made available under the terms of the
3+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
4+
* https://www.eclipse.org/legal/epl-v20.html
5+
*
6+
* SPDX-License-Identifier: EPL-2.0
7+
*
8+
* Copyright Contributors to the Zowe Project.
9+
*/
10+
11+
package org.zowe.apiml.gateway.ws;
12+
13+
import lombok.extern.slf4j.Slf4j;
14+
import org.eclipse.jetty.client.HttpClient;
15+
import org.eclipse.jetty.util.ssl.SslContextFactory;
16+
import org.eclipse.jetty.websocket.client.WebSocketClient;
17+
import org.springframework.stereotype.Component;
18+
import org.springframework.web.socket.client.jetty.JettyWebSocketClient;
19+
20+
import javax.annotation.PreDestroy;
21+
22+
/**
23+
* Factory for provisioning web socket client
24+
*
25+
* Manages the client lifecycle
26+
*/
27+
@Component
28+
@Slf4j
29+
public class WebSocketClientFactory {
30+
31+
private final JettyWebSocketClient client;
32+
33+
public WebSocketClientFactory(SslContextFactoryProvider sslContextFactoryProvider) {
34+
SslContextFactory.Server jettySslContextFactory = sslContextFactoryProvider.getSslFactory();
35+
log.debug("Creating Jetty WebSocket client, with SslFactory: {} and SslContextFactoryProvider: {}",
36+
jettySslContextFactory, sslContextFactoryProvider);
37+
client = new JettyWebSocketClient(new WebSocketClient(new HttpClient(jettySslContextFactory)));
38+
client.start();
39+
}
40+
41+
JettyWebSocketClient getClientInstance() {
42+
return client;
43+
}
44+
45+
@PreDestroy
46+
private void closeClient() {
47+
if (client.isRunning()) {
48+
log.debug("Closing Jetty WebSocket client");
49+
closeClient();
50+
}
51+
}
52+
53+
}

gateway-service/src/main/java/org/zowe/apiml/gateway/ws/WebSocketProxyServerHandler.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,14 @@
99
*/
1010
package org.zowe.apiml.gateway.ws;
1111

12-
import org.zowe.apiml.product.routing.RoutedService;
13-
import org.zowe.apiml.product.routing.RoutedServices;
14-
import org.zowe.apiml.product.routing.RoutedServicesUser;
1512
import lombok.extern.slf4j.Slf4j;
16-
import org.eclipse.jetty.util.ssl.SslContextFactory;
1713
import org.springframework.beans.factory.annotation.Autowired;
1814
import org.springframework.cloud.client.ServiceInstance;
1915
import org.springframework.cloud.client.discovery.DiscoveryClient;
2016
import org.springframework.stereotype.Component;
21-
import org.springframework.web.socket.CloseStatus;
22-
import org.springframework.web.socket.WebSocketMessage;
23-
import org.springframework.web.socket.WebSocketSession;
17+
import org.springframework.web.socket.*;
2418
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
19+
import org.zowe.apiml.product.routing.*;
2520

2621
import javax.inject.Singleton;
2722
import java.io.IOException;
@@ -43,26 +38,26 @@ public class WebSocketProxyServerHandler extends AbstractWebSocketHandler implem
4338
private final Map<String, WebSocketRoutedSession> routedSessions;
4439
private final Map<String, RoutedServices> routedServicesMap = new ConcurrentHashMap<>();
4540
private final DiscoveryClient discovery;
46-
private final SslContextFactory.Server jettySslContextFactory;
4741
private final WebSocketRoutedSessionFactory webSocketRoutedSessionFactory;
42+
private final WebSocketClientFactory webSocketClientFactory;
4843
private static final String SEPARATOR = "/";
4944

5045
@Autowired
51-
public WebSocketProxyServerHandler(DiscoveryClient discovery, SslContextFactoryProvider jettySslContextFactoryProvider) {
46+
public WebSocketProxyServerHandler(DiscoveryClient discovery, WebSocketClientFactory webSocketClientFactory) {
5247
this.discovery = discovery;
53-
this.jettySslContextFactory = jettySslContextFactoryProvider.getSslFactory();
48+
this.webSocketClientFactory = webSocketClientFactory;
5449
this.routedSessions = new ConcurrentHashMap<>(); // Default
5550
this.webSocketRoutedSessionFactory = new WebSocketRoutedSessionFactoryImpl();
56-
log.debug("Creating WebSocketProxyServerHandler {} jettySslContextFactory={}", this, jettySslContextFactory);
51+
log.debug("Creating WebSocketProxyServerHandler {} ", this);
5752
}
5853

59-
public WebSocketProxyServerHandler(DiscoveryClient discovery, SslContextFactoryProvider sslContextFactoryProvider,
54+
public WebSocketProxyServerHandler(DiscoveryClient discovery, WebSocketClientFactory webSocketClientFactory,
6055
Map<String, WebSocketRoutedSession> routedSessions, WebSocketRoutedSessionFactory webSocketRoutedSessionFactory) {
6156
this.discovery = discovery;
62-
this.jettySslContextFactory = sslContextFactoryProvider.getSslFactory();
57+
this.webSocketClientFactory = webSocketClientFactory;
6358
this.routedSessions = routedSessions;
6459
this.webSocketRoutedSessionFactory = webSocketRoutedSessionFactory;
65-
log.debug("Creating WebSocketProxyServerHandler {} jettySslContextFactory={}", this, jettySslContextFactory);
60+
log.debug("Creating WebSocketProxyServerHandler {}", this);
6661
}
6762

6863
public void addRoutedServices(String serviceId, RoutedServices routedServices) {
@@ -133,9 +128,9 @@ private void openWebSocketConnection(RoutedService service, ServiceInstance serv
133128
String serviceUrl = service.getServiceUrl();
134129
String targetUrl = getTargetUrl(serviceUrl, serviceInstance, path);
135130

136-
log.debug(String.format("Opening routed WebSocket session from %s to %s with %s by %s", uri.toString(), targetUrl, jettySslContextFactory, this));
131+
log.debug(String.format("Opening routed WebSocket session from %s to %s with %s by %s", uri.toString(), targetUrl, webSocketClientFactory, this));
137132
try {
138-
WebSocketRoutedSession session = webSocketRoutedSessionFactory.session(webSocketSession, targetUrl, jettySslContextFactory);
133+
WebSocketRoutedSession session = webSocketRoutedSessionFactory.session(webSocketSession, targetUrl, webSocketClientFactory);
139134
routedSessions.put(webSocketSession.getId(), session);
140135
} catch (WebSocketProxyError e) {
141136
log.debug("Error opening WebSocket connection to {}: {}", targetUrl, e.getMessage());
@@ -146,7 +141,7 @@ private void openWebSocketConnection(RoutedService service, ServiceInstance serv
146141
private ServiceInstance findServiceInstance(String serviceId) {
147142
List<ServiceInstance> serviceInstances = this.discovery.getInstances(serviceId);
148143
if (!serviceInstances.isEmpty()) {
149-
// TODO: This just a simple implementation that will be replaced by more sophisticated mechanism in future
144+
// TODO: Is this implementation apropriate?
150145
return serviceInstances.get(0);
151146
}
152147
else {

gateway-service/src/main/java/org/zowe/apiml/gateway/ws/WebSocketRoutedSession.java

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,11 @@
1010
package org.zowe.apiml.gateway.ws;
1111

1212
import lombok.extern.slf4j.Slf4j;
13-
import org.eclipse.jetty.client.HttpClient;
14-
import org.eclipse.jetty.util.ssl.SslContextFactory;
1513
import org.eclipse.jetty.websocket.api.UpgradeException;
16-
import org.eclipse.jetty.websocket.client.WebSocketClient;
1714
import org.springframework.http.HttpHeaders;
1815
import org.springframework.http.HttpStatus;
1916
import org.springframework.util.concurrent.ListenableFuture;
20-
import org.springframework.web.socket.CloseStatus;
21-
import org.springframework.web.socket.WebSocketHttpHeaders;
22-
import org.springframework.web.socket.WebSocketMessage;
23-
import org.springframework.web.socket.WebSocketSession;
17+
import org.springframework.web.socket.*;
2418
import org.springframework.web.socket.client.jetty.JettyWebSocketClient;
2519

2620
import java.io.IOException;
@@ -42,14 +36,12 @@ public class WebSocketRoutedSession {
4236
private final WebSocketSession webSocketClientSession;
4337
private final WebSocketSession webSocketServerSession;
4438

45-
public WebSocketRoutedSession(WebSocketSession webSocketServerSession, String targetUrl, SslContextFactory.Server jettySslContextFactory) {
46-
log.debug("Creating WebSocketRoutedSession jettySslContextFactory={}", jettySslContextFactory);
39+
public WebSocketRoutedSession(WebSocketSession webSocketServerSession, String targetUrl, WebSocketClientFactory webSocketClientFactory) {
4740
this.webSocketServerSession = webSocketServerSession;
48-
this.webSocketClientSession = createWebSocketClientSession(webSocketServerSession, targetUrl, jettySslContextFactory);
41+
this.webSocketClientSession = createWebSocketClientSession(webSocketServerSession, targetUrl, webSocketClientFactory);
4942
}
5043

5144
public WebSocketRoutedSession(WebSocketSession webSocketServerSession, WebSocketSession webSocketClientSession) {
52-
log.debug("Creating WebSocketRoutedSession with provided server and client session.");
5345
this.webSocketClientSession = webSocketClientSession;
5446
this.webSocketServerSession = webSocketServerSession;
5547
}
@@ -73,12 +65,9 @@ public WebSocketSession getWebSocketServerSession() {
7365
return webSocketServerSession;
7466
}
7567

76-
private WebSocketSession createWebSocketClientSession(WebSocketSession webSocketServerSession, String targetUrl, SslContextFactory.Server sslContextFactory) {
68+
private WebSocketSession createWebSocketClientSession(WebSocketSession webSocketServerSession, String targetUrl, WebSocketClientFactory webSocketClientFactory) {
7769
try {
78-
log.debug("createWebSocketClientSession(session={},targetUrl={},jettySslContextFactory={})",
79-
webSocketClientSession, targetUrl, sslContextFactory);
80-
JettyWebSocketClient client = new JettyWebSocketClient(new WebSocketClient(new HttpClient(sslContextFactory)));
81-
client.start();
70+
JettyWebSocketClient client = webSocketClientFactory.getClientInstance();
8271
URI targetURI = new URI(targetUrl);
8372
WebSocketHttpHeaders headers = getWebSocketHttpHeaders(webSocketServerSession);
8473
ListenableFuture<WebSocketSession> futureSession = client

gateway-service/src/main/java/org/zowe/apiml/gateway/ws/WebSocketRoutedSessionFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
*/
1010
package org.zowe.apiml.gateway.ws;
1111

12-
import org.eclipse.jetty.util.ssl.SslContextFactory;
1312
import org.springframework.web.socket.WebSocketSession;
1413

1514
public interface WebSocketRoutedSessionFactory {
@@ -20,5 +19,5 @@ public interface WebSocketRoutedSessionFactory {
2019
* @param sslContextFactory Factory producing the current SSL Context.
2120
* @return Valid routed session handling the client session
2221
*/
23-
WebSocketRoutedSession session(WebSocketSession webSocketSession, String targetUrl, SslContextFactory.Server sslContextFactory);
22+
WebSocketRoutedSession session(WebSocketSession webSocketSession, String targetUrl, WebSocketClientFactory webSocketClientFactory);
2423
}

gateway-service/src/main/java/org/zowe/apiml/gateway/ws/WebSocketRoutedSessionFactoryImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99
*/
1010
package org.zowe.apiml.gateway.ws;
1111

12-
import org.eclipse.jetty.util.ssl.SslContextFactory;
1312
import org.springframework.web.socket.WebSocketSession;
1413

1514
/**
1615
* Default implementation. Provides the WebSocketRoutedSession the same way as before.
1716
*/
1817
public class WebSocketRoutedSessionFactoryImpl implements WebSocketRoutedSessionFactory {
1918
@Override
20-
public WebSocketRoutedSession session(WebSocketSession webSocketSession, String targetUrl, SslContextFactory.Server sslContextFactory) {
21-
return new WebSocketRoutedSession(webSocketSession, targetUrl, sslContextFactory);
19+
public WebSocketRoutedSession session(WebSocketSession webSocketSession, String targetUrl, WebSocketClientFactory webSocketClientFactory) {
20+
return new WebSocketRoutedSession(webSocketSession, targetUrl, webSocketClientFactory);
2221
}
2322
}

gateway-service/src/test/java/org/zowe/apiml/gateway/ws/WebSocketProxyServerHandlerTest.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@
1414
import org.junit.jupiter.api.Test;
1515
import org.springframework.cloud.client.ServiceInstance;
1616
import org.springframework.cloud.client.discovery.DiscoveryClient;
17-
import org.springframework.web.socket.CloseStatus;
18-
import org.springframework.web.socket.WebSocketMessage;
19-
import org.springframework.web.socket.WebSocketSession;
17+
import org.springframework.web.socket.*;
2018
import org.zowe.apiml.product.routing.RoutedService;
2119
import org.zowe.apiml.product.routing.RoutedServices;
2220

2321
import java.net.URI;
24-
import java.util.Collections;
25-
import java.util.HashMap;
26-
import java.util.Map;
22+
import java.util.*;
2723

2824
import static org.hamcrest.CoreMatchers.is;
2925
import static org.hamcrest.CoreMatchers.notNullValue;
@@ -48,7 +44,7 @@ public void setup() {
4844

4945
underTest = new WebSocketProxyServerHandler(
5046
discoveryClient,
51-
sslContextFactoryProvider,
47+
mock(WebSocketClientFactory.class),
5248
routedSessions,
5349
webSocketRoutedSessionFactory
5450
);

0 commit comments

Comments
 (0)