INT-3468 MQTT Async Client
JIRA: https://jira.spring.io/browse/INT-3468 Provide an option to not block when sending and emit events for sends and delivery confirmations. Also use the async client for the inbound adapter; while it doesn't make any performance difference, it does allow us to timeout the disconnect, which we have seen to cause hangs on the CI servers. INT-3468 Polishing - Use Events; Add Docs INT-3468 Doc Polishing INT-3468 More Polishing - PR Comments - Only emit delivered event if async - Add clientId and a new instance counter to events INT-3468 Polishing - Pull client instance up to the abstract class and remove references to the Paho implementation from the events - Improve tests to include a second client INT-3468 Fix Test Case Incorrect classname meant the default location for the application context config was not found on case-sensitive file systems. Also, don't auto-start the adapters in the context, in case the broker is not running. INT-3468: Polishing INT-3468 Fix Package Tangle; Add 'async-events' Add an option (default false) to emit events when async is true.
This commit is contained in:
committed by
Artem Bilan
parent
95d81d4949
commit
dcdaafc075
@@ -7,7 +7,7 @@
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/mqtt http://www.springframework.org/schema/integration/mqtt/spring-integration-mqtt.xsd">
|
||||
|
||||
<int-mqtt:outbound-channel-adapter id="out" client-id="multiOut"
|
||||
<int-mqtt:outbound-channel-adapter id="out" client-id="multiOut"
|
||||
client-factory="multiUriClientFactory"
|
||||
default-topic="multiServerTests" />
|
||||
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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
|
||||
*
|
||||
* http://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.integration.mqtt;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.event.MqttMessageDeliveredEvent;
|
||||
import org.springframework.integration.mqtt.event.MqttMessageSentEvent;
|
||||
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class BackToBackAdapterTests {
|
||||
|
||||
@ClassRule
|
||||
public static final BrokerRunning brokerRunning = BrokerRunning.isRunning(1883);
|
||||
|
||||
@Autowired
|
||||
private MessageChannel out;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel in;
|
||||
|
||||
@Test
|
||||
public void testSingleTopic() {
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out");
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
MqttPahoMessageDrivenChannelAdapter inbound = new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883",
|
||||
"si-test-in", "mqtt-foo");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
adapter.handleMessage(new GenericMessage<String>("foo"));
|
||||
adapter.stop();
|
||||
Message<?> out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoTopics() {
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out");
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
MqttPahoMessageDrivenChannelAdapter inbound = new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883",
|
||||
"si-test-in", "mqtt-foo", "mqtt-bar");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
adapter.handleMessage(new GenericMessage<String>("foo"));
|
||||
Message<?> message = MessageBuilder.withPayload("bar").setHeader(MqttHeaders.TOPIC, "mqtt-bar").build();
|
||||
adapter.handleMessage(message);
|
||||
adapter.stop();
|
||||
Message<?> out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("bar", out.getPayload());
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsync() throws Exception {
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out");
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.setAsync(true);
|
||||
adapter.setAsyncEvents(true);
|
||||
EventPublisher publisher = new EventPublisher();
|
||||
adapter.setApplicationEventPublisher(publisher);
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
MqttPahoMessageDrivenChannelAdapter inbound =
|
||||
new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "si-test-in", "mqtt-foo");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
adapter.handleMessage(message);
|
||||
verifyEvents(adapter, publisher, message);
|
||||
adapter.stop();
|
||||
Message<?> out = outputChannel.receive(10000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncPersisted() throws Exception {
|
||||
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
|
||||
String tmpDir = System.getProperty("java.io.tmpdir") + File.separator + "mqtt_persist";
|
||||
new File(tmpDir).mkdirs();
|
||||
MqttClientPersistence persistence = new MqttDefaultFilePersistence(tmpDir);
|
||||
factory.setPersistence(persistence);
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out", factory);
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.setAsync(true);
|
||||
adapter.setAsyncEvents(true);
|
||||
adapter.setDefaultQos(1);
|
||||
EventPublisher publisher1 = new EventPublisher();
|
||||
adapter.setApplicationEventPublisher(publisher1);
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
|
||||
MqttPahoMessageDrivenChannelAdapter inbound =
|
||||
new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "si-test-in", "mqtt-foo", "mqtt-bar");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
Message<String> message1 = new GenericMessage<String>("foo");
|
||||
adapter.handleMessage(message1);
|
||||
verifyEvents(adapter, publisher1, message1);
|
||||
|
||||
Message<String> message2 = MessageBuilder.withPayload("bar")
|
||||
.setHeader(MqttHeaders.TOPIC, "mqtt-bar")
|
||||
.build();
|
||||
EventPublisher publisher2 = new EventPublisher();
|
||||
adapter.setApplicationEventPublisher(publisher2);
|
||||
adapter.handleMessage(message2);
|
||||
verifyEvents(adapter, publisher2, message2);
|
||||
|
||||
verifyMessageIds(publisher1, publisher2);
|
||||
int clientInstance = publisher1.delivered.getClientInstance();
|
||||
|
||||
adapter.stop();
|
||||
adapter.start(); // new client instance
|
||||
|
||||
publisher1 = new EventPublisher();
|
||||
adapter.setApplicationEventPublisher(publisher1);
|
||||
adapter.handleMessage(message1);
|
||||
verifyEvents(adapter, publisher1, message1);
|
||||
|
||||
publisher2 = new EventPublisher();
|
||||
adapter.setApplicationEventPublisher(publisher2);
|
||||
adapter.handleMessage(message2);
|
||||
verifyEvents(adapter, publisher2, message2);
|
||||
|
||||
verifyMessageIds(publisher1, publisher2);
|
||||
|
||||
assertNotEquals(clientInstance, publisher1.delivered.getClientInstance());
|
||||
adapter.stop();
|
||||
|
||||
Message<?> out = null;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
out = outputChannel.receive(10000);
|
||||
assertNotNull(out);
|
||||
if ("foo".equals(out.getPayload())) {
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
}
|
||||
else if ("bar".equals(out.getPayload())) {
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
}
|
||||
else {
|
||||
fail("unexpected payload " + out.getPayload());
|
||||
}
|
||||
}
|
||||
inbound.stop();
|
||||
}
|
||||
|
||||
private void verifyEvents(MqttPahoMessageHandler adapter, EventPublisher publisher1, Message<String> message1)
|
||||
throws InterruptedException {
|
||||
assertTrue(publisher1.latch.await(10, TimeUnit.SECONDS));
|
||||
assertNotNull(publisher1.sent);
|
||||
assertNotNull(publisher1.delivered);
|
||||
assertEquals(publisher1.sent.getMessageId(), publisher1.delivered.getMessageId());
|
||||
assertEquals(adapter.getClientId(), publisher1.sent.getClientId());
|
||||
assertEquals(adapter.getClientId(), publisher1.delivered.getClientId());
|
||||
assertEquals(adapter.getClientInstance(), publisher1.sent.getClientInstance());
|
||||
assertEquals(adapter.getClientInstance(), publisher1.delivered.getClientInstance());
|
||||
assertSame(message1, publisher1.sent.getMessage());
|
||||
}
|
||||
|
||||
private void verifyMessageIds(EventPublisher publisher1, EventPublisher publisher2) {
|
||||
assertNotEquals(publisher1.delivered.getMessageId(), publisher2.delivered.getMessageId());
|
||||
assertEquals(publisher1.delivered.getClientId(), publisher2.delivered.getClientId());
|
||||
assertEquals(publisher1.delivered.getClientInstance(), publisher2.delivered.getClientInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiURIs() {
|
||||
out.send(new GenericMessage<String>("foo"));
|
||||
Message<?> message = in.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("foo", message.getPayload());
|
||||
}
|
||||
|
||||
private class EventPublisher implements ApplicationEventPublisher {
|
||||
|
||||
private volatile MqttMessageDeliveredEvent delivered;
|
||||
|
||||
private MqttMessageSentEvent sent;
|
||||
|
||||
private final CountDownLatch latch = new CountDownLatch(2);
|
||||
|
||||
@Override
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
if (event instanceof MqttMessageSentEvent) {
|
||||
this.sent = (MqttMessageSentEvent) event;
|
||||
}
|
||||
else if (event instanceof MqttMessageDeliveredEvent){
|
||||
this.delivered = (MqttMessageDeliveredEvent) event;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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
|
||||
*
|
||||
* http://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.integration.mqtt;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
@Ignore //TODO transiently
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class BackTobackAdapterTests {
|
||||
|
||||
@Rule
|
||||
public final BrokerRunning brokerRunning = BrokerRunning.isRunning(1883);
|
||||
|
||||
@Autowired
|
||||
public MessageChannel out;
|
||||
|
||||
@Autowired
|
||||
public PollableChannel in;
|
||||
|
||||
@Test
|
||||
public void testSingleTopic() {
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out");
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
MqttPahoMessageDrivenChannelAdapter inbound = new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "si-test-in", "mqtt-foo");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
adapter.handleMessage(new GenericMessage<String>("foo"));
|
||||
adapter.stop();
|
||||
Message<?> out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoTopics() {
|
||||
MqttPahoMessageHandler adapter = new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out");
|
||||
adapter.setDefaultTopic("mqtt-foo");
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
MqttPahoMessageDrivenChannelAdapter inbound = new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "si-test-in", "mqtt-foo", "mqtt-bar");
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
inbound.setOutputChannel(outputChannel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
inbound.setTaskScheduler(taskScheduler);
|
||||
inbound.setBeanFactory(mock(BeanFactory.class));
|
||||
inbound.afterPropertiesSet();
|
||||
inbound.start();
|
||||
adapter.handleMessage(new GenericMessage<String>("foo"));
|
||||
Message<?> message = MessageBuilder.withPayload("bar").setHeader(MqttHeaders.TOPIC, "mqtt-bar").build();
|
||||
adapter.handleMessage(message);
|
||||
adapter.stop();
|
||||
Message<?> out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("foo", out.getPayload());
|
||||
assertEquals("mqtt-foo", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
out = outputChannel.receive(1000);
|
||||
assertNotNull(out);
|
||||
inbound.stop();
|
||||
assertEquals("bar", out.getPayload());
|
||||
assertEquals("mqtt-bar", out.getHeaders().get(MqttHeaders.TOPIC));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiURIs() {
|
||||
out.send(new GenericMessage<String>("foo"));
|
||||
Message<?> message = in.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("foo", message.getPayload());
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
@@ -58,7 +57,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
@Ignore //TODO transiently
|
||||
public class DownstreamExceptionTests {
|
||||
|
||||
@ClassRule
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -34,10 +35,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttToken;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.junit.Test;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
@@ -107,25 +110,27 @@ public class MqttAdapterTests {
|
||||
factory.setWill(will);
|
||||
|
||||
factory = spy(factory);
|
||||
final MqttClient client = mock(MqttClient.class);
|
||||
doAnswer(new Answer<MqttClient>() {
|
||||
final MqttAsyncClient client = mock(MqttAsyncClient.class);
|
||||
doAnswer(new Answer<MqttAsyncClient>() {
|
||||
|
||||
@Override
|
||||
public MqttClient answer(InvocationOnMock invocation) throws Throwable {
|
||||
public MqttAsyncClient answer(InvocationOnMock invocation) throws Throwable {
|
||||
return client;
|
||||
}
|
||||
}).when(factory).getClientInstance(anyString(), anyString());
|
||||
}).when(factory).getAsyncClientInstance(anyString(), anyString());
|
||||
|
||||
MqttPahoMessageHandler handler = new MqttPahoMessageHandler("foo", "bar", factory);
|
||||
handler.setDefaultTopic("mqtt-foo");
|
||||
handler.setBeanFactory(mock(BeanFactory.class));
|
||||
handler.afterPropertiesSet();
|
||||
handler.start();
|
||||
|
||||
final MqttToken token = mock(MqttToken.class);
|
||||
final AtomicBoolean connectCalled = new AtomicBoolean();
|
||||
doAnswer(new Answer<Object>(){
|
||||
doAnswer(new Answer<MqttToken>(){
|
||||
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
public MqttToken answer(InvocationOnMock invocation) throws Throwable {
|
||||
MqttConnectOptions options = (MqttConnectOptions) invocation.getArguments()[0];
|
||||
assertEquals(23, options.getConnectionTimeout());
|
||||
assertEquals(45, options.getKeepAliveInterval());
|
||||
@@ -137,19 +142,22 @@ public class MqttAdapterTests {
|
||||
assertEquals("bar", new String(options.getWillMessage().getPayload()));
|
||||
assertEquals(2, options.getWillMessage().getQos());
|
||||
connectCalled.set(true);
|
||||
return null;
|
||||
return token;
|
||||
}
|
||||
}).when(client).connect(any(MqttConnectOptions.class));
|
||||
doReturn(token).when(client).subscribe(any(String[].class), any(int[].class));
|
||||
|
||||
final MqttDeliveryToken deliveryToken = mock(MqttDeliveryToken.class);
|
||||
final AtomicBoolean publishCalled = new AtomicBoolean();
|
||||
doAnswer(new Answer<Object>() {
|
||||
doAnswer(new Answer<MqttDeliveryToken>() {
|
||||
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
public MqttDeliveryToken answer(InvocationOnMock invocation) throws Throwable {
|
||||
assertEquals("mqtt-foo", invocation.getArguments()[0]);
|
||||
MqttMessage message = (MqttMessage) invocation.getArguments()[1];
|
||||
assertEquals("Hello, world!", new String(message.getPayload()));
|
||||
publishCalled.set(true);
|
||||
return null;
|
||||
return deliveryToken;
|
||||
}
|
||||
}).when(client).publish(anyString(), any(MqttMessage.class));
|
||||
|
||||
@@ -177,15 +185,16 @@ public class MqttAdapterTests {
|
||||
factory.setWill(will);
|
||||
|
||||
factory = spy(factory);
|
||||
final MqttClient client = mock(MqttClient.class);
|
||||
doAnswer(new Answer<MqttClient>() {
|
||||
final MqttAsyncClient client = mock(MqttAsyncClient.class);
|
||||
doAnswer(new Answer<MqttAsyncClient>() {
|
||||
|
||||
@Override
|
||||
public MqttClient answer(InvocationOnMock invocation) throws Throwable {
|
||||
public MqttAsyncClient answer(InvocationOnMock invocation) throws Throwable {
|
||||
return client;
|
||||
}
|
||||
}).when(factory).getClientInstance(anyString(), anyString());
|
||||
}).when(factory).getAsyncClientInstance(anyString(), anyString());
|
||||
|
||||
final MqttToken token = mock(MqttToken.class);
|
||||
final AtomicBoolean connectCalled = new AtomicBoolean();
|
||||
doAnswer(new Answer<Object>() {
|
||||
|
||||
@@ -202,9 +211,10 @@ public class MqttAdapterTests {
|
||||
assertEquals("bar", new String(options.getWillMessage().getPayload()));
|
||||
assertEquals(2, options.getWillMessage().getQos());
|
||||
connectCalled.set(true);
|
||||
return null;
|
||||
return token;
|
||||
}
|
||||
}).when(client).connect(any(MqttConnectOptions.class));
|
||||
doReturn(token).when(client).subscribe(any(String[].class), any(int[].class));
|
||||
|
||||
final AtomicReference<MqttCallback> callback = new AtomicReference<MqttCallback>();
|
||||
doAnswer(new Answer<Object>() {
|
||||
|
||||
@@ -28,6 +28,19 @@
|
||||
client-id="foo"
|
||||
url="tcp://localhost:1883"
|
||||
topics="bar, baz"
|
||||
qos="0, 2"
|
||||
converter="myConverter"
|
||||
client-factory="clientFactory"
|
||||
send-timeout="123"
|
||||
channel="out" />
|
||||
|
||||
<int-mqtt:message-driven-channel-adapter id="twoTopicsSingleQosAdapter"
|
||||
auto-startup="false"
|
||||
phase="25"
|
||||
client-id="foo"
|
||||
url="tcp://localhost:1883"
|
||||
topics="bar, baz"
|
||||
qos="0"
|
||||
converter="myConverter"
|
||||
client-factory="clientFactory"
|
||||
send-timeout="123"
|
||||
|
||||
@@ -46,6 +46,9 @@ public class MqttMessageDrivenChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private MqttPahoMessageDrivenChannelAdapter twoTopicsAdapter;
|
||||
|
||||
@Autowired
|
||||
private MqttPahoMessageDrivenChannelAdapter twoTopicsSingleQosAdapter;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel out;
|
||||
|
||||
@@ -65,6 +68,7 @@ public class MqttMessageDrivenChannelAdapterParserTests {
|
||||
assertEquals(25, TestUtils.getPropertyValue(oneTopicAdapter, "phase"));
|
||||
assertEquals("foo", TestUtils.getPropertyValue(oneTopicAdapter, "clientId"));
|
||||
assertEquals("bar", TestUtils.getPropertyValue(oneTopicAdapter, "topic", String[].class)[0]);
|
||||
assertEquals(1, TestUtils.getPropertyValue(oneTopicAdapter, "qos", int[].class)[0]);
|
||||
assertSame(converter, TestUtils.getPropertyValue(oneTopicAdapter, "converter"));
|
||||
assertEquals(123L, TestUtils.getPropertyValue(oneTopicAdapter, "messagingTemplate.sendTimeout"));
|
||||
assertSame(out, TestUtils.getPropertyValue(oneTopicAdapter, "outputChannel"));
|
||||
@@ -74,16 +78,26 @@ public class MqttMessageDrivenChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void testTwoTopics() {
|
||||
assertEquals("tcp://localhost:1883", TestUtils.getPropertyValue(oneTopicAdapter, "url"));
|
||||
assertEquals("tcp://localhost:1883", TestUtils.getPropertyValue(twoTopicsAdapter, "url"));
|
||||
assertFalse(TestUtils.getPropertyValue(twoTopicsAdapter, "autoStartup", Boolean.class));
|
||||
assertEquals(25, TestUtils.getPropertyValue(twoTopicsAdapter, "phase"));
|
||||
assertEquals("foo", TestUtils.getPropertyValue(twoTopicsAdapter, "clientId"));
|
||||
assertEquals("bar", TestUtils.getPropertyValue(twoTopicsAdapter, "topic", String[].class)[0]);
|
||||
assertEquals("baz", TestUtils.getPropertyValue(twoTopicsAdapter, "topic", String[].class)[1]);
|
||||
assertEquals(0, TestUtils.getPropertyValue(twoTopicsAdapter, "qos", int[].class)[0]);
|
||||
assertEquals(2, TestUtils.getPropertyValue(twoTopicsAdapter, "qos", int[].class)[1]);
|
||||
assertSame(converter, TestUtils.getPropertyValue(twoTopicsAdapter, "converter"));
|
||||
assertEquals(123L, TestUtils.getPropertyValue(twoTopicsAdapter, "messagingTemplate.sendTimeout"));
|
||||
assertSame(out, TestUtils.getPropertyValue(twoTopicsAdapter, "outputChannel"));
|
||||
assertSame(clientFactory, TestUtils.getPropertyValue(twoTopicsAdapter, "clientFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoTopicsSingleQos() {
|
||||
assertEquals("bar", TestUtils.getPropertyValue(twoTopicsSingleQosAdapter, "topic", String[].class)[0]);
|
||||
assertEquals("baz", TestUtils.getPropertyValue(twoTopicsSingleQosAdapter, "topic", String[].class)[1]);
|
||||
assertEquals(0, TestUtils.getPropertyValue(twoTopicsSingleQosAdapter, "qos", int[].class)[0]);
|
||||
assertEquals(0, TestUtils.getPropertyValue(twoTopicsSingleQosAdapter, "qos", int[].class)[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
client-factory="clientFactory"
|
||||
phase="25"
|
||||
order="1"
|
||||
async="true"
|
||||
async-events="true"
|
||||
channel="target" />
|
||||
|
||||
<bean id="myConverter" class="org.springframework.integration.mqtt.support.DefaultPahoMessageConverter" />
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package org.springframework.integration.mqtt.config.xml;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
@@ -70,6 +74,8 @@ public class MqttOutboundChannelAdapterParserTests {
|
||||
assertEquals("bar", TestUtils.getPropertyValue(withConverterHandler, "defaultTopic"));
|
||||
assertSame(converter, TestUtils.getPropertyValue(withConverterHandler, "converter"));
|
||||
assertSame(clientFactory, TestUtils.getPropertyValue(withConverterHandler, "clientFactory"));
|
||||
assertFalse(TestUtils.getPropertyValue(withConverterHandler, "async", Boolean.class));
|
||||
assertFalse(TestUtils.getPropertyValue(withConverterHandler, "asyncEvents", Boolean.class));
|
||||
|
||||
Object handler = TestUtils.getPropertyValue(this.withConverterEndpoint, "handler");
|
||||
|
||||
@@ -96,6 +102,8 @@ public class MqttOutboundChannelAdapterParserTests {
|
||||
assertEquals(1, TestUtils.getPropertyValue(defaultConverter, "defaultQos"));
|
||||
assertTrue(TestUtils.getPropertyValue(defaultConverter, "defaultRetained", Boolean.class));
|
||||
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