INT-4118: Detect EOF on stdin
JIRA: https://jira.spring.io/browse/INT-4118 Add an option to the `CharacterStreamReadingMessageSource` to detect EOF on the stream and close the context. Publish event instead of closing context. Polishing - PR Comments Polishing Docs about stopping the poller. * Fix typos in the docs
This commit is contained in:
committed by
Artem Bilan
parent
a7171c4db9
commit
f9ddefec2c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -17,16 +17,31 @@
|
||||
package org.springframework.integration.stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class CharacterStreamSourceTests {
|
||||
|
||||
@@ -40,4 +55,49 @@ public class CharacterStreamSourceTests {
|
||||
assertNull(message2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEOF() {
|
||||
StringReader reader = new StringReader("test");
|
||||
CharacterStreamReadingMessageSource source = new CharacterStreamReadingMessageSource(reader, -1, true);
|
||||
ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
|
||||
source.setApplicationEventPublisher(publisher);
|
||||
Message<?> message1 = source.receive();
|
||||
assertEquals("test", message1.getPayload());
|
||||
Message<?> message2 = source.receive();
|
||||
assertNull(message2);
|
||||
verify(publisher).publishEvent(any(StreamClosedEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEOFIntegrationTest() throws Exception {
|
||||
StringReader reader = new StringReader("test");
|
||||
CharacterStreamReadingMessageSource source = new CharacterStreamReadingMessageSource(reader, -1, true);
|
||||
SourcePollingChannelAdapter adapter = new SourcePollingChannelAdapter();
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
source.setApplicationEventPublisher(e -> {
|
||||
if (e instanceof StreamClosedEvent) {
|
||||
if (latch.getCount() == 1) {
|
||||
adapter.stop();
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
adapter.setSource(source);
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.afterPropertiesSet();
|
||||
adapter.setTaskScheduler(scheduler);
|
||||
adapter.setTrigger(new PeriodicTrigger(100));
|
||||
QueueChannel out = new QueueChannel();
|
||||
adapter.setOutputChannel(out);
|
||||
adapter.setBeanFactory(mock(BeanFactory.class));
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
Message<?> received = out.receive(10000);
|
||||
assertNotNull(received);
|
||||
assertEquals("test", received.getPayload());
|
||||
assertTrue(latch.await(10, TimeUnit.SECONDS));
|
||||
assertFalse(adapter.isRunning());
|
||||
scheduler.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,11 +36,13 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.support.context.NamedComponent;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class ConsoleInboundChannelAdapterParserTests {
|
||||
|
||||
@@ -54,8 +56,8 @@ public class ConsoleInboundChannelAdapterParserTests {
|
||||
public void adapterWithDefaultCharset() {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"consoleInboundChannelAdapterParserTests.xml", ConsoleInboundChannelAdapterParserTests.class);
|
||||
SourcePollingChannelAdapter adapter =
|
||||
(SourcePollingChannelAdapter) context.getBean("adapterWithDefaultCharset.adapter");
|
||||
SourcePollingChannelAdapter adapter = context.getBean("adapterWithDefaultCharset.adapter",
|
||||
SourcePollingChannelAdapter.class);
|
||||
MessageSource<?> source = (MessageSource<?>) new DirectFieldAccessor(adapter).getPropertyValue("source");
|
||||
assertTrue(source instanceof NamedComponent);
|
||||
assertEquals("adapterWithDefaultCharset.adapter", adapter.getComponentName());
|
||||
@@ -72,6 +74,9 @@ public class ConsoleInboundChannelAdapterParserTests {
|
||||
Message<?> message = source.receive();
|
||||
assertNotNull(message);
|
||||
assertEquals("foo", message.getPayload());
|
||||
adapter = context.getBean("pipedAdapterNoCharset.adapter", SourcePollingChannelAdapter.class);
|
||||
source = adapter.getMessageSource();
|
||||
assertTrue(TestUtils.getPropertyValue(source, "blockToDetectEOF", Boolean.class));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -79,12 +84,13 @@ public class ConsoleInboundChannelAdapterParserTests {
|
||||
public void adapterWithProvidedCharset() {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"consoleInboundChannelAdapterParserTests.xml", ConsoleInboundChannelAdapterParserTests.class);
|
||||
SourcePollingChannelAdapter adapter =
|
||||
(SourcePollingChannelAdapter) context.getBean("adapterWithProvidedCharset.adapter");
|
||||
MessageSource<?> source = (MessageSource<?>) new DirectFieldAccessor(adapter).getPropertyValue("source");
|
||||
SourcePollingChannelAdapter adapter = context.getBean("adapterWithProvidedCharset.adapter",
|
||||
SourcePollingChannelAdapter.class);
|
||||
MessageSource<?> source = adapter.getMessageSource();
|
||||
DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(source);
|
||||
Reader bufferedReader = (Reader) sourceAccessor.getPropertyValue("reader");
|
||||
assertEquals(BufferedReader.class, bufferedReader.getClass());
|
||||
assertEquals(false, sourceAccessor.getPropertyValue("blockToDetectEOF"));
|
||||
DirectFieldAccessor bufferedReaderAccessor = new DirectFieldAccessor(bufferedReader);
|
||||
Reader reader = (Reader) bufferedReaderAccessor.getPropertyValue("in");
|
||||
assertEquals(InputStreamReader.class, reader.getClass());
|
||||
@@ -93,6 +99,16 @@ public class ConsoleInboundChannelAdapterParserTests {
|
||||
Message<?> message = source.receive();
|
||||
assertNotNull(message);
|
||||
assertEquals("foo", message.getPayload());
|
||||
adapter = context.getBean("pipedAdapterWithCharset.adapter", SourcePollingChannelAdapter.class);
|
||||
source = adapter.getMessageSource();
|
||||
assertTrue(TestUtils.getPropertyValue(source, "blockToDetectEOF", Boolean.class));
|
||||
bufferedReader = (Reader) sourceAccessor.getPropertyValue("reader");
|
||||
assertEquals(BufferedReader.class, bufferedReader.getClass());
|
||||
bufferedReaderAccessor = new DirectFieldAccessor(bufferedReader);
|
||||
reader = (Reader) bufferedReaderAccessor.getPropertyValue("in");
|
||||
assertEquals(InputStreamReader.class, reader.getClass());
|
||||
readerCharset = Charset.forName(((InputStreamReader) reader).getEncoding());
|
||||
assertEquals(Charset.forName("UTF-8"), readerCharset);
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,17 @@
|
||||
http://www.springframework.org/schema/integration/stream
|
||||
http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd">
|
||||
|
||||
<integration:message-history/>
|
||||
<integration:message-history />
|
||||
|
||||
<stdin-channel-adapter id="adapterWithDefaultCharset" auto-startup="false"/>
|
||||
<stdin-channel-adapter id="adapterWithDefaultCharset" auto-startup="false" />
|
||||
|
||||
<stdin-channel-adapter id="adapterWithProvidedCharset" charset="UTF-8" auto-startup="false"/>
|
||||
<stdin-channel-adapter id="adapterWithProvidedCharset" charset="UTF-8" auto-startup="false" />
|
||||
|
||||
<integration:poller id="poller" default="true" fixed-rate="3000"/>
|
||||
<stdin-channel-adapter id="pipedAdapterNoCharset" auto-startup="false" detect-eof="true" />
|
||||
|
||||
<stdin-channel-adapter id="pipedAdapterWithCharset" charset="UTF-8" auto-startup="false"
|
||||
detect-eof="true" />
|
||||
|
||||
<integration:poller id="poller" default="true" fixed-rate="3000" />
|
||||
|
||||
</beans:beans>
|
||||
|
||||
Reference in New Issue
Block a user