/* * Copyright 2013-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.xd.integration.reactor; import static org.junit.Assert.*; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; import org.springframework.integration.channel.PublishSubscribeChannel; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.SocketUtils; import org.springframework.validation.BindException; import org.springframework.xd.integration.reactor.net.ReactorPeerInboundChannelAdapterConfiguration; import org.springframework.xd.integration.reactor.net.ReactorNetSourceOptionsMetadata; import org.springframework.xd.module.options.PojoModuleOptionsMetadata; /** * @author Jon Brisbin */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = NetServerInboundChannelAdapterIntegrationTests.BaseConfig.class) public class NetServerInboundChannelAdapterIntegrationTests { @Autowired Executor executor; @Autowired PublishSubscribeChannel output; @Autowired StringWriter writer; @Test public void netServerIngestsMessages() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(2); output.subscribe(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { if ("Hello World!".equals(message.getPayload())) { latch.countDown(); } } }); executor.execute(writer); assertTrue("latch was counted down", latch.await(5, TimeUnit.SECONDS)); } @Configuration static class TestConfig { int port = SocketUtils.findAvailableTcpPort(); @Bean public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws BindException { PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer(); MutablePropertySources ps = new MutablePropertySources(); ps.addFirst(optionsMetadataPropertySource()); pspc.setPropertySources(ps); return pspc; } @Bean public PropertySource<?> optionsMetadataPropertySource() throws BindException { Map<String, String> opts = new HashMap<String, String>(); opts.put("port", String.valueOf(port)); return new PojoModuleOptionsMetadata(ReactorNetSourceOptionsMetadata.class) .interpolate(opts) .asPropertySource(); } @Bean public StringWriter writer() { return new StringWriter(port); } @Bean public Executor executor() { return Executors.newCachedThreadPool(); } @Bean public PublishSubscribeChannel output() { return new PublishSubscribeChannel(); } @Bean public PublishSubscribeChannel errorChannel() { return new PublishSubscribeChannel(); } } @Configuration @Import({ TestConfig.class, ReactorPeerInboundChannelAdapterConfiguration.class }) static class BaseConfig { } static class StringWriter implements Runnable { final String line = "Hello World!\n"; final int port; StringWriter(int port) { this.port = port; } @Override public void run() { try { InetSocketAddress connectAddr = new InetSocketAddress("127.0.0.1", port); SocketChannel ch = SocketChannel.open(); ch.configureBlocking(true); ch.connect(connectAddr); ch.write(ByteBuffer.wrap(line.getBytes())); ch.write(ByteBuffer.wrap(line.getBytes())); ch.close(); } catch (IOException e) { throw new IllegalStateException(e); } } } }