From 7b182b0de9073634d6f1b153192ba9ed543ed781 Mon Sep 17 00:00:00 2001 From: Gunnar Hillert Date: Mon, 29 Oct 2012 14:01:59 -0400 Subject: [PATCH] INTSAMPLES-23 - Add Splitter-Aggregator example For reference see: https://jira.springsource.org/browse/INTSAMPLES-23 --- README.md | 6 +- intermediate/pom.xml | 1 + .../splitter-aggregator-reaper/README.md | 50 +++++++++ .../splitter-aggregator-reaper/pom.xml | 101 +++++++++++++++++ .../splitteraggregator/AbstractCriteria.java | 26 +++++ .../splitteraggregator/CompositeCriteria.java | 34 ++++++ .../splitteraggregator/CompositeResult.java | 33 ++++++ .../samples/splitteraggregator/CriteriaA.java | 26 +++++ .../samples/splitteraggregator/CriteriaB.java | 26 +++++ .../samples/splitteraggregator/Main.java | 104 ++++++++++++++++++ .../samples/splitteraggregator/Result.java | 25 +++++ .../samples/splitteraggregator/SearchA.java | 50 +++++++++ .../samples/splitteraggregator/SearchB.java | 50 +++++++++ .../SearchRequestSplitter.java | 31 ++++++ .../splitteraggregator/SearchRequestor.java | 28 +++++ .../SearchResultAggregator.java | 32 ++++++ .../splitteraggregator/support/TestUtils.java | 44 ++++++++ .../spring-integration-context.xml | 91 +++++++++++++++ .../src/main/resources/log4j.xml | 36 ++++++ .../TestSplitterAggregator.java | 81 ++++++++++++++ 20 files changed, 874 insertions(+), 1 deletion(-) create mode 100644 intermediate/splitter-aggregator-reaper/README.md create mode 100644 intermediate/splitter-aggregator-reaper/pom.xml create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/AbstractCriteria.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeCriteria.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeResult.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaA.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaB.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Main.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Result.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchA.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchB.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestSplitter.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestor.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchResultAggregator.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/support/TestUtils.java create mode 100644 intermediate/splitter-aggregator-reaper/src/main/resources/META-INF/spring/integration/spring-integration-context.xml create mode 100644 intermediate/splitter-aggregator-reaper/src/main/resources/log4j.xml create mode 100644 intermediate/splitter-aggregator-reaper/src/test/java/org/springframework/integration/samples/splitteraggregator/TestSplitterAggregator.java diff --git a/README.md b/README.md index 13066afa..7824df8e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Welcome to the Spring Integration Samples. To simplify your experience, Spring I * Advanced * Applications - Inside of each category you'll find a 'README.md' which will contain a more detailed description of that category's specifics. Each sample also comes with its own 'readme.txt' file explaining details. +Inside of each category you'll find a 'README.md' which will contain a more detailed description of that category's specifics. Each sample also comes with its own 'readme.txt' file explaining details. *Happy Integration!* @@ -70,6 +70,7 @@ This category targets developers who are already more familiar with the Spring I * **stored-procedures-oracle** Provides an example of the stored procedure Outbound Gateway using *ORACLE XE* * **stored-procedures-postgresql** Provides an example of the stored procedure Outbound Gateway using *[PostgreSQL](http://www.postgresql.org/)* * **rest-http** - This sample demonstrates how to send an HTTP request to a Spring Integration's HTTP service while utilizing Spring Integration's new HTTP Path usage. This sample also uses Spring Security for HTTP Basic authentication. With HTTP Path facility, the client program can send requests with URL Variables. +* **splitter-aggregator-reaper** A demonstration of implementing the Splitter and Aggregator *Enterprise Integration Patterns* (EIP) together. This sample also provides a concrete example of a [message store reaper][] in action. * **stored-procedures-derby** Provides an example of the stored procedure Outbound Gateway using *[Apache Derby](http://db.apache.org/derby/)* * **stored-procedures-oracle** Provides an example of the stored procedure Outbound Gateway using *ORACLE XE* * **monitoring** The project used in the *[Spring Integration Management and Monitoring Webinar](http://www.springsource.org/node/3598)* Also available on the *[SpringSourceDev YouTube Channel](http://www.youtube.com/SpringSourceDev)* @@ -94,8 +95,11 @@ This category targets developers and architects who have a good understanding of For more information, please visit the Spring Integration website at: [http://www.springsource.org/spring-integration](http://www.springsource.org/spring-integration) +[Spring Integration]: https://github.com/SpringSource/spring-integration [Spring Integration Extensions]: https://github.com/SpringSource/spring-integration-extensions [Spring Integration Templates]: https://github.com/SpringSource/spring-integration-templates/tree/master/si-sts-templates [Spring Integration Dsl Groovy]: https://github.com/SpringSource/spring-integration-dsl-groovy [Spring Integration Dsl Scala]: https://github.com/SpringSource/spring-integration-dsl-scala [Spring Integration Pattern Catalog]: https://github.com/SpringSource/spring-integration-pattern-catalog + +[message store reaper]: http://static.springsource.org/spring-integration/api/org/springframework/integration/store/MessageGroupStoreReaper.html diff --git a/intermediate/pom.xml b/intermediate/pom.xml index 5ff4ac00..70b847ae 100644 --- a/intermediate/pom.xml +++ b/intermediate/pom.xml @@ -14,6 +14,7 @@ errorhandling file-processing multipart-http + splitter-aggregator-reaper stored-procedures-derby tcp-client-server-multiplex travel diff --git a/intermediate/splitter-aggregator-reaper/README.md b/intermediate/splitter-aggregator-reaper/README.md new file mode 100644 index 00000000..57de1aba --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/README.md @@ -0,0 +1,50 @@ +Splitter/Aggregator with Reaper Sample +====================================== + +# Overview + +Demonstration of how to implement the Splitter/Aggregator [Enterprise Integration Patterns][] (EIP) using *Spring Integration*. This sample provides a demonstration of request-reply, [splitting][] a message, and then [aggregating][] the replies. Furthermore, this sample is processing the split messages concurrently and also deals with timeout conditions. Lastly, this sample provides a concrete example of a [message store reaper][] in action. + +# Run the Sample + +* running the "Main" class from within STS (Right-click on Main class --> Run As --> Java Application) +* or from the command line: + - mvn package + - mvn exec:java + +You should see the following output: + + 13:47:54.886 INFO [main][org.springframework.integration.samples.splitteraggregator.Main] + ========================================================= + + Welcome to Spring Integration! + + For more information please visit: + http://www.springsource.org/spring-integration + + ========================================================= + 13:47:56.039 INFO [main][org.springframework.integration.store.MessageGroupStoreReaper] started org.springframework.integration.store.MessageGroupStoreReaper@4b85c17 + Please enter a choice and press : + 1. Submit 2 search queries, 2 results returned. + 2. Submit 2 search queries, 1 search query takes too long, 1 results returned. + 3. Submit 2 search queries, 2 search queries take too long, 0 results returned. + q. Quit the application + Enter you choice: 1 + 13:48:01.036 INFO [searchRequestExecutor-2][org.springframework.integration.samples.splitteraggregator.SearchA] This search will take 1000ms. + 13:48:01.036 INFO [searchRequestExecutor-1][org.springframework.integration.samples.splitteraggregator.SearchB] This search will take 1000ms. + Number of Search Results: 2 + +# Credits + +We would like to thank Christopher Hunt ([@huntchr](http://twitter.com/huntchr)) for contributing this sample. + +-------------------------------------------------------------------------------- + +For help please take a look at the Spring Integration documentation: + +http://www.springsource.org/spring-integration + +[aggregating]: http://static.springsource.org/spring-integration/reference/html/messaging-routing-chapter.html#aggregator +[Enterprise Integration Patterns]: http://www.eaipatterns.com/ +[message store reaper]: http://static.springsource.org/spring-integration/reference/html/messaging-routing-chapter.html#aggregator-config +[splitting]: http://static.springsource.org/spring-integration/reference/html/messaging-routing-chapter.html#splitter \ No newline at end of file diff --git a/intermediate/splitter-aggregator-reaper/pom.xml b/intermediate/splitter-aggregator-reaper/pom.xml new file mode 100644 index 00000000..99f78d9c --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/pom.xml @@ -0,0 +1,101 @@ + + 4.0.0 + + org.springframework.integration.samples + splitter-aggregator-reaper + 2.2.0.BUILD-SNAPSHOT + jar + + Samples (Intermediate) - Splitter-Aggregator-Reaper + http://www.springsource.org/spring-integration + + A demonstration of implementing the Splitter and Aggregator Enterprise + Integration Patterns (EIP) together + + + + 2.2.1 + + + + UTF-8 + 2.2.0.RC2 + 1.2.16 + 4.10 + 1 + 3.1.2.RELEASE + + + + + repo.springsource.org.milestone + Spring Framework Maven Milestone Repository + https://repo.springsource.org/libs-milestone + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + -Xlint:all + true + true + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + org.springframework.integration.samples.splitteraggregator.Main + + + + + + + + + + + org.springframework.integration + spring-integration-core + ${spring.integration.version} + + + javax.inject + javax.inject + ${inject.version} + + + + + + log4j + log4j + ${log4j.version} + + + + + + junit + junit + ${junit.version} + test + + + + org.springframework + spring-test + ${spring.version} + + + \ No newline at end of file diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/AbstractCriteria.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/AbstractCriteria.java new file mode 100644 index 00000000..fa322068 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/AbstractCriteria.java @@ -0,0 +1,26 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +/** + * A class that represents all criteria. + * + * @author Christopher Hunt + * + */ +public abstract class AbstractCriteria { + +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeCriteria.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeCriteria.java new file mode 100644 index 00000000..2e07e4d7 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeCriteria.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Criteria that contains other criteria. + * + * @author Christopher Hunt + * + */ +public class CompositeCriteria extends AbstractCriteria { + + private final Collection criteria = new ArrayList(); + + public Collection getCriteria() { + return criteria; + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeResult.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeResult.java new file mode 100644 index 00000000..7ca65d85 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CompositeResult.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A result that can contain other results. + * + * @author Christopher Hunt + * + */ +public class CompositeResult extends Result { + private Collection results = new ArrayList(); + + public Collection getResults() { + return results; + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaA.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaA.java new file mode 100644 index 00000000..6823abbb --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaA.java @@ -0,0 +1,26 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +/** + * One type of criteria. + * + * @author Christopher Hunt + * + */ +public class CriteriaA extends AbstractCriteria { + +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaB.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaB.java new file mode 100644 index 00000000..919032ca --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/CriteriaB.java @@ -0,0 +1,26 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +/** + * Another type of criteria. + * + * @author Christopher Hunt + * + */ +public class CriteriaB extends AbstractCriteria { + +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Main.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Main.java new file mode 100644 index 00000000..d865e0c6 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Main.java @@ -0,0 +1,104 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import java.util.Scanner; + +import org.apache.log4j.Logger; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.samples.splitteraggregator.support.TestUtils; + + +/** + * Starts the Spring Context and will initialize the Spring Integration routes. + * + * @author Gunnar Hillert + * @version 1.0 + * + */ +public final class Main { + + private static final Logger LOGGER = Logger.getLogger(Main.class); + + private Main() { } + + /** + * Load the Spring Integration Application Context + * + * @param args - command line arguments + */ + public static void main(final String... args) { + + LOGGER.info("\n=========================================================" + + "\n " + + "\n Welcome to Spring Integration! " + + "\n " + + "\n For more information please visit: " + + "\n http://www.springsource.org/spring-integration " + + "\n " + + "\n=========================================================" ); + + final AbstractApplicationContext context = + new ClassPathXmlApplicationContext("classpath:META-INF/spring/integration/*-context.xml"); + + context.registerShutdownHook(); + + final SearchRequestor searchRequestor = context.getBean(SearchRequestor.class); + final SearchA searchA = context.getBean(SearchA.class); + final SearchB searchB = context.getBean(SearchB.class); + + final Scanner scanner = new Scanner(System.in); + + System.out.println("Please enter a choice and press : "); + System.out.println("\t1. Submit 2 search queries, 2 results returned."); + System.out.println("\t2. Submit 2 search queries, 1 search query takes too long, 1 result returned."); + System.out.println("\t3. Submit 2 search queries, 2 search queries take too long, 0 results returned."); + + System.out.println("\tq. Quit the application"); + System.out.print("Enter your choice: "); + + while (true) { + final String input = scanner.nextLine(); + + if("1".equals(input.trim())) { + searchA.setExecutionTime(1000L); + searchB.setExecutionTime(1000L); + final CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + System.out.println("Number of Search Results: " + result.getResults().size()); + } else if("2".equals(input.trim())) { + searchA.setExecutionTime(6000L); + searchB.setExecutionTime(1000L); + final CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + System.out.println("Number of Search Results: " + result.getResults().size()); + } else if("3".equals(input.trim())) { + searchA.setExecutionTime(6000L); + searchB.setExecutionTime(6000L); + final CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + System.out.println("Result is null: " + (result == null)); + } else if("q".equals(input.trim())) { + break; + } else { + System.out.println("Invalid choice\n\n"); + } + + } + + System.out.println("Exiting application...bye."); + System.exit(0); + + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Result.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Result.java new file mode 100644 index 00000000..7370c284 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/Result.java @@ -0,0 +1,25 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +/** + * The result for a search query. + * + * @author Christopher Hunt + * + */ +public class Result { +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchA.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchA.java new file mode 100644 index 00000000..0264b738 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchA.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import org.apache.log4j.Logger; + +/** + * One type of search. + * + * @author Christopher Hunt + * + */ +public class SearchA { + + private static final Logger LOGGER = Logger.getLogger(SearchA.class); + + private long executionTime = 1000L; + + public Result search(CriteriaA criteria) { + + LOGGER.info(String.format("This search will take %sms.", executionTime)); + + try { + Thread.sleep(executionTime); + } catch (InterruptedException e) { + } + return new Result(); + } + + public long getExecutionTime() { + return executionTime; + } + + public void setExecutionTime(long executionTime) { + this.executionTime = executionTime; + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchB.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchB.java new file mode 100644 index 00000000..7c7fc934 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchB.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import org.apache.log4j.Logger; + +/** + * Another type of search. + * + * @author Christopher Hunt + * + */ +public class SearchB { + + private static final Logger LOGGER = Logger.getLogger(SearchB.class); + + private long executionTime = 1000L; + + public Result search(CriteriaB criteria) { + + LOGGER.info(String.format("This search will take %sms.", executionTime)); + + try { + Thread.sleep(executionTime); + } catch (InterruptedException e) { + } + return new Result(); + } + + public long getExecutionTime() { + return executionTime; + } + + public void setExecutionTime(long executionTime) { + this.executionTime = executionTime; + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestSplitter.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestSplitter.java new file mode 100644 index 00000000..90d3d134 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestSplitter.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import java.util.Collection; + +/** + * Given CompositeCriteria, return a collection of the individual criterion. + * + * @author Christopher Hunt + * + */ +public class SearchRequestSplitter { + + public Collection split(CompositeCriteria criteria) { + return criteria.getCriteria(); + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestor.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestor.java new file mode 100644 index 00000000..380e28ed --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchRequestor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +/** + * A service interface responsible for performing a search and returning a + * result synchronously. + * + * @author Christopher Hunt + * + */ +public interface SearchRequestor { + + CompositeResult search(CompositeCriteria criteria); +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchResultAggregator.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchResultAggregator.java new file mode 100644 index 00000000..22fe2dfb --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/SearchResultAggregator.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import java.util.Collection; + +/** + * Aggregate a collection of results into a composite result object. + * + * @author Christopher Hunt + * + */ +public class SearchResultAggregator { + public Result aggregate(Collection results) { + CompositeResult result = new CompositeResult(); + result.getResults().addAll(results); + return result; + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/support/TestUtils.java b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/support/TestUtils.java new file mode 100644 index 00000000..92cad645 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/java/org/springframework/integration/samples/splitteraggregator/support/TestUtils.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2012 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.splitteraggregator.support; + +import org.springframework.integration.samples.splitteraggregator.CompositeCriteria; +import org.springframework.integration.samples.splitteraggregator.CriteriaA; +import org.springframework.integration.samples.splitteraggregator.CriteriaB; + + +/** + * @author Gunnar Hillert + * @since 1.0 + * + */ +public final class TestUtils { + + /** + * Private constructor to prevent instantiation. + */ + private TestUtils() { + } + + public static CompositeCriteria getCompositeCriteria() { + + final CompositeCriteria generalCriteria = new CompositeCriteria(); + generalCriteria.getCriteria().add(new CriteriaA()); + generalCriteria.getCriteria().add(new CriteriaB()); + return generalCriteria; + + } +} diff --git a/intermediate/splitter-aggregator-reaper/src/main/resources/META-INF/spring/integration/spring-integration-context.xml b/intermediate/splitter-aggregator-reaper/src/main/resources/META-INF/spring/integration/spring-integration-context.xml new file mode 100644 index 00000000..2ec88b76 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/resources/META-INF/spring/integration/spring-integration-context.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intermediate/splitter-aggregator-reaper/src/main/resources/log4j.xml b/intermediate/splitter-aggregator-reaper/src/main/resources/log4j.xml new file mode 100644 index 00000000..c9992aa8 --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/main/resources/log4j.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/intermediate/splitter-aggregator-reaper/src/test/java/org/springframework/integration/samples/splitteraggregator/TestSplitterAggregator.java b/intermediate/splitter-aggregator-reaper/src/test/java/org/springframework/integration/samples/splitteraggregator/TestSplitterAggregator.java new file mode 100644 index 00000000..48171dad --- /dev/null +++ b/intermediate/splitter-aggregator-reaper/src/test/java/org/springframework/integration/samples/splitteraggregator/TestSplitterAggregator.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2012 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.splitteraggregator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import javax.inject.Inject; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.integration.samples.splitteraggregator.support.TestUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration tests for the Scatter-Gather + * + * @author Christopher Hunt + * @author Gunnar Hillert + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"classpath:META-INF/spring/integration/spring-integration-context.xml"}) +public class TestSplitterAggregator { + + @Inject + SearchRequestor searchRequestor; + + @Inject + SearchA searchA; + + @Inject + SearchB searchB; + + /** + * Test the happy path. + * + * @throws InterruptedException + */ + @Test + public void testSearch() throws InterruptedException { + CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + assertEquals(2, result.getResults().size()); + } + + /** + * Test searchA taking longer than we're expecting. + */ + @Test + public void testSearchNoSearchA() { + searchA.setExecutionTime(6000L); + CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + assertEquals(1, result.getResults().size()); + } + + /** + * Test both searchA and searchB taking longer than we're expecting. + */ + @Test + public void testSearchNoSearchB() { + searchA.setExecutionTime(6000L); + searchB.setExecutionTime(6000L); + CompositeResult result = searchRequestor.search(TestUtils.getCompositeCriteria()); + assertNull(result); + } + +}