INT-4138: MQTT: Outbound Adapter Improvements
JIRA:https://jira.spring.io/browse/INT-4138 Expressions for topic, qos, retained. Also change inbound mapping to `RECEIVED_...` headers. Fix some minor asciidoc problems in (s)ftp. Rework Qos/Retained Expressions/Defaults Encapsulate the logic entirely in the converter. Polishing - PR Comments
This commit is contained in:
committed by
Artem Bilan
parent
d42357ba02
commit
3035bc716d
@@ -54,8 +54,7 @@ import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -63,8 +62,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class BackToBackAdapterTests {
|
||||
|
||||
@@ -103,7 +101,7 @@ public class BackToBackAdapterTests {
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,21 +122,21 @@ public class BackToBackAdapterTests {
|
||||
inbound.start();
|
||||
inbound.addTopic("mqtt-foo");
|
||||
adapter.handleMessage(new GenericMessage<String>("foo"));
|
||||
Message<?> out = outputChannel.receive(10000);
|
||||
Message<?> out = outputChannel.receive(10_000);
|
||||
assertNotNull(out);
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
|
||||
inbound.addTopic("mqtt-bar");
|
||||
adapter.handleMessage(MessageBuilder.withPayload("bar").setHeader(MqttHeaders.TOPIC, "mqtt-bar").build());
|
||||
out = outputChannel.receive(10000);
|
||||
out = outputChannel.receive(10_000);
|
||||
assertNotNull(out);
|
||||
assertEquals("bar", out.getPayload());
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
|
||||
inbound.removeTopic("mqtt-bar");
|
||||
adapter.handleMessage(MessageBuilder.withPayload("bar").setHeader(MqttHeaders.TOPIC, "mqtt-bar").build());
|
||||
out = outputChannel.receive(10000);
|
||||
out = outputChannel.receive(10_000);
|
||||
assertNull(out);
|
||||
|
||||
try {
|
||||
@@ -183,12 +181,12 @@ public class BackToBackAdapterTests {
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
out = outputChannel.receive(10000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("bar", out.getPayload());
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -220,7 +218,7 @@ public class BackToBackAdapterTests {
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -288,10 +286,10 @@ public class BackToBackAdapterTests {
|
||||
out = outputChannel.receive(10000);
|
||||
assertNotNull(out);
|
||||
if ("foo".equals(out.getPayload())) {
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
}
|
||||
else if ("bar".equals(out.getPayload())) {
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
}
|
||||
else {
|
||||
fail("unexpected payload " + out.getPayload());
|
||||
|
||||
@@ -45,16 +45,14 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class DownstreamExceptionTests {
|
||||
|
||||
|
||||
@@ -59,8 +59,12 @@ import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
import org.springframework.integration.mqtt.core.ConsumerStopAction;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory.Will;
|
||||
@@ -69,6 +73,8 @@ import org.springframework.integration.mqtt.event.MqttIntegrationEvent;
|
||||
import org.springframework.integration.mqtt.event.MqttSubscribedEvent;
|
||||
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
@@ -337,6 +343,31 @@ public class MqttAdapterTests {
|
||||
verifyNotUnsubscribe(client);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testCustomExpressions() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
|
||||
MqttPahoMessageHandler handler = ctx.getBean("handler", MqttPahoMessageHandler.class);
|
||||
GenericMessage<String> message = new GenericMessage<>("foo");
|
||||
assertEquals("fooTopic",
|
||||
TestUtils.getPropertyValue(handler, "topicProcessor", MessageProcessor.class).processMessage(message));
|
||||
assertEquals(1,
|
||||
TestUtils.getPropertyValue(handler, "converter.qosProcessor", MessageProcessor.class)
|
||||
.processMessage(message));
|
||||
assertEquals(Boolean.TRUE,
|
||||
TestUtils.getPropertyValue(handler, "converter.retainedProcessor", MessageProcessor.class)
|
||||
.processMessage(message));
|
||||
|
||||
handler = ctx.getBean("handlerWithNullExpressions", MqttPahoMessageHandler.class);
|
||||
assertEquals(1,
|
||||
TestUtils.getPropertyValue(handler, "converter", DefaultPahoMessageConverter.class)
|
||||
.fromMessage(message, null).getQos());
|
||||
assertEquals(Boolean.TRUE,
|
||||
TestUtils.getPropertyValue(handler, "converter", DefaultPahoMessageConverter.class)
|
||||
.fromMessage(message, null).isRetained());
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
private MqttPahoMessageDrivenChannelAdapter buildAdapter(final MqttAsyncClient client, Boolean cleanSession,
|
||||
ConsumerStopAction action) throws MqttException, MqttSecurityException {
|
||||
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory() {
|
||||
@@ -380,4 +411,43 @@ public class MqttAdapterTests {
|
||||
verify(client).disconnect();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public MqttPahoMessageHandler handler() {
|
||||
MqttPahoMessageHandler handler = new MqttPahoMessageHandler("tcp://localhost:1883", "bar");
|
||||
handler.setTopicExpressionString("@topic");
|
||||
handler.setQosExpressionString("@qos");
|
||||
handler.setRetainedExpressionString("@retained");
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public String topic() {
|
||||
return "fooTopic";
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Integer qos() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Boolean retained() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MqttPahoMessageHandler handlerWithNullExpressions() {
|
||||
MqttPahoMessageHandler handler = new MqttPahoMessageHandler("tcp://localhost:1883", "bar");
|
||||
handler.setDefaultQos(1);
|
||||
handler.setQosExpressionString("null");
|
||||
handler.setDefaultRetained(true);
|
||||
handler.setRetainedExpressionString("null");
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannel
|
||||
import org.springframework.integration.mqtt.support.MqttMessageConverter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -41,8 +41,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class MqttMessageDrivenChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
converter="myConverter"
|
||||
client-factory="clientFactory"
|
||||
default-topic="bar"
|
||||
topic-expression="'bar'"
|
||||
qos-expression="2"
|
||||
retained-expression="true"
|
||||
phase="25"
|
||||
order="1"
|
||||
channel="target">
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
@@ -38,16 +39,17 @@ import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
|
||||
import org.springframework.integration.mqtt.support.MqttMessageConverter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 4.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class MqttOutboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired @Qualifier("withConverter")
|
||||
@@ -65,11 +67,21 @@ public class MqttOutboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private DefaultMqttPahoClientFactory clientFactory;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testWithConverter() throws Exception {
|
||||
assertEquals("tcp://localhost:1883", TestUtils.getPropertyValue(withConverterHandler, "url"));
|
||||
assertEquals("foo", TestUtils.getPropertyValue(withConverterHandler, "clientId"));
|
||||
assertEquals("bar", TestUtils.getPropertyValue(withConverterHandler, "defaultTopic"));
|
||||
GenericMessage<String> message = new GenericMessage<>("foo");
|
||||
assertEquals("bar",
|
||||
TestUtils.getPropertyValue(withConverterHandler, "topicProcessor", MessageProcessor.class)
|
||||
.processMessage(message));
|
||||
assertEquals(2, TestUtils.getPropertyValue(withConverterHandler, "qosProcessor", MessageProcessor.class)
|
||||
.processMessage(message));
|
||||
assertEquals(Boolean.TRUE,
|
||||
TestUtils.getPropertyValue(withConverterHandler, "retainedProcessor", MessageProcessor.class)
|
||||
.processMessage(message));
|
||||
assertSame(converter, TestUtils.getPropertyValue(withConverterHandler, "converter"));
|
||||
assertSame(clientFactory, TestUtils.getPropertyValue(withConverterHandler, "clientFactory"));
|
||||
assertFalse(TestUtils.getPropertyValue(withConverterHandler, "async", Boolean.class));
|
||||
@@ -87,16 +99,17 @@ public class MqttOutboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void testWithDefaultConverter() {
|
||||
GenericMessage<String> message = new GenericMessage<>("foo");
|
||||
assertEquals("tcp://localhost:1883", TestUtils.getPropertyValue(withDefaultConverterHandler, "url"));
|
||||
assertEquals("foo", TestUtils.getPropertyValue(withDefaultConverterHandler, "clientId"));
|
||||
assertEquals("bar", TestUtils.getPropertyValue(withDefaultConverterHandler, "defaultTopic"));
|
||||
assertEquals(1, TestUtils.getPropertyValue(withDefaultConverterHandler, "defaultQos"));
|
||||
assertTrue(TestUtils.getPropertyValue(withDefaultConverterHandler, "defaultRetained", Boolean.class));
|
||||
MqttMessageConverter defaultConverter = TestUtils.getPropertyValue(withDefaultConverterHandler, "converter",
|
||||
MqttMessageConverter.class);
|
||||
assertTrue(defaultConverter instanceof DefaultPahoMessageConverter);
|
||||
assertEquals(1, TestUtils.getPropertyValue(defaultConverter, "defaultQos"));
|
||||
assertTrue(TestUtils.getPropertyValue(defaultConverter, "defaultRetained", Boolean.class));
|
||||
assertEquals(Boolean.TRUE,
|
||||
TestUtils.getPropertyValue(withDefaultConverterHandler, "defaultRetained", Boolean.class));
|
||||
DefaultPahoMessageConverter defaultConverter = TestUtils.getPropertyValue(withDefaultConverterHandler,
|
||||
"converter", DefaultPahoMessageConverter.class);
|
||||
assertEquals(1, defaultConverter.fromMessage(message, null).getQos());
|
||||
assertTrue(defaultConverter.fromMessage(message, null).isRetained());
|
||||
assertSame(clientFactory, TestUtils.getPropertyValue(withDefaultConverterHandler, "clientFactory"));
|
||||
assertTrue(TestUtils.getPropertyValue(withDefaultConverterHandler, "async", Boolean.class));
|
||||
assertTrue(TestUtils.getPropertyValue(withDefaultConverterHandler, "asyncEvents", Boolean.class));
|
||||
|
||||
Reference in New Issue
Block a user