Spring Integration Samples
-
- Starting with the current release of Spring Integration the samples are distributed as independent
- Maven-based projects (http://maven.apache.org/) to minimize the setup time.
- Since each project is also an Eclipse-based project, they can be imported as is using the Eclipse Import wizard.
- If you prefer another IDE, configuration should be very trivial, since a special Maven profile was setup to download all
- of the required dependencies for all samples. Detailed instructions on how to build and run the samples are provided in
- the README.txt file located in the samples directory of the main distribution.
-
-
-
- The Cafe Sample
-
- In this section, we will review a sample application that is included in the Spring Integration
- distribution. This sample is inspired by one of the samples featured in Gregor Hohpe's
- Ramblings.
-
-
- The domain is that of a Cafe, and the basic flow is depicted in the following diagram:
-
-
-
-
-
-
-
-
-
-
-
-
- The Order object may contain multiple OrderItems. Once the order
- is placed, a Splitter will break the composite order message into a single message per
- drink. Each of these is then processed by a Router that determines whether the drink is hot
- or cold (checking the OrderItem object's 'isIced' property). The
- Barista prepares each drink, but hot and cold drink preparation are handled by two
- distinct methods: 'prepareHotDrink' and 'prepareColdDrink'. The prepared drinks are then sent to the Waiter where
- they are aggregated into a Delivery object.
-
-
- Here is the XML configuration:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
- As you can see, each Message Endpoint is connected to input and/or output channels. Each endpoint will manage
- its own Lifecycle (by default endpoints start automatically upon initialization - to prevent that add the
- "auto-startup" attribute with a value of "false"). Most importantly, notice that the objects are simple POJOs
- with strongly typed method arguments. For example, here is the Splitter:
- split(Order order) {
- return order.getItems();
- }
-}]]>
- In the case of the Router, the return value does not have to be a MessageChannel
- instance (although it can be). As you see in this example, a String-value representing the channel name is
- returned instead.
-
-
-
- Now turning back to the XML, you see that there are two <service-activator> elements. Each of these
- is delegating to the same Barista instance but different methods: 'prepareHotDrink'
- or 'prepareColdDrink' corresponding to the two channels where order items have been routed.
-
-
-
- As you can see from the code excerpt above, the barista methods have different delays (the hot drinks take 5
- times as long to prepare). This simulates work being completed at different rates. When the
- CafeDemo 'main' method runs, it will loop 100 times sending a single hot drink and a
- single cold drink each time. It actually sends the messages by invoking the 'placeOrder' method on the Cafe
- interface. Above, you will see that the <gateway> element is specified in the configuration file. This
- triggers the creation of a proxy that implements the given 'service-interface' and connects it to a channel.
- The channel name is provided on the @Gateway annotation of the Cafe interface.
- public interface Cafe {
-
- @Gateway(requestChannel="orders")
- void placeOrder(Order order);
-
-}
- Finally, have a look at the main() method of the CafeDemo itself.
- 0) {
- context = new FileSystemXmlApplicationContext(args);
- }
- else {
- context = new ClassPathXmlApplicationContext("cafeDemo.xml", CafeDemo.class);
- }
- Cafe cafe = (Cafe) context.getBean("cafe");
- for (int i = 1; i <= 100; i++) {
- Order order = new Order(i);
- order.addItem(DrinkType.LATTE, 2, false);
- order.addItem(DrinkType.MOCHA, 3, true);
- cafe.placeOrder(order);
- }
-}]]>
-
-
- To run this sample as well as 8 others, refer to the README.txt within the "samples" directory
- of the main distribution as described at the beginning of this chapter.
-
-
- When you run cafeDemo, you will see that the cold drinks are initially prepared more quickly than the hot drinks.
- Because there is an aggregator, the cold drinks are effectively limited by the rate of the hot drink preparation.
- This is to be expected based on their respective delays of 1000 and 5000 milliseconds. However, by configuring a
- poller with a concurrent task executor, you can dramatically change the results. For example, you could use a
- thread pool executor with 5 workers for the hot drink barista while keeping the cold drink barista as it is:
-
-
-
- ]]>
- ]]>
-
-]]>]]>
-
-
- Also, notice that the worker thread name is displayed with each invocation. You will see that the hot drinks are
- prepared by the task-executor threads. If you provide a much shorter poller interval (such as 100 milliseconds),
- then you will notice that occasionally it throttles the input by forcing the task-scheduler (the caller) to invoke
- the operation.
-
-
- In addition to experimenting with the poller's concurrency settings, you can also add the 'transactional'
- sub-element and then refer to any PlatformTransactionManager instance within the context.
-
-
-
-
- The XML Messaging Sample
-
- The xml messaging sample in the org.springframework.integration.samples.xml illustrates how to use
- some of the provided components which deal with xml payloads. The sample uses the idea of processing an order for books
- represented as xml.
-
-
- First the order is split into a number of messages, each one representing a single order item using
- the XPath splitter component.
-
-
-
-]]>
-
-
- A service activator is then used to pass the message into a stock checker POJO. The order item document is enriched with information
- from the stock checker about order item stock level. This enriched order item message is then used to route the message. In the
- case where the order item is in stock the message is routed to the warehouse. The XPath router makes use of a
- MapBasedChannelResolver which maps the XPath evaluation result to a channel reference.
-
-
-
-
-
-
-
-
-
-]]>
-
-
- Where the order item is not in stock the message is transformed using
- xslt into a format suitable for sending to the supplier.
-
-]]>
-
-
+
+ Introduction
+
+ Starting with the current release of Spring Integration the samples are no longer included with
+ Spring Integration distribution. Instead we've switched to a much simpler collaborative model that should promote
+ better community participation and community contributions. Samples now have a dedicated Git SCM repository and a
+ dedicated JIRA Issue Tracking system. Sample development will also have its own lifecycle which is not dependent on the
+ lifecycle of the framework releases although the repository will still be tagged with each major release for compatibility
+ reasons.
+
+
+ The great benefit to the community is that we can now add more samples and make them available to you right away
+ without waiting for the release to get them out to you. Having its own JIRA that is not tied up to the the actual
+ framework is also a great benefit. You now have a dedicated place to suggest samples as well as report issues with existing
+ samples. Or you may want to submit a sample to us as an attachment through the JIRA and if we believe your sample adds value we
+ would be more then glad to add it to a samples repository properly crediting the author.
+
+
-
- The OSGi Samples
-
- This release of Spring Integration includes several samples that are OSGi enabled as well as samples that were
- specifically designed to show some of the other benefits of OSGi and Spring Integration when used together.
- First lets look at the two familiar examples that are also configured to be valid OSGi bundles. These are
- Hello World and Cafe. All you need to do to see these samples work in
- an OSGi environment is deploy the generated JAR into such an environment.
-
-
- Use Maven to generate the JAR by executing the 'mvn install' command on either of these projects. This will
- generate the JAR file in the target directory. Now you can simply drop that JAR file into the deployment
- directory of your OSGi platform. For example, if you are using
- SpringSource dm Server,
- drop the files into the 'pickup' directory within the dm Server home directory.
-
-
- Prior to deploying and testing Spring Integration samples in the dm Server or any other OSGi server platform,
- you must have the Spring Integration and Spring bundles installed on that platform. For example, to install
- Spring Integration into SpringSource dm Server, copy all JAR files that are located in the 'dist' directory of
- your Spring Integration distribution into the 'repository/bundles/usr' directory of your dm Server instance
- (see the
- dm Server User Guide
- for more detail on how to install bundles).
-
-
- The Spring Integration samples require a few other bundles to be installed. For the 1.0.3 release, the full
- list including transitive dependencies is:
-
- org.apache.commons.codec-1.3.0.jar
- org.apache.commons.collections-3.2.0.jar
- org.apache.commons.httpclient-3.1.0.jar
- org.apache.ws.commons.schema-1.3.2.jar
- org.springframework.oxm-1.5.5.A.jar
- org.springframework.security-2.0.4.A.jar
- org.springframework.ws-1.5.5.A.jar
- org.springframework.xml-1.5.5.A.jar
-
- These are all located within the 'lib' directory of the Spring Integration distribution. So, you can simply
- copy those JARs into the dm Server 'repository/bundles/usr' directory as well.
-
- The Spring Framework bundles (aop, beans, context, etc.) are also included in the 'lib' directory of the
- Spring Integration distribution, but they do not need to be installed since they are already part of the
- dm Server infrastructure. Also, note that the versions listed above are those included with the Spring
- Integration 1.0.3 release. Newer versions of individual JARs may be used as long as they are within the
- range specified in the MANIFEST.MF files of those bundles that depend upon them.
-
-
- The bundles listed above are appropriate for a SpringSource dm Server 1.0.x deployment environment
- with a Spring Framework 2.5.x foundation. That is the version against which Spring Integration 1.0.3
- has been developed and tested. However, as of the time of the Spring Integration 1.0.3 release, the
- Spring Framework 3.0 release candidates are about to be available, and the dm Server 2.0.x milestones
- are available. If you want to try running these samples in that environment, then you will need to
- replace the Spring Security and Spring Web Services bundles with versions that support Spring 3.0.
- The OXM functionality is moving into the Spring Framework itself for the 3.0 release. Otherwise,
- Spring Integration 1.0.3 has been superficially tested against the Spring 3.0 snapshots available
- at the time of its release. In fact, some internal changes were made in the 1.0.3 release
- specifically to support Spring 3.0 (whereas 1.0.2 does not). Spring Integration 2.0 will be built
- upon a Spring 3.0 foundation.
-
-
-
- To demonstrate some of the benefits of running Spring Integration projects in an OSGi environment (e.g.
- modularity, OSGi service dynamics, etc.), we have included a couple new samples that are dedicated to
- highlighting those benefits. In the 'samples' directory, you will find the following two projects:
-
- osgi-inbound (producer bundle)
- osgi-outbound (consumer bundle)
-
- Unlike the other samples in the distribution, these are not Maven enabled. Instead, we have simply configured
- them as valid dm Server Bundle projects. That means you can import these projects directly into an STS
- workspace using the "Existing Projects into Workspace" option from the Eclipse Import wizard. Then, you can
- take advantage of the STS dm Server tools to deploy them into a SpringSource dm Server instance.
-
- A simple Ant 'build.xml' file has been included within each of these projects as well. The build
- files contain a single 'jar' target. Therefore, after these projects have been built within
- Eclipse/STS, you can generate the bundle (JAR) directly and deploy it manually.
-
-
-
- The structure of these projects is very simple, yet the concepts they showcase are quite powerful. The
- 'osgi-inbound' module enables sending a Message to a Publish-Subscribe Channel using a Spring Integration
- Gateway proxy. The interesting part, however, is that the Publish-Subscribe Channel is exported as an OSGi
- service via the <osgi:service/> element. As a result, any other bundles can be developed, deployed, and
- maintained independently yet still subscribe to that channel.
-
-
- The 'osgi-outbound' module is an example of such a subscribing consumer bundle. It uses the corresponding
- <osgi:reference/> element to locate the channel exported by the 'osgi-inbound' bundle. It also contains
- configuration for a <file:outbound-gateway/> which is a subscriber to that channel and will write the
- Message content to a file once it arrives. It then sends a response Message with the name of the file and its
- location.
-
-
- To make it easy to run, we've exposed a command-line interface where you can type in the command, the message,
- and the file name to execute the demo. This is exposed through the OSGi console. Likewise, the response that
- provides the name and location of the resulting file will also be visible within the OSGi console.
-
-
- To run these samples, make sure your OSGi environment is properly configured to host Spring Integration bundles
- (as described in the note above). Deploy the producer bundle (osgi-inbound) first, and then deploy the consumer
- bundle (osgi-outbound). After you have deployed these bundles, open the OSGi console and type the following
- command:
- help ]]>
- You will see the following amidst the output:
- - send text to be written to a file]]>
- As you can see, that describes the command that you will be able to use to send messages. If you are interested
- in how it is implemented or want to customize message sending logic or even create a new command look at
- InboundDemoBundleActivator.java in the consumer bundle.
-
- When using the SpringSource Tool Suite, you can open the OSGi console by first opening the dm Server
- view and then choosing the 'Server Console' tab at the bottom (to open the dm Server view, navigate to
- the dm Server instance listed in the 'Servers' view and either double-click or hit F3). Alternatively,
- you can open the OSGi console by connecting to port 2401 via telnet (as long as that is enabled, and
- for dm Server, it is enabled by default):
- telnet localhost 2401
-
-
-
- Now send a message by typing: siSend "Hello World" hello.txt]]>
- You will see something similar to the following in the OSGi console:
-
-
- It is not necessary to wrap the message in quotes if it does not contain spaces.
- Go ahead and open up the file and verify that the message content was written to it.
-
-
-
- Let's assume you wanted to change the directory to which the files are written or make any other change to the
- consumer bundle (osgi-outboud). You only need to update the consumer bundle and not the producer bundle. So, go
- ahead and change the directory in the 'osgi-outbound.xml' file located within 'src/META-INF/spring' and refresh
- the consumer bundle.
-
- If using STS to deploy to dm Server, the refresh will happen automatically. If replacing bundles manually,
- you can issue the command 'refresh n' in the OSGi console (where n would be the ID of the bundle as
- displayed at any point after issuing the 'ss' command to see the short status output).
-
- You will see that the change takes affect immediately. Not only that, you could even start developing and
- deploying new bundles that subscribe to the messages produced by the producer bundle the same way as the existing
- consumer bundle (osgi-outbound) does. With a publish-subscribe-channel any newly deployed bundles would start
- receiving each Message as well.
-
- If you also want to modify and refresh the producer bundle, be sure to refresh the consumer bundle
- afterwards as well. This is necessary because the consumer's subscription must be explicitly re-enabled
- after the producer's channel disappears. You could alternatively deploy a relatively static bundle that
- defines channels so that producers and consumers can be completely dynamic without affecting each other
- at all. In Spring Integration 2.0, we plan to support automatic re-subscription and more through the use
- of a Control Bus.
-
-
-
- That pretty much wraps up this very simple example. Hopefully it has successfully demonstrated the benefits of
- modularity and OSGi service dynamics while working with Spring Integration. Feel free to experiment by following
- some of the suggestions mentioned above. For deeper coverage of the applicability of OSGi when used with Spring
- Integration, read this blog
- by Spring Integration team member Iwein Fuld.
-
+
+ Where to get Samples
+
+ To monitor samples development and to get more information on the repository you can visit the following
+ URL: http://git.springsource.org/spring-integration/samples
+ Since we are using Git SCM we should use the proper terminology as well when it comes to the tasks you need to perform to make
+ samples available locally on your machine. For more information on Git SCM please visit their
+ website: http://git-scm.com/
+
+
+ CLONE samples repository. (For those unfamiliar with Git, this is somewhat the equivalent of a checkout.)
+
+
+ This is the first step you should go through. You must have Git installed on your machine. There are many GUI-based products
+ available for many platforms. Simple Google search will let you find them.
+ To clone samples repository from command line:
+ mkdir spring-itegration-samples
+> cd spring-itegration-samples
+> git clone git://git.springsource.org/spring-integration/samples.git]]>
+
+
+ That is all you need to do. Now you have cloned the entire samples repository. Since samples repository is a live
+ repository, you might want to perform periodic updates to get new samples as well as updates to the existing samples.
+ To get the updates use git PULL command:
+ git pull]]>
+
+
+ Submit samples or sample requests
+
+
+ As mentioned earlier, Spring Integration samples have a dedicated JIRA Issue tracking system.
+ To submit new sample request or to submit the actual sample (as an attachment) please visit our JIRA Issue Tracking system:
+ https://jira.springframework.org/browse/INTSAMPLES
+
+
+
+ Samples structure
+
+ The structure of the samples changed as well. With plans for more samples we realized that some
+ samples have different goals then others. While they all share the common goal of showing you how to apply and work with
+ Spring Integration framework, they also defer in areas where some samples were meant to concentrate on a technical
+ use case while others on the business use case and some samples are all about showcasing various techniques that
+ could be applied to address certain scenarios (both technical and business). Categorization of samples will allow us
+ better organize them based on the problem each sample addresses while giving you a simpler way of finding the right sample
+
+
+ Currently there are 4 categories. Within the samples repository each category has its own directory which is named after the
+ category name:
+
+
+
+ BASIC (samples/basic)
+
+
+ This is a good place to get started. The samples here are technically motivated and demonstrate the bare
+ minimum with regard to configuration and code, to help you to get started quickly by introducing you to the basic concepts,
+ API and configuration of Spring Integration as well as Enterprise Integration Patterns (EIP). For example; If your are
+ looking for an answer on how to implement and wire Service Activator to a Channel
+ or how to use Messaging Gateway to your message exchange or how to get started with using MAIL or
+ TCP/UDP modules etc., this would be the right place to find a good sample. The bottom line is this is a good place
+ to get started.
+
+
+
+ INTERMEDIATE (samples/intermediate)
+
+
+ This category targets developers who are already familiar with Spring Integration framework (past getting started),
+ but need some more guidance while resolving a more advanced technical problems one might deal with
+ once switch to a Messaging architecture.
+ For example; If you are looking for an answer on how to handle errors in various message exchange
+ scenarios or how to properly configure the Aggregator for the situations where some messages
+ might not ever arrive for aggregation etc,. and any other issue that goes beyond a basic implementation and configuration
+ of a particular component and addresses "what else you can do with it" type of problem this
+ would be the right place to find these type of samples.
+
+
+
+ ADVANCED (samples/advanced)
+
+
+ This category targets develoopers who are very familiar with Spring Integration framework but looking to
+ extend it to address a specific custom need by using 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 Bean parser on top of Spring Integration Bean parsers hierarchy when implementing custom name space
+ for a custom component, 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 to allow you to connect remote systems with Spring Integration messaging framework.
+ However you might have a need to integrate with system for which the core framework does not provide an adapter.
+ So you have to implement your own. This category would include samples showing you how to do it.
+
+
+
+
+ APPLICATIONS (samples/applications)
+
+
+ This category targets developers and architects who have a good understanding of the Messaging architecture,
+ EIP and above average understanding of Spring and Spring Integration frameworks and are looking for samples that
+ address a particular business problem. In other words the emphasis of samples in this category
+ is business use cases and how it could be solved via Messaging Architecture and Spring Integration
+ in particular.
+ For example; If you are interested to see how a Loan Broker or Travel Agent
+ process could be implemented and automated via Spring Integration this would be the right place to find these types of samples.
+
+
+
+
+ Remember! Spring Integration is a community driven framework, therefore community participation is IMPORTANT.
+That includes Samples, so if you can't find what you are looking for let us know.
+
+
+
+
+
+ Samples
+
+ Currently Spring Integration comes with quite a few samples and you can only expect more.
+ To help you better navigate through them, each sample comes with its own readme.txt file which coveres
+ sevaral details about the sample (e.g., what EIP patterns it addresses, what problem it is trying to solve, how to run sample etc.).
+ However, certain samples require a more detailed and some times graphical explanation. In these section you'll
+ find details on samples that we believe require special attention.
+
+
+ Loan Broker
+
+
+ The Cafe Sample
+
+ In this section, we will review a sample application that is included in the Spring Integration
+ distribution. This sample is inspired by one of the samples featured in Gregor Hohpe's
+ Ramblings.
+
+
+ The domain is that of a Cafe, and the basic flow is depicted in the following diagram:
+
+
+
+
+
+
+
+
+
+
+
+
+ The Order object may contain multiple OrderItems. Once the order
+ is placed, a Splitter will break the composite order message into a single message per
+ drink. Each of these is then processed by a Router that determines whether the drink is hot
+ or cold (checking the OrderItem object's 'isIced' property). The
+ Barista prepares each drink, but hot and cold drink preparation are handled by two
+ distinct methods: 'prepareHotDrink' and 'prepareColdDrink'. The prepared drinks are then sent to the Waiter where
+ they are aggregated into a Delivery object.
+
+
+ Here is the XML configuration:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+ As you can see, each Message Endpoint is connected to input and/or output channels. Each endpoint will manage
+ its own Lifecycle (by default endpoints start automatically upon initialization - to prevent that add the
+ "auto-startup" attribute with a value of "false"). Most importantly, notice that the objects are simple POJOs
+ with strongly typed method arguments. For example, here is the Splitter:
+ split(Order order) {
+ return order.getItems();
+ }
+ }]]>
+ In the case of the Router, the return value does not have to be a MessageChannel
+ instance (although it can be). As you see in this example, a String-value representing the channel name is
+ returned instead.
+
+
+
+ Now turning back to the XML, you see that there are two <service-activator> elements. Each of these
+ is delegating to the same Barista instance but different methods: 'prepareHotDrink'
+ or 'prepareColdDrink' corresponding to the two channels where order items have been routed.
+
+
+
+ As you can see from the code excerpt above, the barista methods have different delays (the hot drinks take 5
+ times as long to prepare). This simulates work being completed at different rates. When the
+ CafeDemo 'main' method runs, it will loop 100 times sending a single hot drink and a
+ single cold drink each time. It actually sends the messages by invoking the 'placeOrder' method on the Cafe
+ interface. Above, you will see that the <gateway> element is specified in the configuration file. This
+ triggers the creation of a proxy that implements the given 'service-interface' and connects it to a channel.
+ The channel name is provided on the @Gateway annotation of the Cafe interface.
+ public interface Cafe {
+
+ @Gateway(requestChannel="orders")
+ void placeOrder(Order order);
+
+ }
+ Finally, have a look at the main() method of the CafeDemo itself.
+ 0) {
+ context = new FileSystemXmlApplicationContext(args);
+ }
+ else {
+ context = new ClassPathXmlApplicationContext("cafeDemo.xml", CafeDemo.class);
+ }
+ Cafe cafe = (Cafe) context.getBean("cafe");
+ for (int i = 1; i <= 100; i++) {
+ Order order = new Order(i);
+ order.addItem(DrinkType.LATTE, 2, false);
+ order.addItem(DrinkType.MOCHA, 3, true);
+ cafe.placeOrder(order);
+ }
+ }]]>
+
+
+ To run this sample as well as 8 others, refer to the README.txt within the "samples" directory
+ of the main distribution as described at the beginning of this chapter.
+
+
+ When you run cafeDemo, you will see that the cold drinks are initially prepared more quickly than the hot drinks.
+ Because there is an aggregator, the cold drinks are effectively limited by the rate of the hot drink preparation.
+ This is to be expected based on their respective delays of 1000 and 5000 milliseconds. However, by configuring a
+ poller with a concurrent task executor, you can dramatically change the results. For example, you could use a
+ thread pool executor with 5 workers for the hot drink barista while keeping the cold drink barista as it is:
+
+
+
+ ]]>
+ ]]>
+
+ ]]>]]>
+
+
+ Also, notice that the worker thread name is displayed with each invocation. You will see that the hot drinks are
+ prepared by the task-executor threads. If you provide a much shorter poller interval (such as 100 milliseconds),
+ then you will notice that occasionally it throttles the input by forcing the task-scheduler (the caller) to invoke
+ the operation.
+
+
+ In addition to experimenting with the poller's concurrency settings, you can also add the 'transactional'
+ sub-element and then refer to any PlatformTransactionManager instance within the context.
+
+
+
+
+ The XML Messaging Sample
+
+ The xml messaging sample in the org.springframework.integration.samples.xml illustrates how to use
+ some of the provided components which deal with xml payloads. The sample uses the idea of processing an order for books
+ represented as xml.
+
+
+ First the order is split into a number of messages, each one representing a single order item using
+ the XPath splitter component.
+
+
+
+ ]]>
+
+
+ A service activator is then used to pass the message into a stock checker POJO. The order item document is enriched with information
+ from the stock checker about order item stock level. This enriched order item message is then used to route the message. In the
+ case where the order item is in stock the message is routed to the warehouse. The XPath router makes use of a
+ MapBasedChannelResolver which maps the XPath evaluation result to a channel reference.
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+ Where the order item is not in stock the message is transformed using
+ xslt into a format suitable for sending to the supplier.
+
+ ]]>
+
+
+