/*
* Copyright 2002-2015 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.ip.udp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.core.DestinationResolver;
import org.springframework.messaging.support.GenericMessage;
/**
* Sends and receives a simple message through to the Udp channel adapters.
* If run as a JUnit just sends one message and terminates (see console).
*
* If run from main(),
* hangs around for a couple of minutes to allow console interaction - enter a message on the
* console and you should see it go through the outbound context, over UDP, and
* received in the other context (and written back to the console).
*
* @author Gary Russell
* @author Artem Bilan
* @author Gunnar Hillert
* @since 2.0
*/
public class UdpUnicastEndToEndTests implements Runnable {
private String testingIpText;
private Message<byte[]> finalMessage;
private CountDownLatch sentFirst = new CountDownLatch(1);
private CountDownLatch firstReceived = new CountDownLatch(1);
private CountDownLatch doneProcessing = new CountDownLatch(1);
private boolean okToRun = true;
private CountDownLatch readyToReceive = new CountDownLatch(1);
private volatile int receiverPort;
private static long hangAroundFor = 10;
@Before
public void setup() {
this.testingIpText = null;
this.finalMessage = null;
this.sentFirst = new CountDownLatch(1);
this.firstReceived = new CountDownLatch(1);
this.doneProcessing = new CountDownLatch(1);
this.okToRun = true;
this.readyToReceive = new CountDownLatch(1);
}
@Test
public void runIt() throws Exception {
String location = "org/springframework/integration/ip/udp/testIp-out-context.xml";
test(location);
}
@Test
public void tesUdpOutboundChannelAdapterWithinChain() throws Exception {
String location = "org/springframework/integration/ip/udp/testIp-out-within-chain-context.xml";
test(location);
}
private void test(String location) throws InterruptedException, Exception {
UdpUnicastEndToEndTests launcher = new UdpUnicastEndToEndTests();
Thread t = new Thread(launcher);
t.start(); // launch the receiver
int n = 0;
while (n++ < 100 && launcher.getReceiverPort() == 0) {
Thread.sleep(100);
}
assertTrue("Receiver failed to listen", n < 100);
ClassPathXmlApplicationContext applicationContext = createContext(launcher, location);
launcher.launchSender(applicationContext);
applicationContext.close();
}
private ClassPathXmlApplicationContext createContext(UdpUnicastEndToEndTests launcher, String location) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();
applicationContext.setConfigLocation(location);
StandardEnvironment env = new StandardEnvironment();
Properties props = new Properties();
props.setProperty("port", Integer.toString(launcher.getReceiverPort()));
PropertiesPropertySource pps = new PropertiesPropertySource("ftpprops", props);
env.getPropertySources().addLast(pps);
applicationContext.setEnvironment(env);
applicationContext.refresh();
return applicationContext;
}
public void launchSender(ApplicationContext applicationContext) throws Exception {
DestinationResolver<MessageChannel> channelResolver = new BeanFactoryChannelResolver(applicationContext);
MessageChannel inputChannel = channelResolver.resolveDestination("inputChannel");
if (!readyToReceive.await(30, TimeUnit.SECONDS)) {
fail("Receiver failed to start in 30s");
}
try {
testingIpText = ">>>>>>> Testing IP " + new Date();
inputChannel.send(new GenericMessage<String>(testingIpText));
sentFirst.countDown();
try {
Thread.sleep(hangAroundFor); // give some time for console interaction
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
finally {
if (hangAroundFor == 0) {
sentFirst = new CountDownLatch(1);
}
else {
okToRun = false;
}
// tell the receiver to we're done
doneProcessing.countDown();
}
assertTrue(firstReceived.await(5, TimeUnit.SECONDS));
assertEquals(testingIpText, new String(finalMessage.getPayload()));
}
public int getReceiverPort() {
return receiverPort;
}
/**
* Instantiate the receiving context
*/
@SuppressWarnings("unchecked")
@Override
public void run() {
@SuppressWarnings("resource")
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
"testIp-in-context.xml", UdpUnicastEndToEndTests.class);
UnicastReceivingChannelAdapter inbound = ctx.getBean(UnicastReceivingChannelAdapter.class);
int n = 0;
try {
while (!inbound.isListening()) {
Thread.sleep(100);
if (n++ > 100) {
throw new RuntimeException("Failed to start listening");
}
}
}
catch (RuntimeException e) {
throw e;
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("interrupted");
}
this.receiverPort = inbound.getPort();
while (okToRun) {
try {
readyToReceive.countDown();
sentFirst.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
QueueChannel channel = ctx.getBean("udpOutChannel", QueueChannel.class);
finalMessage = (Message<byte[]>) channel.receive();
MessageHistory history = MessageHistory.read(finalMessage);
Properties componentHistoryRecord = TestUtils.locateComponentInHistory(history, "udpReceiver", 0);
assertNotNull(componentHistoryRecord);
assertEquals("ip:udp-inbound-channel-adapter", componentHistoryRecord.get("type"));
firstReceived.countDown();
try {
doneProcessing.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
ctx.stop();
ctx.close();
}
public static void main(String[] args) throws Exception {
hangAroundFor = 120000;
new UdpUnicastEndToEndTests().runIt();
new UdpUnicastEndToEndTests().tesUdpOutboundChannelAdapterWithinChain();
}
}