Blogs

SpringSource Blog

Implementing Enterprise Integration Patterns part 0

Iwein Fuld

After my talk on Spring Integration I've been getting quite some questions on clarification and samples. To meet the demand I will start a small series on implementing different integration patterns using Spring Integration. This first article will focus on the basics. It will show you how to get up and running and walk through one of the samples.

If you never heard about Spring Integration before it might be a good idea to familiarize yourself with it reading the introductory blog Mark Fisher wrote about it or by browsing the project website. In general

Let me start with a disclaimer: the patterns you're about to see here are merely meant as an illustration to the features that Spring Integration has to offer; syntax may vary through different versions and extra precautions might be needed on your system.

The first step to getting involved in Spring Integration is to download the project and look at the sample. So let's start with that:

  1. Check out the sources from svn: svn co https://src.springframework.org/svn/spring-integration/trunk
    If you're uncomfortable working with a constantly changing code base you could also go for one of the milestones under https://src.springframework.org/svn/spring-integration/tags/, but at the time of this blog M4 isn't out yet and I still want to show you the latest features of course. Don't forget to check if M4 isn't out already when you read this. Last time I checked it was about to hatch.

  2. Run a build on the entire project:
    $ cd build-spring-integration
    $ ant
  3. Import the projects in Eclipse and configure an IVY_CACHE variable to point to your ivy cache. This will probably be a directory next to build-spring-integration.
  4. Open up HelloWorldDemo and run as Java application. If you've done this before you'll see the changes in syntax.

If this works OK you're up and running. Next you can explore the different samples. I will describe only the cafe sample because that is the most interesting configuration.

In the cafe package of the sample project you will find all the code related to the implementation of the famous Starbucks story. To introduce you to the architecture I will follow an order from start (Cafe) to finish (Barista):

First the order is created by CafeDemo. It contains two drinks, one hot, one cold. Then the order is wrapped in a message and put on the 'orders' channel. The endpoint listening to the 'orders' channel is a splitter (OrderSplitter) in the split method the order is split up into multiple Drinks which are in turn wrapped into separate messages by the framework.

After being split and put on the 'drinks' channel the drinks are being processed by the DrinksRouter. This router has the responsibility of putting hot drinks on the 'hotDrinks' channel and cold drinks on the 'coldDrinks' channel. Both these channels are handled by different endpoints that use the prepareHotDrink and preprareColdDrink method on the Barista respectively.

Let's follow the flow of messages through the relevant bits of code:
In the cafeDemo.xml bean definition file you can see a Cafe being configured as a bean.
class="org.springframework.integration.samples.cafe.Cafe">


This bean is used by the CafeDemo main method to put order messages on the order queue.
Cafe cafe = (Cafe) context.getBean("cafe");
DrinkOrder order = new DrinkOrder();
Drink hotDoubleLatte = new Drink(DrinkType.LATTE, 2, false);
Drink icedTripleMocha = new Drink(DrinkType.MOCHA, 3, true);
order.addDrink(hotDoubleLatte);
order.addDrink(icedTripleMocha);
for (int i = 0; i < 100; i++) {
cafe.placeOrder(order);
}

A <context:component-scan ...../> is being used in cafeDemo.xml to bootstrap the OrderSplitter and DrinkRouter.

The OrderSplitter is sprinkled with some annotations:

  • the @MessageEndpoint annotation tells Spring Integration to wrap a bean of this type in an endpoint when you turn on annotation-config. Additionally it is a subtype of @Component so that you don't need to write an xml bean definition for Spring to pick it up.

  • the @Splitter annotation tells spring to use the splitOrder method to split a message containing an Order as payload into multiple messages containing the drinks of that Order.

@MessageEndpoint(input="orders", output="drinks")
public class OrderSplitter {

@Splitter
public List split(Message orderMessage) {
return orderMessage.getPayload().getDrinks();
}

}

The DrinkRouter is similarly decorated with annotations that tell Spring Integration to use it as a router. The string returned from the @Router annotated method is interpreted by Spring Integration as the output channel.
@MessageEndpoint(input="drinks")
public class DrinkRouter {

@Router
public String resolveDrinkChannel(Drink drink) {
return (drink.isIced()) ? "coldDrinks" : "hotDrinks";
}

}

After the routing the messages are available on the hotDrinks or coldDrinks channel depending on their temperature.

The endpoints configured to call the appropriate method on the Barista are configured in xml:
method="prepareColdDrink">

method="prepareHotDrink">

You can see that both the input channel and the method to feed the message to are defined so Spring Integration knows what to do.

Notice that you don't need to unwrap the message yourself: accepting the payload type as input parameter is fine as well. If you change the methods in the Barista to accept Message and extract the payload yourself, it will still work as expected.
public void prepareColdDrink(Message drinkMessage) {
Drink drink = drinkMessage.getPayload();
//no changes to the rest of the code
}

Play around with the sample and post on the forum if you have any troubles. You'll find that they are quite helpful already (mainly because Mark responds to almost every post). Next episode will feature an other implementation of an EIP.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

6 responses


  1. Your post assumes that the reader is familiar with the Spring Integratino project, which is not true in my case. Some information beyond links to previous blog posts would help to actually get started.


  2. Hi Iwein, nice to see another milestone soon. But I'm trying to build from the sources, and have an eror. Any Idea?

    jar:
    [mkdir] Created dir: C:\work\extracts\spring-integration-trunk\spring-integration-core\target\artifacts
    [mkdir] Created dir: C:\work\extracts\spring-integration-trunk\spring-integration-core\target\classes
    [s:javac] Compiling 167 source files to C:\work\extracts\spring-integration-trunk\spring-integration-core\target\classes
    [subant] Leaving directory: C:\work\extracts\spring-integration-trunk\spring-integration-core

    BUILD FAILED
    C:\work\extracts\spring-integration-trunk\spring-build\multi-bundle\artifact.xml:35: The following error occurred while executing this line:
    C:\work\extracts\spring-integration-trunk\spring-build\multi-bundle\common.xml:70: The following error occurred while executing this line:
    java.lang.NoSuchMethodError: newInstance


  3. Hi Iwein,

    how do you handle the spring-integration-sources in the IDE? Do you use a plugin for ivy? I know there was an Ivy-IDE-Plugin for version 1.4 or so.
    Do you make a single project for every sub-module in spring-integration? Or do you make one Eclipse-Project with multiple src-folders ( for every sub-module at least 2, main / test)?

    Thanks.

    Jörg


  4. @Jörn Zaefferer: I've added some reference to get started, more improvements might follow.

    @Nicolás Cornaglia: This is probably related to a versioning problem, can you stick it on the forums (http://forum.springframework.org/forumdisplay.php?f=42) with a full stacktrace and environment description. That way we can track the particulars of the problem.

    @Jörg Bellmann: I run the build command line and configure an eclipse variable pointing to my IVY_CACHE directory. You may find options on integrating the build with eclipse if you ask on the forums, but command line worked fine for me.
    I'll clear up the IVY_CACHE detail in the post.


  5. Hello Iwein!
    Hope you still read my comment as this post looks old!
    I have tried what you suggested but having problem with configuration of IVY_CACHE variable. Can you please route me through?


  6. One Question Not sure this is the correct place to post.
    I am using something like this

    In a clustered enviormnet & a web application (deployed on weblogic 10.0), I would like to know whether its going to create 3 threads for each HttpRequest or its going to have a pool of 3 threads irrespective of the number of HttpRequest

    Please respond as early as possible
    Thanks in advance

Leave a Reply