Enterprise Integration Zone is brought to you in partnership with:

Java architect with UST Global Biju has posted 5 posts at DZone. View Full User Profile

Spring Integration and Apache Camel

12.31.2009
| 64902 views |
  • submit to reddit

Spring Integration and Apache Camel are open source frameworks providing a simpler solution for the Integration problems in the enterprise, to quote from their respective websites:


Apache Camel -

Apache Camel is a powerful open source integration framework based on known Enterprise Integration Patterns with powerful Bean Integration.

Spring Integration -
It provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns while building on the Spring Framework's existing support for enterprise integration.

Essentially Spring Integration and Apache Camel enable applications to integrate with other systems.

This article seeks to provide an implementation for an integration problem using both Spring Integration and Apache Camel. The objective is to show how easy it is to use these frameworks for a fairly complicated integration problem and to recommend either of these great products for your next Integration challenge.

Problem:

To illustrate the use of these frameworks consider a simple integration scenario, described using EIP terminology:

 

The application needs to get a "Report" by aggregating "Sections" from a Section XML over http service. Each request for Report consists of a set of request for sections – in this specific example there are requests for three sections, the header, body and footer. The XML over http service returns a Section for the Section Request. The responses need to be aggregated into a single report. A sample test for this scenario is of the following type:

        ReportGenerator reportGenerator = reportGeneratorFactory.createReportGenerator();
List<SectionRequest> sectionRequests = new ArrayList<SectionRequest>();

String entityId="A Company";

sectionRequests.add(new SectionRequest(entityId,"header"));
sectionRequests.add(new SectionRequest(entityId,"body"));
sectionRequests.add(new SectionRequest(entityId,"footer"));

ReportRequest reportRequest = new ReportRequest(sectionRequests);

Report report = reportGenerator.generateReport(reportRequest);
List<Section> sectionOfReport = report.getSections();
System.out.println(report);
assertEquals(3, sectionOfReport.size());

The “ReportGenerator” is the messaging gateway, hiding the details of the underlying messaging infrastructure and in this specific case also the integration API – Apache Camel or Spring Integration. To start with, let us implement a solution to this integration problem using Spring Integration as the Framework, followed by Apache Camel. The complete working code using Spring Integration and Apache Camel is also available with the article.

 

Legacy
Published at DZone with permission of its author, Biju Kunjummen.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Stefan Krause replied on Fri, 2010/01/01 - 1:11pm

Thanks for the nice article. Do you know if either of the aggregators supports persistent messages? Considering the much touted delivery guarantee for messaging systems this would look like a very basic requirement.

Claus Ibsen replied on Sun, 2010/01/03 - 7:46am

@Stefan Camel does currently not provide a persistent store for the Aggregator EIP. Its on the roadmap though, for Camel 2.3: CAMEL-217. We have planned an overhaul of the Aggregator EIP which should also make it easier to use out of the box. For example the need to use the low level AggregationStrategy with a POJO of some sort is also desired.

Some design ideas was sketched here: overhaul of Aggregator.

You can however currently create your own persistent capable implementation of org.apache.camel.processor.aggregate.AggregationCollection and use your implementation in the Aggregator EIP. Some end users have done that.

Claus Ibsen replied on Sun, 2010/01/03 - 8:02am

Comments for page 3:
Camel do support Messaging Gateway EIP which is documented here. The documentation do need to be improved with some better samples.

In your case you can for example use the @Produce annotation to inject a messaging gateway to easily send in the message to Camel.

This makes the code nice, simple and easy as shown below:

public class CamelReportGenerator implements ReportGenerator {

    @Produce(uri = "direct:start")
    private ReportGenerator generator;

    public Report generateReport(ReportRequest reportRequest) {
        return generator.generateReport(reportRequest);
    }

}


However there is an issue in Camel (v2.1 or older) when invoking a bean later in the route which you do when calling the bean method in the splitter EIP. To prevent this problem you need to add to use the convertBodyTo as shown below:

	@Override
	public void configure() throws Exception {
            from("direct:start")
            .convertBodyTo(ReportRequest.class)
            .split(bean("sectionRequestSplitterBean", "split"), new ReportAggregationStrategy())
    		    .transform().method("sectionRequestToXMLBean", "transform")
	    	    .to(serviceURL)
	            .transform().method("sectionResponseXMLToSectionBean", "transform")
            .end();
	}

This will be fixed in Camel 2.2 ticket CAMEL-2325.

Instead of using @Produce you can use the CamelProxy which allows you to proxy a POJO and use that POJO as the messaging gateway. You can define the proxy in the Spring XML directly as shown in the documentation.

Biju Kunjummen replied on Sun, 2010/01/03 - 9:01am in response to: Claus Ibsen

Thanks for your feedback davsclaus. CamelProxy is what I should have mentioned in the article. I will update the article shortly. One feedback on the the code that you have provided:
	@Override
	public void configure() throws Exception {
            from("direct:start")
            .convertBodyTo(ReportRequest.class)
            .split(bean("sectionRequestSplitterBean", "split"), new ReportAggregationStrategy())
    		    .transform().method("sectionRequestToXMLBean", "transform")
	    	    .to(serviceURL)
	            .transform().method("sectionResponseXMLToSectionBean", "transform")
            .end();
	}
The .end() is giving a compilation error. I am assuming that this is a bug with Apache Camel 2.1.0. It works without that, so for now I will include the code without the final .end().

Claus Ibsen replied on Sun, 2010/01/03 - 11:20am

Ah cool

The final *end()* is optional as the route ends anyway. Its only needed if you need to do some additional routing after all the messages has been aggregated again (eg. scatter-gather is done). But in this case the message should be returned to the original caller = the service gateway.

The compilation error. Yeah we have stretched as far we can do with regular Java. It certainly got its limitations when trying to mimic and build a DSL.

Kai Wähner replied on Wed, 2012/01/11 - 4:10am

I just wrote an article, which explains my experiences with Apache Camel and its alternatives Spring Integration and Mule ESB:

Spoilt for Choice: Which Integration Framework to use - Spring Integration, Mule ESB or Apache Camel?


Best regards,
Kai Wähner (Twitter: @KaiWaehner)

Oleg Zhurakousky replied on Wed, 2012/03/14 - 11:20am in response to: Claus Ibsen

@Stephan Spring Integration has always provided persistent storage option for both Aggregator and Resequencer via 'message-store' option. You can read more here: http://static.springsource.org/spring-integration/reference/htmlsingle/#aggregator

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.