diff --git a/.gitignore b/.gitignore
index 00723545..c39d1376 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,6 @@
application.log
+target/
+.settings/
+log.roo
+.project
+.classpath
diff --git a/advanced/advanced-testing-examples/pom.xml b/advanced/advanced-testing-examples/pom.xml
new file mode 100644
index 00000000..b5769975
--- /dev/null
+++ b/advanced/advanced-testing-examples/pom.xml
@@ -0,0 +1,126 @@
+
+
+ 4.0.0
+ org.springframework.integration.samples
+ advanced-testing-examples
+ 2.0.0
+ Spring Integration Advanced Testing Examples
+ jar
+
+ 2.0.5.RELEASE
+ 3.0.5.RELEASE
+ 1.2.16
+ 4.7
+
+
+
+ org.springframework.integration
+ spring-integration-jms
+ ${spring.integration.version}
+
+
+
+ org.springframework.integration
+ spring-integration-groovy
+ ${spring.integration.version}
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+
+ junit
+ junit
+ ${junit.version}
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+
+ org.springframework
+ spring-jms
+ ${spring.version}
+
+
+
+ org.apache.geronimo.specs
+ geronimo-jms_1.1_spec
+ 1.1.1
+ provided
+
+
+
+
+ org.mockito
+ mockito-all
+ 1.8.5
+ test
+
+
+
+
+
+
+ src/test/java
+
+ **/*
+
+
+ **/*.java
+
+
+
+ src/test/resources
+
+ **/*
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+ -Xlint:all
+ true
+ false
+
+
+
+ maven-surefire-plugin
+
+
+ **/*Tests.java
+
+
+
+
+
+
+
+ repository.springframework.maven.release
+ Spring Framework Maven Release Repository
+ http://maven.springframework.org/release
+
+
+ repository.springframework.maven.milestone
+ Spring Framework Maven Milestone Repository
+ http://maven.springframework.org/milestone
+
+
+ repository.springframework.maven.snapshot
+ Spring Framework Maven Snapshot Repository
+ http://maven.springframework.org/snapshot
+
+
+
\ No newline at end of file
diff --git a/advanced/advanced-testing-examples/readme.txt b/advanced/advanced-testing-examples/readme.txt
new file mode 100644
index 00000000..915b7c7f
--- /dev/null
+++ b/advanced/advanced-testing-examples/readme.txt
@@ -0,0 +1,14 @@
+Example test cases that show advanced techniques to test Spring Integration applications.
+
+For basic testing examples see basic/testing-examples
+
+Examples
+========
+...jms.JmsMockTests.java
+
+This test case shows how to test an integration flow that uses JMS inbound channel adapter
+by using Mockito to mock a JmsTemplate (and dependent JMS objects). The example flow in
+src/main/resources/integration-config.xml does not depend on JMS but includes some additional
+error handling on errorChannel. The errorChannel is configured on the JMS adapter. So
+We want test the entire flow for cases in which an invalid message is received via JMS and routed
+to errorChannel. How do we do this without requiring a JMS message broker?
\ No newline at end of file
diff --git a/advanced/advanced-testing-examples/src/main/resources/integration-config.xml b/advanced/advanced-testing-examples/src/main/resources/integration-config.xml
new file mode 100644
index 00000000..af6c98fc
--- /dev/null
+++ b/advanced/advanced-testing-examples/src/main/resources/integration-config.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests-context.xml b/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests-context.xml
new file mode 100644
index 00000000..a8132d53
--- /dev/null
+++ b/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests-context.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests.java b/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests.java
new file mode 100644
index 00000000..a1d9edc7
--- /dev/null
+++ b/advanced/advanced-testing-examples/src/test/java/org/springframework/integration/samples/advance/testing/jms/JmsMockTests.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2002-2011 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.samples.advance.testing.jms;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.JMSException;
+import javax.jms.TextMessage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.Message;
+import org.springframework.integration.MessageChannel;
+import org.springframework.integration.MessagingException;
+import org.springframework.integration.core.MessageHandler;
+import org.springframework.integration.core.SubscribableChannel;
+
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class JmsMockTests {
+
+ @Autowired
+ JmsTemplate mockJmsTemplate;
+
+ @Autowired
+ @Qualifier("inputChannel")
+ MessageChannel inputChannel;
+
+ @Autowired
+ @Qualifier("outputChannel")
+ SubscribableChannel outputChannel;
+
+ @Autowired
+ @Qualifier("invalidMessageChannel")
+ SubscribableChannel invalidMessageChannel;
+
+
+ /**
+ * This test verifies that a message received on a polling JMS inbound channel adapter is
+ * routed to the designated channel and that the message payload is as expected
+ *
+ * @throws JMSException
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ @Test
+ public void testReceiveMessage() throws JMSException, InterruptedException, IOException {
+ String msg = "hello";
+
+ boolean sent = verifyJmsMessageReceivedOnOutputChannel(msg, outputChannel,new CountDownHandler() {
+
+ @Override
+ protected void verifyMessage(Message> message) {
+ assertEquals("hello",message.getPayload());
+ }
+ }
+ );
+ assertTrue("message not sent to expected output channel", sent);
+ }
+
+ /**
+ * This test verifies that a message received on a polling JMS inbound channel adapter is
+ * routed to the errorChannel and that the message payload is the expected exception
+ *
+ * @throws JMSException
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ @Test
+ public void testReceiveInvalidMessage() throws JMSException, IOException, InterruptedException {
+ String msg = "whoops";
+ boolean sent = verifyJmsMessageReceivedOnOutputChannel(msg, invalidMessageChannel,new CountDownHandler() {
+
+ @Override
+ protected void verifyMessage(Message> message) {
+ assertEquals("invalid payload",message.getPayload());
+ }
+
+ }
+ );
+ assertTrue("message not sent to expected output channel", sent);
+ }
+
+ /**
+ * Provide a message via a mock JMS template and wait for the default timeout to receive the message on the expected channel
+ * @param obj The message provided to the poller (currently must be a String)
+ * @param expectedOutputChannel The expected output channel
+ * @param handler An instance of CountDownHandler to handle (verify) the output message
+ * @return true if the message was received on the expected channel
+ * @throws JMSException
+ * @throws InterruptedException
+ */
+ protected boolean verifyJmsMessageReceivedOnOutputChannel(Object obj, SubscribableChannel expectedOutputChannel, CountDownHandler handler) throws JMSException, InterruptedException{
+ return verifyJmsMessageOnOutputChannel(obj, expectedOutputChannel, handler, 5000);
+ }
+
+
+ /**
+ * Provide a message via a mock JMS template and wait for the specified timeout to receive the message on the expected channel
+ * @param obj The message provided to the poller (currently must be a String)
+ * @param expectedOutputChannel The expected output channel
+ * @param handler An instance of CountDownHandler to handle (verify) the output message
+ * @param timeoutMillisec The timeout period. Note that this must allow at least enough time to process the entire flow. Only set if the default is
+ * not long enough
+ * @return true if the message was received on the expected channel
+ * @throws JMSException
+ * @throws InterruptedException
+ */
+ protected boolean verifyJmsMessageOnOutputChannel(Object obj, SubscribableChannel expectedOutputChannel, CountDownHandler handler,int timeoutMillisec) throws JMSException,
+ InterruptedException {
+
+ if (!(obj instanceof String)) {
+ throw new IllegalArgumentException("Only TextMessage is currently supported");
+ }
+
+ /*
+ * Use mocks to create a message returned to the JMS inbound adapter. It is assumed that the JmsTemplate
+ * is also a mock.
+ */
+
+ TextMessage message = mock(TextMessage.class);
+ doReturn(new SimpleMessageConverter()).when(mockJmsTemplate).getMessageConverter();
+ doReturn(message).when(mockJmsTemplate).receiveSelected(anyString());
+
+ String text = (String) obj;
+
+ CountDownLatch latch = new CountDownLatch(1);
+ handler.setLatch(latch);
+
+ doReturn(text).when(message).getText();
+
+ expectedOutputChannel.subscribe(handler);
+
+ return latch.await(timeoutMillisec, TimeUnit.MILLISECONDS);
+
+
+ }
+ /*
+ * A MessageHandler that uses a CountDownLatch to syncronize with the calling thread
+ */
+ private abstract class CountDownHandler implements MessageHandler {
+
+ CountDownLatch latch;
+
+ public final void setLatch(CountDownLatch latch){
+ this.latch = latch;
+ }
+
+ protected abstract void verifyMessage(Message> message);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.integration.core.MessageHandler#handleMessage
+ * (org.springframework.integration.Message)
+ */
+ public void handleMessage(Message> message) throws MessagingException {
+ verifyMessage(message);
+ latch.countDown();
+ }
+ }
+}
diff --git a/advanced/advanced-testing-examples/src/test/resources/log4j.xml b/advanced/advanced-testing-examples/src/test/resources/log4j.xml
new file mode 100644
index 00000000..4425c96a
--- /dev/null
+++ b/advanced/advanced-testing-examples/src/test/resources/log4j.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/advanced/pom.xml b/advanced/pom.xml
new file mode 100644
index 00000000..5f99fe3a
--- /dev/null
+++ b/advanced/pom.xml
@@ -0,0 +1,16 @@
+
+
+
+ 4.0.0
+ org.springframework.integration.samples
+ advanced-samples
+ 2.0.0
+ Advanced Spring Integration Samples
+ pom
+
+
+ advanced-testing-examples
+
+
+
diff --git a/advanced/readme.txt b/advanced/readme.txt
index b8a98c94..c853efbd 100644
--- a/advanced/readme.txt
+++ b/advanced/readme.txt
@@ -1,11 +1,11 @@
$$ ADVANCED Samples $$
-This category targets advanced develoopers who are well familiar with Spring Integration framework but looking to
+This category targets advanced developers who are well familiar with Spring Integration framework but looking to
extend it to address a specific custom need by extending from Spring Integration public API.
For example; if you are looking for samples showing you how to implement a custom Channel or
Consumer (event-based or polling-based), or you trying to figure out what is the most appropriate way to implement
-custom BeanParser on top of Spring IntegrationÊBeanParserÊhierarchy when implementing custom name space,
+custom BeanParser on top of Spring Integration�BeanParser�hierarchy when implementing custom name space,
this would be the right place to look.
Here you can also find samples that will help you with adapter development. Spring Integration comes with an extensive
library of adapters that allow you to connect remote systems with Spring Integration messaging framework.