GH-9228: Provide binding to ZeroMqMessageHandler

Fixes: #9228

* add docs

* protected constructor in ZeroMqMessageHandlerSpec, expose them via ZeroMq

* introduce ZeroMqUtils, for common Zero MQ utilities functions

* use ZeroMqUtils.bindSocket in ZeroMqMessageProducer

* refactor ZeroMqMessageHandler providing connectUrl and bindPort setters and simple constructors, following the same logic used for ZeroMqMessageProvider

* fix tests to follow the new ZeroMqMessageHandler implementation

* fix typo

* add new updates to whats-new.adoc

* address ZeroMQUtils comments

* remove connectUrl and boundPort setters, add Javadoc to new constructors

* add new DLS constructor for random port

* add since closure in ZeroMqUtils

* add DSL support methods and specific that, when not defined, the socket will be bound to a random port
This commit is contained in:
Alessio Matricardi
2024-07-01 19:00:26 +02:00
committed by GitHub
parent 78ae221fd5
commit 272dde8945
9 changed files with 302 additions and 33 deletions

View File

@@ -35,6 +35,7 @@ import org.springframework.integration.zeromq.ZeroMqProxy;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.util.TestSocketUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
@@ -65,12 +66,12 @@ public class ZeroMqMessageHandlerTests {
messageHandler.setBeanFactory(mock(BeanFactory.class));
messageHandler.setSocketConfigurer(s -> s.setZapDomain("global"));
messageHandler.afterPropertiesSet();
messageHandler.start();
@SuppressWarnings("unchecked")
Mono<ZMQ.Socket> socketMono = TestUtils.getPropertyValue(messageHandler, "socketMono", Mono.class);
ZMQ.Socket socketInUse = socketMono.block(Duration.ofSeconds(10));
assertThat(socketInUse.getZapDomain()).isEqualTo("global");
messageHandler.start();
Message<?> testMessage = new GenericMessage<>("test");
messageHandler.handleMessage(testMessage).subscribe();
@@ -187,4 +188,41 @@ public class ZeroMqMessageHandlerTests {
subSocket.close();
}
@Test
void testMessageHandlerForPubSubWithBind() {
int boundPort = TestSocketUtils.findAvailableTcpPort();
ZeroMqMessageHandler messageHandler =
new ZeroMqMessageHandler(CONTEXT, boundPort, SocketType.PUB);
messageHandler.setBeanFactory(mock(BeanFactory.class));
messageHandler.setTopicExpression(
new FunctionExpression<Message<?>>((message) -> message.getHeaders().get("topic")));
messageHandler.setMessageMapper(new EmbeddedJsonHeadersMessageMapper());
messageHandler.wrapTopic(false);
messageHandler.afterPropertiesSet();
messageHandler.start();
ZMQ.Socket subSocket = CONTEXT.createSocket(SocketType.SUB);
subSocket.setReceiveTimeOut(0);
subSocket.connect("tcp://localhost:" + boundPort);
subSocket.subscribe("test");
Message<?> testMessage = MessageBuilder.withPayload("test").setHeader("topic", "testTopic").build();
await().atMost(Duration.ofSeconds(20)).pollDelay(Duration.ofMillis(100))
.untilAsserted(() -> {
subSocket.subscribe("test");
messageHandler.handleMessage(testMessage).subscribe();
ZMsg msg = ZMsg.recvMsg(subSocket);
assertThat(msg).isNotNull();
assertThat(msg.pop().getString(ZMQ.CHARSET)).isEqualTo("testTopic");
Message<?> capturedMessage =
new EmbeddedJsonHeadersMessageMapper().toMessage(msg.getFirst().getData());
assertThat(capturedMessage).isEqualTo(testMessage);
msg.destroy();
});
messageHandler.destroy();
subSocket.close();
}
}