Use of TcpClient extensible per connection
Closes gh-25889
This commit is contained in:
parent
43f595f80e
commit
76eb5e6e2c
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.messaging.simp.stomp;
|
||||
|
||||
import org.springframework.messaging.tcp.TcpConnectionHandler;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
|
|
@ -30,7 +29,7 @@ import org.springframework.util.concurrent.ListenableFuture;
|
|||
* @author Rossen Stoyanchev
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface ConnectionHandlingStompSession extends StompSession, TcpConnectionHandler<byte[]> {
|
||||
public interface ConnectionHandlingStompSession extends StompSession, StompTcpConnectionHandler<byte[]> {
|
||||
|
||||
/**
|
||||
* Return a future that will complete when the session is ready for use.
|
||||
|
|
|
|||
|
|
@ -133,6 +133,13 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
|
|||
return this.sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StompHeaderAccessor getConnectHeaders() {
|
||||
StompHeaderAccessor accessor = createHeaderAccessor(StompCommand.CONNECT);
|
||||
accessor.addNativeHeaders(this.connectHeaders);
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured session handler.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ import org.springframework.messaging.support.MessageHeaderAccessor;
|
|||
import org.springframework.messaging.support.MessageHeaderInitializer;
|
||||
import org.springframework.messaging.tcp.FixedIntervalReconnectStrategy;
|
||||
import org.springframework.messaging.tcp.TcpConnection;
|
||||
import org.springframework.messaging.tcp.TcpConnectionHandler;
|
||||
import org.springframework.messaging.tcp.TcpOperations;
|
||||
import org.springframework.messaging.tcp.reactor.ReactorNettyCodec;
|
||||
import org.springframework.messaging.tcp.reactor.ReactorNettyTcpClient;
|
||||
|
|
@ -141,7 +140,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
|
||||
private final DefaultStats stats = new DefaultStats();
|
||||
|
||||
private final Map<String, StompConnectionHandler> connectionHandlers = new ConcurrentHashMap<>();
|
||||
private final Map<String, RelayConnectionHandler> connectionHandlers = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private TaskScheduler taskScheduler;
|
||||
|
|
@ -451,7 +450,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
logger.debug("Forwarding " + accessor.getShortLogMessage(EMPTY_PAYLOAD));
|
||||
}
|
||||
|
||||
SystemStompConnectionHandler handler = new SystemStompConnectionHandler(accessor);
|
||||
SystemSessionConnectionHandler handler = new SystemSessionConnectionHandler(accessor);
|
||||
this.connectionHandlers.put(handler.getSessionId(), handler);
|
||||
|
||||
this.stats.incrementConnectCount();
|
||||
|
|
@ -495,7 +494,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
throw new MessageDeliveryException("Message broker not active. Consider subscribing to " +
|
||||
"receive BrokerAvailabilityEvent's from an ApplicationListener Spring bean.");
|
||||
}
|
||||
StompConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
RelayConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
if (handler != null) {
|
||||
handler.sendStompErrorFrameToClient("Broker not available.");
|
||||
handler.clearConnection();
|
||||
|
|
@ -562,14 +561,14 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
if (getVirtualHost() != null) {
|
||||
stompAccessor.setHost(getVirtualHost());
|
||||
}
|
||||
StompConnectionHandler handler = new StompConnectionHandler(sessionId, stompAccessor);
|
||||
RelayConnectionHandler handler = new RelayConnectionHandler(sessionId, stompAccessor);
|
||||
this.connectionHandlers.put(sessionId, handler);
|
||||
this.stats.incrementConnectCount();
|
||||
Assert.state(this.tcpClient != null, "No TCP client available");
|
||||
this.tcpClient.connect(handler);
|
||||
}
|
||||
else if (StompCommand.DISCONNECT.equals(command)) {
|
||||
StompConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
RelayConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
if (handler == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring DISCONNECT in session " + sessionId + ". Connection already cleaned up.");
|
||||
|
|
@ -580,7 +579,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
handler.forward(message, stompAccessor);
|
||||
}
|
||||
else {
|
||||
StompConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
RelayConnectionHandler handler = this.connectionHandlers.get(sessionId);
|
||||
if (handler == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No TCP connection for session " + sessionId + " in " + message);
|
||||
|
|
@ -611,7 +610,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
}
|
||||
|
||||
|
||||
private class StompConnectionHandler implements TcpConnectionHandler<byte[]> {
|
||||
private class RelayConnectionHandler implements StompTcpConnectionHandler<byte[]> {
|
||||
|
||||
private final String sessionId;
|
||||
|
||||
|
|
@ -634,11 +633,11 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
private long clientSendMessageTimestamp;
|
||||
|
||||
|
||||
protected StompConnectionHandler(String sessionId, StompHeaderAccessor connectHeaders) {
|
||||
protected RelayConnectionHandler(String sessionId, StompHeaderAccessor connectHeaders) {
|
||||
this(sessionId, connectHeaders, true);
|
||||
}
|
||||
|
||||
private StompConnectionHandler(String sessionId, StompHeaderAccessor connectHeaders, boolean isClientSession) {
|
||||
private RelayConnectionHandler(String sessionId, StompHeaderAccessor connectHeaders, boolean isClientSession) {
|
||||
Assert.notNull(sessionId, "'sessionId' must not be null");
|
||||
Assert.notNull(connectHeaders, "'connectHeaders' must not be null");
|
||||
this.sessionId = sessionId;
|
||||
|
|
@ -662,6 +661,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
return this.sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StompHeaderAccessor getConnectHeaders() {
|
||||
return this.connectHeaders;
|
||||
}
|
||||
|
|
@ -968,9 +968,9 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
}
|
||||
|
||||
|
||||
private class SystemStompConnectionHandler extends StompConnectionHandler {
|
||||
private class SystemSessionConnectionHandler extends RelayConnectionHandler {
|
||||
|
||||
public SystemStompConnectionHandler(StompHeaderAccessor connectHeaders) {
|
||||
public SystemSessionConnectionHandler(StompHeaderAccessor connectHeaders) {
|
||||
super(SYSTEM_SESSION_ID, connectHeaders, false);
|
||||
}
|
||||
|
||||
|
|
@ -1099,7 +1099,7 @@ public class StompBrokerRelayMessageHandler extends AbstractBrokerMessageHandler
|
|||
@Override
|
||||
public void run() {
|
||||
long now = System.currentTimeMillis();
|
||||
for (StompConnectionHandler handler : connectionHandlers.values()) {
|
||||
for (RelayConnectionHandler handler : connectionHandlers.values()) {
|
||||
handler.updateClientSendMessageCount(now);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.messaging.simp.stomp;
|
||||
|
||||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||
import org.springframework.messaging.tcp.TcpConnectionHandler;
|
||||
|
||||
/**
|
||||
* A {@link TcpConnectionHandler} for use with STOMP connections, exposing
|
||||
* further information about the connection.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.3
|
||||
* @param <P> the type of payload for inbound and outbound messages
|
||||
*/
|
||||
public interface StompTcpConnectionHandler<P> extends TcpConnectionHandler<P> {
|
||||
|
||||
/**
|
||||
* Return the {@link SimpMessageHeaderAccessor#getSessionId() sessionId}
|
||||
* associated with the STOMP connection.
|
||||
*/
|
||||
String getSessionId();
|
||||
|
||||
/**
|
||||
* Return the headers that will be sent in the STOMP CONNECT frame.
|
||||
*/
|
||||
StompHeaderAccessor getConnectHeaders();
|
||||
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ public class ReactorNettyTcpClient<P> implements TcpOperations<P> {
|
|||
return handleShuttingDownConnectFailure(handler);
|
||||
}
|
||||
|
||||
Mono<Void> connectMono = this.tcpClient
|
||||
Mono<Void> connectMono = extendTcpClient(this.tcpClient, handler)
|
||||
.handle(new ReactorNettyHandler(handler))
|
||||
.connect()
|
||||
.doOnError(handler::afterConnectFailure)
|
||||
|
|
@ -195,6 +195,19 @@ public class ReactorNettyTcpClient<P> implements TcpOperations<P> {
|
|||
return new MonoToListenableFutureAdapter<>(connectMono);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an opportunity to initialize the {@link TcpClient} for the given
|
||||
* {@link TcpConnectionHandler} which may implement sub-interfaces such as
|
||||
* {@link org.springframework.messaging.simp.stomp.StompTcpConnectionHandler}
|
||||
* that expose further information.
|
||||
* @param tcpClient the candidate TcpClient
|
||||
* @param handler the handler for the TCP connection
|
||||
* @return the same handler or an updated instance
|
||||
*/
|
||||
protected TcpClient extendTcpClient(TcpClient tcpClient, TcpConnectionHandler<P> handler) {
|
||||
return tcpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) {
|
||||
Assert.notNull(handler, "TcpConnectionHandler is required");
|
||||
|
|
@ -207,7 +220,7 @@ public class ReactorNettyTcpClient<P> implements TcpOperations<P> {
|
|||
// Report first connect to the ListenableFuture
|
||||
CompletableFuture<Void> connectFuture = new CompletableFuture<>();
|
||||
|
||||
this.tcpClient
|
||||
extendTcpClient(this.tcpClient, handler)
|
||||
.handle(new ReactorNettyHandler(handler))
|
||||
.connect()
|
||||
.doOnNext(conn -> connectFuture.complete(null))
|
||||
|
|
|
|||
Loading…
Reference in New Issue