Sie sind auf Seite 1von 69

InstitutfrArchitekturvonAnwendungssystemen

UniversittStuttgart
Universittsstrae38
70569Stuttgart

StudienarbeitNr.2127

RealizationofEAIPatterns
withApacheCamel
PascalKolb

Studiengang:

Informatik

Prfer:

Prof.Dr.FrankLeymann

Betreuer:

Dipl.Inf.ThorstenScheibler

begonnenam:

26.10.2007

beendetam:

26.04.2008

CRKlassifikation

D.2.11,D.3,H.4.1

Table of Contents
TableofListings.............................................................................................................vii
1 Introduction.............................................................................................................1
1.1

TaskDescription.................................................................................................................................1

1.2

Structureofthisthesis.......................................................................................................................2

2 ApacheCamelFundamentals...................................................................................3
2.1

IntroductionintoApacheCamel........................................................................................................3

2.2 ApacheCamelsArchitecture.............................................................................................................4
2.2.1
CamelComponentsandEndpoints............................................................................................4
2.2.2
CamelExchangeandMessage...................................................................................................6
2.2.3
CamelTypeConverter...............................................................................................................6
2.2.4
CamelProcessor........................................................................................................................7
2.2.5
CamelContext...........................................................................................................................7
2.2.6
CamelDomainSpecificLanguage/FluentAPI..........................................................................8
2.2.7
CamelRoutes.............................................................................................................................8
2.3

AsimpleCamelexample....................................................................................................................9

3 EAIPatternsinApacheCamel.................................................................................11
3.1 MessagingChannels........................................................................................................................12
3.1.1
PointtoPointChannel............................................................................................................12
3.1.2
PublishSubscribeChannel......................................................................................................13
3.1.3
DatatypeChannel....................................................................................................................13
3.1.4
InvalidMessageChannel.........................................................................................................13
3.1.5
DeadLetterChannel................................................................................................................13
3.1.6
GuaranteedDelivery................................................................................................................14
3.1.7
ChannelAdapter......................................................................................................................14
3.1.8
MessagingBridge.....................................................................................................................15
3.1.9
MessageBus............................................................................................................................15
3.2 MessageConstruction.....................................................................................................................15
3.2.1
Command/Document/EventMessage.................................................................................16
3.2.2
RequestReply..........................................................................................................................16
3.2.3
ReturnAddress........................................................................................................................17
3.2.4
MessageExpiration..................................................................................................................17
3.2.5
CorrelationIdentifier/MessageSequence/FormatIndicator...............................................18
3.3

PipesandFilters...............................................................................................................................18
iii

TABLEOFCONTENTS

3.4 MessageRouting..............................................................................................................................20
3.4.1
ContentBasedRouter..............................................................................................................20
3.4.2
MessageFilter..........................................................................................................................21
3.4.3
DynamicRouter........................................................................................................................21
3.4.4
RecipientList............................................................................................................................22
3.4.5
Splitter......................................................................................................................................23
3.4.6
Aggregator................................................................................................................................24
3.4.7
ComposedMessageProcessor/ScatterGather......................................................................27
3.5 MessageTransformation..................................................................................................................27
3.5.1
EnvelopeWrapper....................................................................................................................27
3.5.2
ContentEnricher......................................................................................................................28
3.5.3
ContentFilter...........................................................................................................................28
3.5.4
ClaimCheck..............................................................................................................................29
3.5.5
Normalizer................................................................................................................................30
3.6 MessagingEndpoint.........................................................................................................................30
3.6.1
MessagingGateway..................................................................................................................30
3.6.2
MessagingMapper...................................................................................................................31
3.6.3
PollingConsumer.....................................................................................................................31
3.6.4
EventDrivenConsumer............................................................................................................32
3.6.5
CompetingConsumers.............................................................................................................32
3.6.6
MessageDispatcher.................................................................................................................33
3.6.7
SelectiveConsumer..................................................................................................................34
3.6.8
DurableSubscriber...................................................................................................................34
3.6.9
IdempotentReceiver................................................................................................................35
3.6.10 ServiceActivator.......................................................................................................................35

4 Implementation......................................................................................................37
4.1

Concept............................................................................................................................................37

4.2

Technologiesused.............................................................................................................................38

4.3 TheEAI2CamelFramework............................................................................................................39
4.3.1
HelperClasses..........................................................................................................................40
4.3.2
MessageProducerTemplate....................................................................................................41
4.3.3
WebServiceEndpoint..............................................................................................................41
4.3.4
WebServiceProvider...............................................................................................................42
4.3.5
MessageTranslator..................................................................................................................43
4.3.6
ContentEnricher......................................................................................................................43
4.3.7
RecipientList............................................................................................................................44
4.3.8
Aggregator................................................................................................................................45
4.4 GenerationofApacheCamelbasedJavacode.................................................................................47
4.4.1
ParameterizationoftheEAIpatterns.......................................................................................47
4.4.2
IntegrationintotheEclipsebasedEditor.................................................................................48
4.4.3
GenerationoftheCode............................................................................................................48
4.4.4
RequiredLibraries.....................................................................................................................49
4.5

iv

ExampleMessagingSystem.............................................................................................................49

Bibliography.................................................................................................................51
Appendix......................................................................................................................55
A.1 CamelexampleusingbuiltinPipeline.............................................................................................55
A.1.1
JavaCode.................................................................................................................................55
A.1.2
Output.....................................................................................................................................58
A.1.3
Discussion................................................................................................................................60

Table of Listings
Listing1:ConfiguringEndpoints......................................................................................................................5
Listing2:SimpleCamelexample....................................................................................................................10
Listing3:DeadLetterChannelfornonmessagingsystemcomponents.......................................................14
Listing4:AMessagingBridgeinApacheCamel.............................................................................................15
Listing5:RequestReplyinApacheCamel.....................................................................................................17
Listing6:MessageExpirationforJMSEndpointsinApacheCamel...............................................................17
Listing7:ApacheCamelsapproachtothePipesandFilterspattern...........................................................19
Listing8:PatternconformapproachtothePipesandFilterspattern..........................................................20
Listing9:FixedrouteinApacheCamel..........................................................................................................20
Listing10:ContentBasedRouterinApacheCamel.......................................................................................21
Listing11:MessageFilterinApacheCamel...................................................................................................21
Listing12:PossibleimplementationoftheDynamicRouterpattern............................................................22
Listing13:RecipientListinApacheCamel.....................................................................................................23
Listing14:SplitterinApacheCamel..............................................................................................................24
Listing15:ApacheCamelsAggregatorwithacustomAggregationCollection..............................................26
Listing16:MessageTranslatorinApacheCamel...........................................................................................27
Listing17:PossibleContentEnricherimplementationinApacheCamel.......................................................28
Listing18:ContentfilteringusinganXPathexpressioninApacheCamel.....................................................29
Listing19:PossibleClaimCheckimplementationinApacheCamel...............................................................29
Listing20:NormalizerinApacheCamel........................................................................................................30
Listing21:PollingConsumerinApacheCamel..............................................................................................31
Listing22:EventDrivenConsumerinApacheCamel....................................................................................32
Listing23:CompetingConsumerusingtheJMSComponentinApacheCamel............................................32
Listing24:MessageDispatcherusingaContentBasedRouter.....................................................................34
Listing25:SelectiveConsumerusingApacheCamelsJMSComponent.......................................................34
Listing26:DurableSubscriberusingApacheCamelsJMSComponent........................................................35
Listing27:ApacheCamelsIdempotentReceiver..........................................................................................35
Listing28:TheServiceActivatorpatterninApacheCamel...........................................................................36
Listing29:UsingtheMessageProducerTemplateoftheEAI2CamelFramework......................................41
Listing30:RetrievingthedatatoenrichinanXSLTstylesheetviaaspecialURL..........................................44
Listing31:RetrievingthedatatoenrichinanXSLTstylesheetviaanXSLTparameter..................................44

vii

Introduction

Enterprise application systems rarely live in isolation as creating a single huge application that
runs a complete business is almost impossible. Thus enterprises typically run hundreds or even
thousands of different application systems. Because most of these application systems typically
needtoworktogethertosupportcommonbusinessprocessesandtosharedataacrossapplication
systems,theseapplicationsystemsneedtobeintegrated.Enterpriseapplicationintegrationneeds
toprovideefficient,reliableandsecuredataexchangebetweenmultipleenterpriseapplications.
An important aspect of application integration is to keep the integrated application system inde
pendent. This isimportant in order toenable the different applicationsystems to evolve without
affecting each other and thus making the overall solution more tolerant to changes. This is often
referredtoasLooseCoupling.LooseCouplingcanbeachievedbyusingasynchronouscommuni
cation,forexamplebyusingmessaging.
Becauseintegratingenterpriseapplicationsisachallengingtopicsomefrequentlyrecurringprob
lemsandtheirsolutionhasbeendescribedinformofpatterns.Patternsareatechniquetodocu
ment expert knowledge and experience. The book Enterprise Integration Patterns by Gregor
HohpeandBoobyWoolf[HW03]describesacollectionofpatternsresidinginthedomainofenter
priseapplicationintegrationusingmessaging.
The main objective of this work is to analyze the implementation of these Enterprise Integration
PatternsinApacheCamel[Cam].

1.1

Task Description

InthisworktheApacheCamelplatformshallbeevaluatedregardingthecorrectimplementation
of the Enterprise Integration Patterns. Missing patterns shall be supplemented and the platform
shall be extended by appropriate mechanisms if required. Thereby an application programming
interface(API)shallbedeveloped,thatenablesthemodelingofintegrationscenariosbasedonthe
enterprise integration patterns. ThisAPI shall also enable the generation of executable code. The
resultsofthisworkshallbedemonstratedbyaprototypeandaconcreteexample.
Intheworkof[Dru07]atoolforthegraphicalmodelingofintegrationscenarioshasalreadybeen
developed. This tool enables the generation of WSBPEL [AAA+07] processes from the modeled
integrationscenario.Thesolutiondevelopedaspartofthisworkisbasedonthistool.Thetoolis
therebyextendedwiththeabilitytogenerateexecutableJavacode.

INTRODUCTION

1.2

Structure of this thesis

Thisthesisisstructuredasfollows:
Inchapter2theworkintroducestotheApacheCamelplatformandsummarizesitsarchitecture.It
isimportanttounderstandApacheCamelsarchitectureasthisisarequirementtounderstandthe
evaluationofApacheCamelanditsimplementationoftheenterpriseintegrationpatterns.
Inchapter3thedifferententerpriseintegrationpatternsdescribedinHohpesandWoolfsbookare
evaluatedregardingtheirimplementationinApacheCamel.Theevaluationofthepatternsisstruc
turedingroupssimilartotheiroccurrenceinHohpesandWoolfsbook.
Inchapter4theresultsfromchapter3areusedtoextendthemodelingtoolwhichwasdeveloped
as part of the work from [Dru07]. The tool is extended with the ability to create executable Java
codefromthemodeledintegrationscenario.

2
2.1

Apache Camel Fundamentals


Introduction to Apache Camel

ThischapterintroducestoApacheCamel[Cam].TheApacheCamelversiondiscussedinthiswork
andusedfortheimplementationdescribedinchapter4belowisApacheCamelrelease1.2.0,the
mostrecentreleasetodate.TheApacheCamelprojectisarelativelyyoungprojectitwasstarted
inearly2007andisthuslackinggooddocumentation.Forthisreason,thischapterintroducesto
Camels architecture so the reader doesnt need to crawl through the projects little and unstruc
tured documentation or Camels API specification, to be able to follow the evaluation of Camel
regardingitsimplementationoftheEnterpriseIntegrationPatterns[HW03]inchapter3below.
Apache Camel is a routing and mediation engine which implements the Enterprise Integration
Patternsfrom[HW03].Itprovidesaframeworkwhichcanbeusedtointegratedifferentapplica
tionsusingtheEnterpriseIntegrationPatternsanditcanbeusedasaroutingandmediationen
gineforthefollowingApacheprojects:
ApacheActiveMQ,anopensourcemessagebroker[Act]
ApacheCXF,anopensourcewebserviceframework(JAXWS)[Cxf]
ApacheMINA,anetworkingframework[Min]
ApacheServiceMix,anopensourceESBandJBIcontainer[Ser]
TheCamelenginecanrunasastandaloneJavaApplicationorcanbedeployedasaJBIcomponent
intoApache ServiceMix. SinceActiveMQ 5.0 [Act] it is also possible to run the Camel Engine in
ActiveMQs broker process. For details about the integration of Camel in ServiceMix and Acti
veMQ see the respective project pages documentation. To configure the routing and mediation
rulesCamelsupportstwoapproaches.OneapproachistoconfigureCamelviaSpring[Spr]based
XMLConfigurationfiles.TheotherapproachistoconfigureCamelviaCamelsJavabasedDomain
SpecificLanguage(DSL),wheretheconfigurationisdonebychainedJavamethodcallsinafashion
thattheproducedJavacodeiseasilyhumanreadable,thusCamelsDSLisalsocalledFluentAPI
(SeeListing2belowforanexampleoftheFluentAPI).Witheitherapproachtheconfigurationis
facilitatedtroughsmartcompletionoftheroutingrulesbyeithertheXMLortheJavaeditor.Dueto
the time constraints of this work, and since theApache Camel developers recommend using the
Java DSL in preference over the Spring based XML configuration because it is more expressive
andoffersmaximumsmartcompletionbytheIDEthefocusofthisworkisontheconfiguration
ofCamelviaitsJavaDomainSpecificLanguage.

APACHECAMELFUNDAMENTALS

2.2

Apache Camels Architecture

Figure1belowgivesanoverviewofCamelsarchitecture.ThemainbuildingblocksofCamelare
Components, Endpoints and Processors. Endpoints and Processors are wired together to Routes.
Routes represent the routing and mediation rules and are added to a Camel Context which is a
containerforthewholeconfiguration.Thefollowingparagraphsexplainthesebuildingblocksin
moredetail.

Figure1:ApacheCamelsArchitecture[Cam]

2.2.1

Camel Components and Endpoints

Tobeabletointegratewithdifferentapplicationsondifferentplatforms,ApacheCamelsupports
multiple so called Components, where each of these Components enablesApache Camel to send

2.2ApacheCamelsArchitecture

andreceivemessagesusingacertainprotocolormiddlewareforexampleamessagebroker.Some
commonComponentsare:
TheJMSComponentwhichenablesApacheCameltoconnecttoanyJMSprovider.
TheFileComponentwhichenablesCameltoreadfilesfromafilesystemortowritemessages
asfilestoafilesystem.
The DirectComponent where a message producer directly, i.e. synchronously, invokes the
messageconsumers.
The SEDAComponent which implements inmemory blocking queues to be able to produce
andconsumemessagesasynchronously.
ForalistofthecurrentlysupportedcomponentsrefertoCamelsprojectpage[Cam].AComponent
actsasconnectortoothersystemsormiddlewareandisessentiallyafactoryforCamelEndpoints,
to which messages can be sent and from which messages can be received. In that sense Camel
EndpointsrepresentachannelasintheChannelpatternfrom[HW03].ACamelEndpointcreated
byCamelsJMS ComponentforexamplewouldrepresentaJMSqueueortopic.CamelusesURIs
to identify Endpoints and lazily creates them using the appropriate Component if they dont al
ready exist. This makes it simple to configure routes, as Endpoints dont have to be instantiated
explicitly.TheURIschemeoftheEndpointURIidentifiesthecomponentwhichisresponsiblefor
creatingtheEndpoint.CamelautodiscoversComponentsbytheirscheme.ThereforeaComponent
hastohaveaconfigurationfileintheproperdirectory 1 ,whichhastoresidesomewhereintheclass
path. Alternatively the Component can be registered explicitly with the Camel Context. Compo
nents with a complex configuration are usually registered explicitly with the Camel Context as
seenwiththeJMSComponent(myComponent)inListing2below.
Components always implement the Component 2 interface and are usually not used directly to
create Endpoint instances. Instead the Endpoint instances are created implicitly when an URI is
usedinaRouteorwhenanEndpointforanURIisrequestedfromtheCamel Context.Endpoints
always implement the Endpoint 3 interface and are used as interface for sending and receiving
messages.TheyarepreconfiguredbytheComponenttheyareinstantiatedby,butcanalsobecon
figureddirectlyandusedinroutingrulesinsteadofURIslikeinListing1below.
1
2
3
4
5

SomeEndpointClass myEndpoint
= (SomeEndpointClass) camelContext.getEndpoint("myEndpointURI");
myEndpoint.setSomething("aValue");
from(myEndpoint).to("anotherEndpointURI")
Listing1:ConfiguringEndpoints

META-INF/services/org/apache/camel/component/
org.apache.camel.Component
3org.apache.camel.Endpoint
1
2

APACHECAMELFUNDAMENTALS

The sending and receiving of messages to and from Endpoints is done via Producer 1 and
Consumer 2 instancescreatedbyanEndpoint.AConsumerconsumesmessagesfromanEndpoints
underlying channel. Camel supports the Eventdriven Consumer pattern by using the
createConsumer(Processor)method,whichcreatesaConsumerinstance,invokingthesup
pliedProcessor 3 onmessagearrival.CamelalsosupportsthePolling Consumerpatternbyus
ing the createPollingConsumer() method, which creates a PollingConsumer 4 that can be
polledfornewmessagesinablockingorinanonblockingway.
A Producer adds messages to an Endpoints underlying channel and is implemented in Camel
trough the Producer3 interface which offers methods for the creation of Exchanges (see 2.2.2
CamelExchangeandMessagebelow)andamethodforthesendingoftheseExchanges.Itisimpor
tanttonotethatthesendingofExchangesisdoneviatheprocess()methodoftheProcessor3
interface.ThisallowstheusageofaProducerasaProcessorwhichprocessesmessagesbyadding
themtotheEndpointsunderlyingchannelandwhichalsosetstheExchangesoutputmessageto
thereceivedresponsemessageincaseofin/outexchangepatterns,likerequest/replyexchangesfor
example.

2.2.2

Camel Exchange and Message

To support various message exchange patterns, like request/reply message exchanges or event
messages,CamelofferstheExchange 5 interfacewhichbasicallycontainsaninput,outputanda
faultmessage,dependingontheExchangePattern 6 .AnExchangecanalsobeandusuallyis
extendedbyaComponenttoexposetheunderlyingtransportsemanticsofthatComponent.
Theinput,outputorfaultmessagescontainedinanExchangeimplementtheMessage 7 interface
representingtheMessagepatternandbasicallycontainingamessagebodyandacollectionofmes
sage headers. The message body can contain any Java object, but for almost all Components the
messagebodyneedstocontainaserializable 8 object,asthemessagewillleavethesendersaddress
spaceoreventhemachineitoriginatesfrom.

2.2.3

Camel Type Converter

Because some Endpoints always return messages of a certain type the FileEndpoint 9 for ex
amplealwaysreturnsaninstanceofFile 10 asmessagebodyandbecauseitsquitecommonto

org.apache.camel.Producer
org.apache.camel.Consumer
3org.apache.camel.Processor
4org.apache.camel.PollingConsumer
5org.apache.camel.Exchange
6org.apache.camel.ExchangePattern
7org.apache.camel.Message
8i.e.implementthejava.io.Serializableinterface
9org.apache.camel.component.file.FileEndpoint
10java.io.File
1
2

2.2ApacheCamelsArchitecture

needtoconvertamessagebodytoandfromcertaintypes,Cameloffersanextensibletypeconver
sionstrategyviasocalledTypeConverters.
CamelprovidesthemethodgetBody(Class)intheMessage 1 interface,whichreturnsthemes
sage payload converted to the given type. The conversion is done by the implementation of the
TypeConverter 2 interfacewhichisassociatedwiththecurrentCamelContext 3 .Camelsdefault
implementationoftheconverteristheDefaultTypeConverter 4 classwhichdiscoverstypecon
vertersbysearchingtroughdefined 5 packagesforclassesandmethodswhichareannotatedwith
the @Converter 6 annotation. To support common conversions, Camel provides already some
builtintypeconverters.

2.2.4

Camel Processor

Another building block ofApache Camel, besides the Component, is the Processor which, as the
name indicates, processesmessages.AProcessor is handed overan Exchange(i.e. a message) by
theCamelengine,andafterprocessingit,CamelsendstheExchangetoachannelorinvokesthe
following Processor. This seems to follow the PipesandFilters pattern, where the pipes are the
channels represented by the Camel Endpoints and the filters are the Camel Processors. And in
deed,ifappliedinaproperway,itimplementsthePipesandFilterspattern.Butitisalsopossible
tochainCamelProcessorsdirectlywhereoneProcessordirectlyinvokesthenext,whichviolates
thePipesandFilterspattern.Thisisdiscussedindetailinchapter3.3below.ACamelProcessor
canalsoperformroutingbydecidingwheretosendamessagetoandthuscanalsobeusedtoim
plementtheRoutingpatterns.
Camel Processors are EventDriven Consumers (as in [HW03]) and implement the Processor 7
interface. Most patterns implemented in Apache Camel are EventDriven Consumers as this
enablestheCamelcontainertomanagepoolingandthreading.Oneofthefewpatternimplementa
tions in Camel which are not EventDriven Consumers is the Aggregator pattern which imple
mentsthePollingConsumerpattern.

2.2.5

Camel Context

ACamel Contextisthecontainerforaspecificintegrationscenarioandrepresentsthatscenarios
routing rule base. It implements the CamelContext 8 interface and contains a collection of all
Component instances used in theintegration scenarioand all specified Camel Routes of the inte

org.apache.camel.Message
org.apache.camel.TypeConverter
3org.apache.camel.CamelContext
4org.apache.camel.impl.converter.DefaultTypeConverter
5Thepackagestobesearchedhavetobedefinedinthefollowingfile:
META-INF/services/org/apache/camel/TypeConverter
6org.apache.camel.Converter
7org.apache.camel.Processor
8org.apache.camel.CamelContext
1
2

APACHECAMELFUNDAMENTALS

gration scenario. The Routes define the processing used on inbound message exchanges from a
specific Endpoint. To add Routes to a Camel Context using the Java DSL aka FluentAPI, Camel
provides the RouteBuilder 1 class, which can be used, as in the example in listing 2 below, to
createRoutes.
Camel provides a simple Service 2 interface for managing Camels lifecycle. The interface pro
videstwomethods,thestart()andthestop()method.MostComponentsandEndpointsim
plementthisinterfaceanditstheCamelContextstasktostartallthenecessaryserviceswhenthe
Camelengineisstarted.TheCamelContextitselfimplementstheServiceinterfacewhichisused
tostarttheCamelengineasseenintheexampleinlisting2below.
CamelalsosupportsaregistrypluginstrategywhichallowsCameltoretrieveCamelProcessors
or Endpoints for example from a registry. The Registry 3 is associated with the Camel Context
and can be replaced by any registry provider implementing this interface. Camel offers builtin
supportforJNDIasaregistry.

2.2.6

Camel Domain Specific Language / Fluent API

Asmentionedbefore,CameloffersaJavaDomainSpecificLanguage(DSL)alsoknownasFluent
APIwhichallowsthewritingofroutingrulesinaneasilyhumanreadableformatsupportedbythe
Javadevelopmentenvironmentssmartcompletioncapabilities.CamelsDSLisveryexpressiveas
itallowstomixowncodewiththeDSLbyusingcustomProcessors,ExpressionsandPredicatesas
itwillbedemonstratedlater.
Expressions are used in Camels DSL to configure dynamic rules, where they offer evaluation of
messageexchanges.TheRecipientListPatternforinstanceusesanExpressionforgettingthereci
pient list contained in a message. Camel comes with already builtin support for a variety of ex
pressionlanguageslikeXPath[CD99]forexample,whichisimplementedintheXPathBuilder 4
class.
InadditiontoExpressions,CameloffersalsoPredicatesinitsDSLtocheckifamessageexchange
hasacertainproperty.AsfortheExpressions,Camelalsooffersbuiltinsupportforpredicatelan
guages, one of them is XPath implemented in the XPathBuilder class. Message Filters, for ex
ample,usePredicatestodecidewhetheramessageshouldbeforwardedorfiltered.

2.2.7

Camel Routes

RoutesarerulestoconfigurehowCamelprocessesincomingmessages.ARouteisachainofCa
mel Processors, implemented by the Pipeline 5 class, where the result of one Processor is the

org.apache.camel.builder.RouteBuilder
org.apache.camel.Service
3org.apache.camel.spi.Registry
4org.apache.camel.builder.xml.XPathBuilder
5org.apache.camel.processor.Pipeline
1
2

2.3AsimpleCamelexample

inputofthefollowingProcessorandsoontillthelastProcessorisreachedandthePipelinere
turnsfromitsprocess()methodinvocation.ThefirstelementofarouteisalwaysaConsumer
ofanEndpointwhichinvokesthePipeline.ItisimportanttoknowthatthePipelinereturnsonly
afterthewholeroutei.e.thewholeprocessingchainhasbeenprocessed,whichmeansthatthe
Consumer of an Endpoint is only done processing an Exchange after the message has been
processedbythewholeroute.Thisisimportantfirstinordertoprocessrequestresponsemessage
exchangeswhicharereturnedtotheconsumer.Andsecondtoensurethatamessageisonlysuc
cessfullyconsumedaftertheprocessingbythelastprocessor,whichisusuallyanEndpointsPro
ducer,isfinished.

2.3

A simple Camel example

The code in listing 2 below shows a simple example of Apache Camel, where messages are re
ceivedfromtheJMSqueue'test.queue',processedbytheProcessor'myProcessor'andput
inthe'testFolder'.AsmentionedbeforetheCamelContextisthecontainerofourintegration
scenario,soourexamplestartswithcreatingaCamelContext(line1),thenaddsaComponentto
it(line9),thenaddsRoutestoit(line11)andfinallytheCamelContextisexecutedfor10minutes
(lines3638).
In this example two Components are used: the 'myComponent'Component which is explicitly
registeredwiththeCamelContextandthe'file'Componentwhichisautodiscovered.Onecan
alsoseehowEndpointsarereferencedbytheirURIsandcreatedimplicitlybyCamel.Lines29to
31demonstratehowtheusageofCamelsDSLakaFluentAPIcreateshumanreadableandeasyto
understand code. The Processor in this example is defined in lines 16 to 25 and doesnt alter the
messagesitprocesses,butsimplyprintsthemessagebodiestotheconsole.TheProcessorscustom
implementation also shows how the type conversion mentioned above is used to get a String
representationofthemessagebody(line22).

APACHECAMELFUNDAMENTALS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

CamelContext context = new DefaultCamelContext();


// explicitly add a JMS Component which connects to the
// ActiveMQ server 'myServer' on port 61616:
ConnectionFactory connectionFactory
= new ActiveMQConnectionFactory("tcp://myServer:61616");
Component myComponent
= JmsComponent.jmsComponentAutoAcknowledge(connectionFactory);
context.addComponent("myComponent", myComponent);
context.addRoutes(new RouteBuilder() {
public void configure() {
// create a message processor:
Processor myProcessor = new Processor() {
public void process(Exchange e) {
// get the inbound request message:
Message inboundMessage = e.getIn();
System.out.println("Processing message: "
+ inboundMessage.getBody(String.class));
}
};
// take messages from the JMS-Queue 'test.queue', process
// them and put them into the folder 'testFolder':
from("myComponent:queue:test.queue")
.process(myProcessor)
.to("file://testFolder");
}
});
context.start();
Thread.sleep(600000); // wait for 10 minutes
context.stop();
Listing2:SimpleCamelexample

10

EAI Patterns in Apache Camel

InthischapterApacheCamelisevaluatedregardingwhichoftheEnterpriseIntegrationPatterns
[HW03]areimplementedinCamel,towhatextenttheyareimplementedandiftheimplementa
tioniscorrectaccordingtotheirdefinitioninHohpesandWoolfsbookonEnterpriseIntegration
Patterns[HW03].
Because the Camel Project is relatively young and thus has only a rudimentary and incomplete
documentation,theevaluationhasmostlybeendonebyreadingCamelsAPIspecificationinform
of JavaDocs and by reading through Camels implementation itself. Also it has to be mentioned
that the evaluation is based on the latest Camel release at the time of this work, which is release
1.2.0. This release contains several bugs and is also missing functionality that is implied by the
specification. This fact reflects in the following subchapters in form of comments to Camels im
plementation. At the time of the creation of this work the developing of release 1.3.0 was in
progresswheresomebugsmentionedinthisworkarealreadyfixed.Thisisignoredfortheevalua
tionofthepatternsinthiswork,astheevaluationneededtoreflectonedefinedversionofCamel
forwhichrelease1.2.0waschosen,asthemostrecentrelease.Further,itisimportanttomention
thatCamelsdocumentationdoesntrefertoaspecificreleaseofApacheCamel.Ratherthedocu
mentation is updated continuously without mentioning which release of Camel is actually docu
mented.ThisiseventrueforCamelsAPIdocumentationavailableonline,buttheJavaDocdocu
mentation can also be generated from the source code available online by oneself, resulting in a
consistentAPIspecification.
The evaluation of the different patterns is following the order of their appearance in the book of
Hohpe and Woolf [HW03]. The only difference is that the more generic patterns that form their
ownsubchaptercontainingtheirseveralsubpatterns,liketheMessageChannel,theMessage,the
PipesandFilters,theMessageRouter,theMessageTranslatorandtheMessageEndpointarenot
discussedinanintroductorychapterlikeinthecaseofHohpesandWoolfsbook,butintheirre
spectivesubchapter.
Due to thelimited time frame of thiswork notallpatterns could be evaluated. The patterns that
havebeenskippedhavebeenchosenbecausetheywereeithergooddocumentedinCamelsdocu
mentationortheywereadvancedpatternsoftheirrespectivecategory.Amongthepatternsthatare
not evaluated are also all System Management patterns because they are advanced patterns that
describeadifferentaspectofamessagingsolutionandthuscanbeevaluatedseparately.Thefol
lowingpatternsarenotevaluatedeither:
The Resequencer pattern which is implemented in Camel and has a comparably good docu
mentationontheprojectwebsite.
TheRoutingSlippatternwhichisnotimplementedatallinApacheCamel.

11

EAIPATTERNSINAPACHECAMEL

The Process Manager pattern which goes beyond the scope of Apache Camel and is
covered by workflow engines like the one developed in the Apache ODE project
[Ode].
TheMessageBrokerwhichisanarchitecturalpatternthatis opposed to thePipesand
Filtersarchitectureandisthearchitecturalpattern,thegraphicaleditorandBPELge
nerator of the diploma thesis from Druckenmller on Parameterization of EAI Pat
terns[Dru07],whichwillbeextendedinthiswork,isbasedon.
TheCanonicalDataModelpatternwhichisnotimplementableinApacheCamel,butisrather
apatternthatshouldbefollowedbythearchitectofamessagingsolution.
The Transactional Client pattern which is implemented in Camel using Spring transactions
andisacomplexpatternthatneedsadeepevaluation

3.1

Messaging Channels

TheMessageChannelpatternisnotexplicitlyimplementedinApacheCamelinsteadthemessage
channels are provided by the underlying middleware, the operating system or are implemented
completelyinCameldependingonthekindofchannel.WhatCameldoesisprovidingacommon
interface to address and access channels using Endpoints, which are usually identified and ad
dressedbytheirURI.Asexplainedinchapter2.2CamelsupportsdifferentComponentsforinte
grating with different systems. These Components create Endpoints which all implement the
Endpoint 1 interface, providing a unified interface for accessing the channels of the underlying
infrastructure. This can be a channel, implemented by a JMS queue and accessed through the
JmsEndpoint 2 ,aswellasachannelimplementedasadirectoryinafilesystem,accessedthrough
theFileEndpoint 3 .

3.1.1

Point-to-Point Channel

As mentioned above, the Messaging Channels are not explicitly implemented in Apache Camel
butareprovidedbyComponents.AcommonComponentthatenablesApacheCameltousemany
different messagequeuing systems viaJMS[HBS+] is theJMS Component. The JMS Component
provides PointtoPoint Channels as Endpoints1 on JMSQueues. These Endpoints are refe
rencedviaURIsofthefollowingformat:

org.apache.camel.Endpoint
org.apache.camel.component.jms.JmsEndpoint
3org.apache.camel.component.file.FileEndpoint
1
2

12

3.1MessagingChannels

"jms:queue:myQueueNameA"
AnotherComponentthatoffersPointtoPoint ChannelsisCamelsSEDA Componentwhichof
fersaccesstoinmemoryqueues.

3.1.2

Publish-Subscribe Channel

Like for the PointtoPoint Channel also the PublishSubscribe Channel is provided by Camel
Components.TheJMSComponentprovidesPublishSubscribeChannelsasEndpoints 1 onJMS
Topics[HBS+].TheDirectComponentalsoimplementsaPublishSubscribe Channel,asallCon
sumersregisteredonaDirectEndpointreceiveallmessagessenttothatEndpoint.TheJMSTopics
areaddressedusingEndpointURIsofthefollowingformat:
"jms:topic:myTopicNameA"

3.1.3

Datatype Channel

TheDatatypeChannelisaconceptualpatternwhichadvicestouseseparatechannelsformessages
withseparatedatatypes.ThispatternisnotimplementedinApacheCamel,butofcourseCamel
canbeusedtoimplementthepatternusingaseparatechannelforeachmessagetype.

3.1.4

Invalid Message Channel

LiketheDatatype Channel,theInvalid Message Channelisaconceptualpattern.Itadvicesmes


sage receivers to put messages they cant process on a dedicated channel: the Invalid Message
Channel. It can be implemented by using any channel available through Camels Components to
whichProcessors 2 sendtheirmessagestheycantprocess.

3.1.5

Dead Letter Channel

TheDead Letter ChannelpatterncangenerallynotbeimplementedinApacheCamelasthisisa


channelwheretheunderlyingmessagingsystemshallputmessagesitcantdeliver.ButasApache

1
2

org.apache.camel.Endpoint
org.apache.camel.Processor

13

EAIPATTERNSINAPACHECAMEL

CamelcanworkwithseveraldifferentComponentswhereofmostofthemdontuseanunderlying
messagingsystem,itcanmakesensetouseanerrorhandlerthatApacheCamelprovideswhichis
called DeadLetterChannel 1 and that can be used to handle errors which occur while a
Processor is processing a message. In fact Camels DeadLetterChannel is the default error
handlerandisconfigurednottosendmessagestoaparticularDeadLetter Channel,buttotryto
redeliverthemessagessixtimes,waitingforonesecondbetweeneachattempt.
TheDeadLetterChannelisparticularlyusefultohandleerrorsofProducers 2 thatdontusean
underlyingmessagingsystemliketheFileProducer 3 whichcouldraiseanexceptionbecauseit
cantdeliveramessageintoafolderbecauseofmissingwritepermissions.Listing3belowshows
howtosetupaDeadLetterChannelFehler! Textmarke nicht definiert.andconfigurearedeliverypolicythat
retries five times to redeliver messages while increasing the delay between the delivery attempts
exponentially,startingfrom0.5seconds.
1
2
3
4
5
6
7
8

from("myComponent:endpointA")
.process(myCustomProcessor)
.errorHandler(
deadLetterChannel("myComponent:myDeadLetterChannel")
.maximumRedeliveries(5)
.initialRedeliveryDelay(500)
.useExponentialBackOff())
.to("file:/path/to/a/directory/without/writing/permission");
Listing3:DeadLetterChannelfornonmessagingsystemcomponents

3.1.6

Guaranteed Delivery

The Guaranteed Deliver pattern is not implemented inApache Camel either, but is provided by
ComponentsliketheJMSComponentthatusespersistentdeliverybydefault,theFileComponent
that stores messages on a filesystem and the JPAComponent which uses a database table as a
messagequeue.

3.1.7

Channel Adapter

The Channel Adapter pattern is not implemented inApache Camel, the contrary is the case: one
canuseCameltoimplementaChannelAdapterforapplicationsthatarewritteninJavabywriting
codethatsendsmessagestoCamelEndpoints.

org.apache.camel.processor.DeadLetterChannel
org.apache.camel.Producer
3org.apache.camel.component.file.FileProducer
1
2

14

3.2MessageConstruction

3.1.8

Messaging Bridge

ApacheCamelcanalsobeusedtoimplementaMessagingBridge,asCamelsupportsmanydiffer
ent Components and can also use the JMSComponent to connect to most messaging systems.A
Messaging Bridgecanbeimplementedbycreatingsimpleroutingrulesthatconnectthedifferent
channelsofthedifferentmessagingsystemsorevenchannelswhicharenotbasedonmessaging
systems.Listing4belowshowshowtherulesforsuchamessagingbridgewouldlooklike.Ifne
cessaryonecouldevenaddsomecustomProcessors 1 totheroutes,thattransformthemessages
tofittherequirementsofthereceivingmessaginginfrastructure.
1
2
3

from("myJmsComponentA:endpointX").to("myJMSComponentB:endpointX");
from("myJmsComponentA:endpointY").to("myJMSComponentB:endpointY");
from("myJmsComponentA:endpointZ").to("file:/my/path/Z");
Listing4:AMessagingBridgeinApacheCamel

3.1.9

Message Bus

CameldoesntimplementtheMessage Buspattern,ratheritcanbeusedtoimplementamessage
bususinganunderlyingmessagingsystemascommoncommunicationinfrastructureandimple
menting the message routing and message transformation using the various patterns which are
implementedinApacheCamel.AsmentionedaboveCamelcanalsobeusedtoimplementChan
nelAdaptersforthoseapplicationsystemsthatareimplementedinJava.

3.2

Message Construction

TheMessagepatternisimplementedinCamelbytheMessage 2 interface.InCamelmessagesare
alwayswrappedbytheExchange 3 interfacetooffersupportfordifferentmessageexchangepat
ternslikerequestreplyoronewaymessaging.Thesimplestexchangepatternwhichisalsooften
usedistheInOnly 4 patternforonewaymessaging.Inthiscasethemessagecanbeobtainedby
thegetIn()methodoftheExchangeinterface.

org.apache.camel.Processor
org.apache.camel.Message
3org.apache.camel.Exchange
4org.apache.camel.ExchangePattern.InOnly
1
2

15

EAIPATTERNSINAPACHECAMEL

3.2.1

Command / Document / Event Message

AsHohpeandWoolfindicateintheirbook[HW03]therearenospecialmessagetypesforaCom
mandMessage,DocumentMessageoranEventMessage.Ratherthecontentofamessagemakesit
what it is, i.e. a Command Message is a message that contains a command. Thus Camel doesnt
implementthesepatterns;itisratherthearchitectsliabilitytocreateandusemessagesaccording
tothepatterns.

3.2.2

Request-Reply

TheRequestReplypatternistheoreticallyimplementedbyCamelsExchange 1 interfacewhichis
anabstractionofamessageexchangelikearequestanditscorrespondingreplymessage.Touse
the RequestReply pattern the Exchange, which contains the request message, has to be created
using Camels InOut 2 exchange pattern. Usually this is done by invoking the Endpoints 3
createExchange(ExchangePattern.InOut) method. Exchanges, created using the InOut
exchangepatternshouldthencontaintherequestmessageastheExchanges In 4 messageand
thereceiverthenwritesitsreplymessagetotheExchanges Out 5 message.
AtthetimeofthecreationofthisworkalmostnoComponentsupportstheInOut2exchangepat
tern and thus the RequestReply pattern. The JMSComponent doesnt implement the InOut ex
change pattern, neither does the SEDA Component. Then again the Direct Component does im
plementit,asitsynchronouslypassestheExchangeinstancetothereceiver.Toaddsupportfor
the InOut exchange pattern to a Components Producer 6 , that sends a message and would re
ceive the reply asynchronously, the Producer has to add a Return Address (see 3.2.3 ReturnAd
dress) to the messages header and listen on the corresponding channel. In case of the JMS
Component this could be implemented using the JMSReplyTo header specifying a temporary
JMSdestination [HBS+] the reply is expected on. While waiting for the reply message the
Producerhastoblockaftersendingtherequestmessage.Tosupportalsoasynchronouscallback
as described by Hohpe and Woolf [HW03] a Producer could also implement the
AsyncProcessor 7 interfacewhichofferssuchacallbackmechanism.
Listing 5 below demonstrates how the RequestReply pattern is used inApache Camel.As men
tionedbeforethisexampleonlyworkswithComponentsthatsupporttheInOutexchangepattern.

org.apache.camel.Exchange
org.apache.camel.ExchangePattern.InOut
3org.apache.camel.Endpoint
4Viatheorg.apache.camel.Exchange.getIn()method
5Viatheorg.apache.camel.Exchange.getOut()method
6org.apache.camel.Producer
7org.apache.camel.AsyncProcessor
1
2

16

3.2MessageConstruction

1
2
3
4
5
6
7

Endpoint myEndpoint = context.getEndpoint("myComponent:endpointA");


Producer myProducer = myEndpoint.createProducer();
Exchange myExchange = myEndpoint.createExchange(ExchangePattern.InOut);
Message request = myExchange.getIn();
request.setBody("my request body"); // create the request
myProducer.process(myExchange); // send the request
Message response = myExchange.getOut(); // get the response
Listing5:RequestReplyinApacheCamel

3.2.3

Return Address

Asmentionedabove(Chapter3.2.2)theReturnAddressisimplicitlyimplementedbyApacheCa
melsEndpointsProducers 1 .IfmessageexchangesaresentusingtheInOut 2 exchangepattern
whichcorrespondstoarequestreplypair,thentheEndpointsProducerhastotakecareofadd
ingareturnaddresstothemessageheader,listenonthechannelcorrespondingtothereturnad
dressandreturnthereceivedreplymessageviatheExchange 3 interface.

3.2.4

Message Expiration

TheMessage ExpirationpatternisnotimplementedinApacheCamelbutmaybeprovidedbya
Components underlying messaging system. For example the JMSComponent provides message
expiration which can be set either as default for all Endpoints of a JMSComponent via its
setTimeToLive()methodorperEndpointviatheEndpointURIasinlisting6below.
TocorrectlyimplementtheMessage ExpirationpatterntheComponentsConsumer 4 shouldalso
discardexpiredmessages(orputthemonthedeadletterqueue)itreceived.Thisiscurrentlynot
thecaseforCamelsJMSComponent.
....to("jms:queue:myDestination?timeToLive=5000");
Listing6:MessageExpirationforJMSEndpointsinApacheCamel

org.apache.camel.Producer
org.apache.camel.ExchangePattern.InOut
3org.apache.camel.Exchange
4org.apache.camel.Consumer
1
2

17

EAIPATTERNSINAPACHECAMEL

3.2.5

Correlation Identifier / Message Sequence / Format Indicator

The Correlation Identifier, Message Sequence and the Format Indicator pattern are not imple
mentedinApacheCamel,buttheycanbeimplementedbysettingappropriateheadersonthepro
ducer side and evaluating them on the consumer side. Headers are namevalue pairs, which are
addedtomessagesusingthesetHeader()methodoftheMessage 1 interface.

3.3

Pipes and Filters

Camel supports the PipesandFilters pattern using two different approaches, whereas the ap
proach explained in Camels documentation does not correctly implement the PipesandFilters
pattern. The approach according to Camels documentation makes use of the Pipeline 2 class
whichisofferedbyCamelandwhichisaCamelProcessordelegatingtheprocessingofmessage
exchangestoachainofsubprocessors.WeathertheProcessorsinthePipelineareprocessingmes
sagesasrequestresponse,i.e.usingtheExchangesoutmessage,ormodifytheoriginalmessage,
i.e.theinmessage,doesntmatter,asCamelsPipelinehandlesthisaccordingly.
CamelsJavaDSLalsosupportstheusageofthePipeline2classviathepipeline()methodas
usedinlisting7below.IncontrasttothePipelineclasswhichsupportsalistofProcessors 3 as
members,theJavaDSLspipeline()methodsupportsonlyEndpoints 4 whoseProducersare
usedasmemberProcessorsinthePipeline(seechapter2.2CamelComponentsandEndpointsfor
details about Producers). But this is no drawback, as Camels Direct Component can be used (as
seeninlisting7below)toinvoketheFilterProcessors.CamelsDirectComponentisimplemented
such,thatProducersonDirect EndpointssynchronouslyinvoketheConsumersoftheaccording
Endpoint.CamelsdocumentationsuggestexactlythisimplementationusingthePipelineclass
in conjunction with Direct Endpoints as seen in listing 7 below but this implements the Pipes
andFilters pattern only in the broader sense as the pipe is only implemented as a synchronous
method call and is thus lacking the concept of a queue which would decouple the processing of
onefilteranditspredecessor/successor.Whetherthisisaninmemoryqueueoranentiremessage
oriented middleware wouldnt matter for the correct implementation of this pattern. Tightly
coupledlikethat,onlyonemessagecanbeprocessedbythepipelineatthesametimeinsteadof
beingabletoprocessseveralmessagesinparallel,eachmessagebeinginanotherstage.Thiscould
be compensated by configuring Camel to use several threads for executing the Pipeline. But this
wouldstillnotofferthesamesemanticsasqueuebasedpipeswouldofferandwhichisintended
bythePipesandFilterspattern.

org.apache.camel.Message
org.apache.camel.processor.Pipeline
3org.apache.camel.Processor
4org.apache.camel.Endpoint
1
2

18

3.3PipesandFilters

1
2
3
4
5
6
7
8
9
10

// create the routes for the filters:


from("direct:endpointFilter1").process(myFilter1Processor);
from("direct:endpointFilter2").process(myFilter2Processor);
from("direct:endpointFilter3").process(myFilter3Processor);
// create the pipeline route:
from("direct:endpointA").pipeline("direct:endpointFilter1",
"direct:endpointFilter2",
"direct:endpointFilter3",
"direct:endpointB");
Listing7:ApacheCamelsapproachtothePipesandFilterspattern
The intuitive approach of using an asynchronous Component like Camels SEDA Component in
steadofasynchronousonelikeCamelsDirectComponentdoesntresultintheintendedgoal.This
is because Camels asynchronous Components are lacking the support of InOut message ex
changes.Using Camels current implementation ofasynchronous Components, the processing by
an asynchronous Producer 1 would only add the message to the Endpoints channel and return
without awaiting a response which should then be added to the Exchanges outmessage. This
would make the Pipeline 2 call the next Processor 3 with the unmodified message which in
turnwouldonlyaddthemessagetoachannel.Thisresultsinaprocessingwhereneitherthere
sulting message of one filter is passed to the next filter nor the filters are executed consecutively
butpossiblyinparallel.ThiswouldnthaveanythingtodowiththePipesandFilterspatternan
ymore.Intheappendixanexamplecanbefoundwherethisisdemonstrated(A.1Camelexample
usingbuiltinPipeline).
The second approach is simple and exactly implements the PipesandFilters architecture. It just
consistsinusingseveralroutingrules,oneforeachfilterinthePipesandFilterschain.Onlytwo
thingshavetobetakenintoaccountusingthisapproach.FirsttheEndpointsusedhavetobeim
plementedbyanasynchronousComponent,becauseotherwisethesamedrawback,asinthepre
viousapproach,wouldapply.Namelythelackofthedecouplingofthefiltersbyaconceptlikea
queue would result in an implementation not strictly following the PipesandFilters pattern.
Second all Processors must read received messages from an Endpoint and send to another End
point, i.e. two Processors must never be chained directly together. Using this approach the in
tendedpipelinefromtheexampleinlisting7abovewouldlookasseeninlisting8below.

org.apache.camel.Producer
org.apache.camel.processor.Pipeline
3org.apache.camel.Processor
1
2

19

EAIPATTERNSINAPACHECAMEL

1
2
3
4
5
6
7

// create the pipeline routes:


from("seda:endpointA").process(myFilter1Processor)
.to("seda:endpointFilter2");
from("seda:endpointFilter2").process(myFilter2Processor)
.to("seda:endpointFilter3");
from("seda:endpointFilter3").process(myFilter3Processor)
.to("seda:endpointB");
Listing8:PatternconformapproachtothePipesandFilterspattern

3.4

Message Routing

CamelsupportsmostMessageRoutingpatternstheyaredescribedinthefollowingsubchapters.
Themosttrivialrouter,whichisafixedrouterthatforwardsallmessagestoafixedoutputchan
nel,isimplementedinApacheCamelbysimpleusageoftheJavaDSLasseeninlisting9below.
This fixed route can be useful if the decoupling of two Endpoints is required, for example to re
servethepossibilitytoreplacethesimpleroutethroughamoresophisticatedRouterlater,orifa
MessagingBridgeistobeimplemented.
from("myComponent:endpointA").to("myComponent:endpointB");
Listing9:FixedrouteinApacheCamel

3.4.1

Content-Based Router

ApacheCamelsupportstheContentBased RouterpatternbytheuseofitsChoiceProcessor 1 ,
whichisimplementedbymanagingalistofFilterProcessors.AFilterProcessor 2 isawrapper
classforProcessorsandalsocontainsaPredicate 3 thatisusedtoevaluateExchanges.TheFilter
ProcessordelegatesthemessageprocessingtoitswrappedProcessoronlyifitsPredicateappliesto
thatmessage.TheChoice ProcessorperformstheroutingbyiteratingtroughitslistofFilter Pro
cessorsandchoosingthefirstProcessorinthelistwhosePredicatematchesthemessagesubjectto
routing.IfnoneofthePredicatesinthelistmatches,theChoiceProcessordelegatestheprocessing
toitsassociatedOtherwiseProcessor.
EventhoughtheChoiceProcessorusesalistofFilterProcessorsforitsimplementation,itcorrectly
implementstheContentBased RouterpatternasitjustusestheFilter ProcessorsPredicateasa
containerforProcessorPredicatepairs.Itsimplementationperformspredictiveroutingasrequired

org.apache.camel.processor.ChoiceProcessor
org.apache.camel.processor.FilterProcessor
3org.apache.camel.Predicate

1
2

20

3.4MessageRouting

bytheContentBased Routerpatternincontrasttoareactivefilteringapproachbytheuseofsev
eral Message Filters. The only critique to Camels implementation is that it discards messages if
noneofthePredicatesmatchandnoOtherwiseProcessorisdefined,insteadofputtingthosemes
sagesonaDeadLetterChannelorhandlingthemsomehow.
CamelalsosupportstheChoiceProcessorviaitsJavaDSLasdemonstratedinlisting10below.
1
2
3
4
5

from("myComponent:endpointA").choice()
.when(myPredicate1).to("myComponent:endpointB")
.when(myPredicate2).to("myComponent:endpointC")
.when(myPredicate3).to("myComponent:endpointD")
.otherwise().to("myComponent:endpointE");
Listing10:ContentBasedRouterinApacheCamel

3.4.2

Message Filter

The Message Filter is implemented in Apache Camel using the FilterProcessor 1 class. As
mentioned above the Filter Processor processes messages only if the associated Predicate 2
matches a message and discards it otherwise. The Filter Processor is also integrated in Camels
JavaDSLusingthefilter()methodsasdemonstratedinlisting11below.
CamelsFilter Processorsupportsonlystatelessfiltering.Ifstatefulfilteringisrequired,asforthe
filteringofduplicatemessages,theFilterProcessorwouldhavetobeextended.Butinthiscasethe
JavaDSLwouldhavetobeextendedtoo,tosupportthestatefulMessageFilteroritwouldhaveto
bewiredtotheEndpointswithouttheuseoftheJavaDSL.
6
7

from("myComponent:endpointA").filter(myFilterPredicate)
.to("myComponent:endpointB");
Listing11:MessageFilterinApacheCamel

3.4.3

Dynamic Router

The Dynamic Router pattern is not implemented at all inApache Camel. It can be implemented
thoughbyextendingtheChoiceProcessor 3 classbyaddingasubprocessorforhandlingcontrol
messagesandbyaddingadynamicrulebasewhichcouldbepersistedforexamplebyusingthe
Java PersistenceAPI (JPA). Even though such a DynamicRouterProcessor would not be sup

org.apache.camel.processor.FilterProcessor
org.apache.camel.Predicate
3org.apache.camel.processor.ChoiceProcessor
1
2

21

EAIPATTERNSINAPACHECAMEL

porteddirectlyinCamelsJavaDSLitcouldstillbeusedintheDSLwithouthavingtomodifythe
DSL. Listing 12 below demonstrates how the use of an extended ChoiceProcessor 1 class
(named DynamicRouterProcessor in the listing), which persists its rule base via the JPA and
usesauniquerulebasenametoidentifyitsassociatedrulebase,couldlooklike.Inthelistingthe
constructortakesEndpointURIsasparametersforthecontrolmessagechannelandtheotherwise
channeltosupporteasyusageinCamelsJavaDSL.Butitshouldbenotedthatforanimplementa
tion to be consistent with Camels architecture, such a DynamicRouterProcessor class should
alsohaveaconstructorthattakesProcessor 2 instancesasparametersinsteadofEndpointURIs.
1
2
3
4
5

from("myComponent:endpointA").process(
new DynamicRouterProcessor("myComponent:controlEndpoint",
"rulebase-test1",
"myComponent:otherwiseEndpoint")
);
Listing12:PossibleimplementationoftheDynamicRouterpattern

3.4.4

Recipient List

ApacheCamelsupportstheRecipientListPatternbyasimpleclass,theRecipientList 3 class,
which implements the Recipient List by using an Expression which evaluates the message ex
changes and outputs a list of recipients as EndpointURIs. The Expression can be created using
any of Camels builtin Expression 4 classes, for example by the XPathExpression 5 class, or
canbeacustomExpressionclass.TheonlyconstraintsuchanExpressionhastofulfillisthatit
hastoreturnthelistinoneofthefollowingformats:
AsaCollection 6 ofEndpoints 7 orofStringrepresentationsofEndpointURIs
AsanArrayofEndpointsorofStringrepresentationsofEndpointURIs
AsaNodeList 8
AsasingleEndpointorasingleStringrepresentationofanEndpointURI
Camels Recipient List implementation iterates through the list gained from the Expression and
sendsacopyofthemessageexchangetoeachchannelrepresentedbyanEndpointinthelist.
Thesendingofthemessagesisimplementedsequentially,dependingontheEndpoints.Aparallel
implementationcouldbeconsidered,whichisnotavailableinApacheCamel.

org.apache.camel.processor.ChoiceProcessor
org.apache.camel.Processor
3org.apache.camel.processor.RecipientList
4org.apache.camel.Expression
5org.apache.camel.model.language.XPathExpression
6java.util.Collection
7org.apache.camel.Endpoint
8org.w3c.dom.NodeList
1
2

22

3.4MessageRouting

IncasetheEndpoints ProducersmodifytheExchangewhileprocessing,likeitcanbethecaseif
the Direct Component is used, then the resulting Exchange of letting a Recipient List process a
message, would be the result returned by the last Endpoint in the list. Even if this possibility is
implemented, it wouldnt be of any use to process the result returned by a Recipient List and is
thususuallynotdone.
CamelsJavaDSLalsosupportsthispatternbyusingtherecipientListmethodasdemonstrat
ed in listing 13 below. Note that for the reasons just mentioned it is not common to append the
to()expressiontotheroutingruleseeninlisting13below.
from("myComponent:endpointA").recipientList(myExpression);
Listing13:RecipientListinApacheCamel
ADynamic Recipient Listasdescribedby[HW03]isnotimplementedinApacheCamel,butthe
existingRecipientListcouldbemadedynamicbyimplementingacustomExpression,whichuses
a persisted rule base that can be modified through control messages to evaluate a message ex
changesimilartotheDynamicRouterdescribedinchapter3.4.3above.

3.4.5

Splitter

The Splitter pattern is implemented in Apache Camel by the Splitter 1 class, using an
Expression 2 to get a list of the split message parts which are then processed by the Splitters
child Processor. Camels Splitter also supports an AggregationStrategy 3 which it uses to
aggregatetheresultsoftheprocessingofthedifferentmessageparts.Thisfeatureisnotpartofthe
Splitterpatternfrom[HW03],butcanbeusefulinconjunctionwithInOut 4 Exchangeswherethe
SplitterreturnstheaggregatedmessageasresponsetoamessagesenttotheSplitter.Thisispar
ticularlyusefulforasimpleimplementationoftheScatterGatherpattern.Astheactualsplittingis
done by an Expression, the Splitter class can be used to implement Iterating Splitters as
well as Static Splitters (see [HW03]). The message parts split by the Expression are then all
processedbytheSplitterschildProcessor,whichmeans,incaseofProducersaschildProcessors,
thatallmessagepartsareaddedtotheProducerscorrespondingMessage Channel.Similartothe
Recipient Lists Expression, also the Expression of the Splitter needs to return a list of message
partswhichhastobeofoneofthefollowingformats:
ACollection 5 ofmessagebodies(i.e.arbitraryJavaObjects)
AnArrayofmessagebodies

org.apache.camel.processor.Splitter
org.apache.camel.Expression
3org.apache.camel.processor.aggregate.AggregationStrategy
4org.apache.camel.ExchangePattern.InOut
5java.util.Collection

1
2

23

EAIPATTERNSINAPACHECAMEL

ANodeList 1
Asinglemessagebody
TheSplittercopiesallheadersfromthesourcemessagetothesplitmessageparts,thusalsoinclud
ingpossiblecorrelationidentifiers,andalsoaddstwonewheaders:
TheSPLIT_SIZE 2 headerwhichindicatesintohowmanypartstheoriginalmessagewassplit.
The SPLIT_COUNTER 3 header which is a sequence number ranging from zero to
(SPLIT_SIZE2 1),andindicatestheorderofthemessageparts,originatingfromthesame
sourcemessage.
Thefactthatthemessageheadersarecopiedandthatthetwomentionedheadersareadded,can
simplifythetaskoftheAggregatorifusedinconjunctionwiththeSplitterpatterntoimplement
theScatterGatherpattern.
LiketheRecipientList,theSplitterprocessesthemessagepartsinsequence,butespeciallyifcom
plexmessageProcessors(i.e.longrunningones)areused,itisdesirablethatallmessagepartsare
processed in parallel. Parallel processing is not implemented in Camels Splitter, but can be
achieved using Producers of Endpoints as Processors that run quickly to decouple the message
Processors from the Splitter. For example the SEDAComponent that uses inmemory queues or
theJMSComponentthatjustsendsamessageusingitsunderlyingmessagingmiddlewarecould
be used.And despite the parallel processing, the PipesandFilters architecture requires anyway
thedecouplingoftheSplitterfromitsfollowingProcessors(i.e.filters).
Like the other patterns also the Splitter is integrated in Camels Java DSL and can be used with
eitheracustomExpressionorwithanExpressioncreatedbyCamelsbuiltinexpressionlanguag
es.Listing14belowshowshowtheSplitterisusedwithCamelsJavaDSL.
1
2
3

from("myComponent:endpointA")
.splitter(mySplitterExpression)
.to("myComponent:endpointB");
Listing14:SplitterinApacheCamel

3.4.6

Aggregator

TheAggregatorpatternisnotfullyimplementedinApacheCamel,butCamelcanbeextendedto
fully support the Aggregator pattern. Camels Aggregator is implemented in the Aggregator 4
classwhichis,unlikemostotherpatternimplementationsbyCamel,aPollingConsumerthatthus
runsinitsownthread.CamelsAggregatorusesaCorrelationExpressiontocorrelatetheincoming

org.w3c.dom.NodeList
org.apache.camel.processor.Splitter.SPLIT_SIZE=org.apache.camel.splitSize
3org.apache.camel.processor.Splitter.SPLIT_COUNTER=org.apache.camel.splitCounter
4org.apache.camel.processor.Aggregator
1
2

24

3.4MessageRouting

messagesandthusforbeingabletodecidewhichmessagesbelongtogetherandshouldbeaggre
gated. The Correlation Expression can be any Expression 1 and needs to return an arbitrary
Object 2 thatuniquely identifies the group of messages toaggregate. This Correlation Identifier
Objectreturnedneedstobeequal,inthesenseoftheObjectsequals()method,toallother
Objectsreturnedformessagesthatbelongtogether.CamelsAggregatorperformstheactualag
gregationofthemessagesthroughtheAggregationStrategy 3 interfacewhoseaggregate()
methodneedstobeimplementedtosupplytheAggregatorwithanaggregationstrategy.Theag
gregationstrategyisusedbyinvokingtheaggregate()methodwithtwoparameterseachtime
a new message arrives. One parameter is the current aggregate (i.e. the Exchange 4 which
representsthemessageswithacertainCorrelation Identifierthathavebeenaggregatedtillnow)
andtheotheristhenewlyarrivedExchange4.Theaggregate()methodthenreturnsthenew
aggregate.
ThethirdpropertyofanAggregator,besidesthemessagecorrelationandtheaggregationstrategy,
isthecompletenessconditionwhichisnotimplementedinCamelsAggregator.Camelaggregates
messagestilladefinedamountofmessagesarrivedortilladefinedamountoftimepassed.Butas
themessagecounterandthetimeoutarecommontoallarrivingmessages,insteadofhavingsepa
rateonesforeachaggregate,thisdoesntevenimplementabasiccompletenessconditionbecause
the decision whether an aggregate is complete, does neither depend on how many messages ar
rivedforanaggregate, nor on howlong itis ago that the first messagearrived for an aggregate.
Thusfromanaggregatespointofviewthecompletionissomehowrandom.
To implement a completeness condition the Aggregator 5 can be extended by using a custom
AggregationCollection 6 .TheAggregatorusestheAggregation Collectiontostorehisaggre
gates,anditeratesthroughthecollectionafterthedefinedamountofmessagesarrivedorafterthe
defined amount of time passed, sending all aggregates of the collection to its sub processor. The
Aggregation Collection thereby makes use of the Correlation Identifier Expression and the Ag
gregationStrategymentionedabove.
One way to add a completeness condition to the AggregationCollection could be to extend
the AggregationCollection and to expose only aggregates that are complete, according to a
completeness condition, which could be implemented using Camels Predicates 7 . Using this
approach only the messages exposed to the Aggregator and thus only the complete aggregates
wouldbeforwardedtotheAggregatorschildProcessor 8 .
AnothershortcomingofCamelsAggregatorimplementationisthatitdoesntsupportapersistent
state, namely it doesnt include a persistent implementation of the AggregationCollection.
This shortcoming could also be fixed by developing a custom implementation of the

org.apache.camel.Expression
java.lang.Object
3org.apache.camel.processor.aggregate.AggregationStrategy
4org.apache.camel.Exchange
5org.apache.camel.processor.Aggregator
6org.apache.camel.processor.aggregate.AggregationCollection
7org.apache.camel.Predicate
8org.apache.camel.Processor
1
2

25

EAIPATTERNSINAPACHECAMEL

AggregationCollection 1 whichstoresitsstateinadatabase,forexampleviatheJava Persis


tenceAPI[DK06].
BecauseCamelsimplementationoftheAggregatordoesntneedpriorknowledgeofanewaggre
gate it simply creates a new aggregate if an aggregate with the current correlation identifier
doesnt existyet it implements a so called selfstarting Aggregator.Another variant of the Ag
gregator where the Aggregator needs prior knowledge of the aggregates is called an initialized
Aggregator.SuchanAggregatorcouldbeinitializedforexamplebyaSplitteroraRecipient List
throughaseparatechannelasproposedby[HW03].Suchanimplementationcouldagainberea
lizedinCamelbyacustomAggregationCollectionimplementationwhichlistensonanaddi
tionalchannelforinitializationmessages.
CamelsupportstheAggregationinitsDSLbyusingtheaggregator()methods,buttheseme
thodsdontsupportacustomAggregationCollectionandthuscantbeusedforanimplemen
tationthatcorrectlyimplementstheAggregatorpattern.ForusingtheAggregatorpatterninCa
mels routing rules either the Java DSL needs to be adapted to support custom
AggregationCollections or the Aggregator class can be used directly for creating a route,
although this approach produces less readable code. Listing 15 below shows how to create a
routingruleusingthelatterapproachandusingacustomAggregationCollectionimplemen
tation which also supports a correlation identifier Predicate 2 . Note that, as mentioned before,
CamelsAggregatorisaPollingConsumerandthusneedstoruninitsownthread.Forthatreason
theAggregatorhastobestartedthroughitsstart()method,providedbytheService 3 inter
face,aftertheCamelContexthasbeenstarted.
1
2
3
4
5
6
7
8
9
10

AggregationCollection myAggregationCollection
= new MyAggregationCollection(myCorrelationExpression,
myAggregationStrategy,
myCompletnessConditionPredicate);
Aggregator myAggregator
= new Aggregator(getEndpoint("myComponent:endpointA"),
getEndpoint("myComponent:endpointB")
.createProducer(),
myAggregationCollection);
Listing15:ApacheCamelsAggregatorwithacustomAggregationCollection

3.4.7

Composed Message Processor / Scatter-Gather

TheComposed Message ProcessorandtheScatterGatherpatternandalsoacombinationofboth


can be implemented by combining the Splitter, Router, Aggregator, Recipient List and Publish
SubscribeChannelpatternasdescribedinHohpesandWoolfsbook[HW03].

org.apache.camel.processor.aggregate.AggregationCollection
org.apache.camel.Predicate
3org.apache.camel.Service
1
2

26

3.5MessageTransformation

3.5

Message Transformation

MessageTransformation,andthustheMessageTranslatorpattern,issupportedbyApacheCamel
in several different ways and for several different levels of transformation. Transportlevel trans
formationisimplicitlydonebyApacheCamelsComponents.Datarepresentationleveltransforma
tion is supported by Apache Camels Type Converter (see chapter 2.2.3 Camel Type Converter
above)forsimpledatatypetransformationandbyCamelsDataFormat 1 interface,whichoffersa
pluginstrategyforthemarshallingandunmarshallingofmessages.
Data type and data structure level transformations are supported in Camel by using custom
Processors 2 whichallowthetransformationofmessagesusingarbitraryJavacodeorbyusing
an Expression whose result replaces the old message body. Listing 16 below demonstrates both
approaches.
1
2
3
4
5
6
7
8
9

// translation by a custom Processor:


from("myComponent:endpointA1")
.process(myCustomTranslatorProcessor)
.to("myComponent:endpointB1");
// translation by an Expression:
from("myComponent:endpointA2")
.setBody(myTranslatorExpression)
.to("myComponent:endpointB2");
Listing16:MessageTranslatorinApacheCamel

3.5.1

Envelope Wrapper

TheEnvelopeWrapperpatternisimplementedinApacheCamelbyitsComponents.Ifamessaging
system or a transport protocol requires a special message format, its the corresponding Compo
nentstasktowrapthemessagesothatthemessageiscomplianttotheinfrastructuretheCompo
nentinterfacesto.ForexampletheJMSComponentwrapsaCamelmessageinaJMSmessageand
also adds the Camel message headers as JMS properties to the JMS message. If application level
wrappingofmessagesisneededitcanbeimplementedbythesametechniquesdescribedinchap
ter3.5above.

1
2

org.apache.camel.spi.DataFormat
org.apache.camel.Processor

27

EAIPATTERNSINAPACHECAMEL

3.5.2

Content Enricher

TheContentEnricherpatternisnotimplementedinApacheCamel.ThebestwaytoaddaContent
EnrichertoCamelistocreateacustomProcessor 1 whichisableofcollectingtherequireddata
needed for the enriching of the messages. For example the custom Processor could connect to a
database system orinvoke a web service to get the required data. By using the latterapproacha
custom Processor could be implemented that is generic enough to be reusable. Such a Processor
couldinvokeawebservicebysendingincomingmessagestothewebservicewhichthenreturns
therequiredinformationthatcanthenbeusedinanXSLtransformationtogetherwiththeoriginal
messagetogeneratetheenrichedmessage.Listing17belowshowshowsuchanimplementation
couldbeintegratedinCamelsJavaDSL
1
2
3
4
5
6
7
8
9

Processor myContentEnricher
= new MyContentEnricher(myWebserviceWsdlUrl,
myServiceName,
myPortName,
myXsltUrl);
from("myComponent:endpointA")
.process(myContentEnricher)
.to("myComponent:endpointB");
Listing17:PossibleContentEnricherimplementationinApacheCamel

3.5.3

Content Filter

TheContent FilterisnotexplicitlyimplementedinApacheCamelbutthesamegeneralmessage
transformationtechniquesdescribedinchapter3.5abovecanbeusedtoimplementaContentFil
ter. Particularly the use of an Expression 2 to filter content of a message provides a simple ap
proach to a Content Filter where the Expression would return the filtered content. For example
Camels builtin XPathBuilder 3 could be used to filter message content according to an XPath
expression.Listing18belowdemonstratessuchascenarioinCamelsJavaDSL.
10
11
12

from("myComponent:endpointA")
.setBody(XPathBuilder.xpath("/my/xpath/expression"))
.to("myComponent:endpointB");
Listing18:ContentfilteringusinganXPathexpressioninApacheCamel

org.apache.camel.Processor
org.apache.camel.Expression
3org.apache.camel.builder.xml.XPathBuilder
1
2

28

3.5MessageTransformation

3.5.4

Claim Check

Apache Camel doesnt implement the Claim Check pattern, but can be extended to support this
pattern. Unlike for the Content Filter pattern a custom Processor 1 implementation should be
used, as it would be bad design to develop a custom Expression 2 that has side effects like the
storage of the filtered data.A Processor, filtering the content, would need to store the filtered
contentpersistentlytobeabletoretrieveitlater,forexampleitcouldstorethefilteredcontentina
database which could be accessed using the Java Persistence API [DK06]. Also a unique key to
identifythefilteredcontentisneeded,thathastobeeitheralreadypresentinthemessageorgen
erated.
A general implementation of the Claim Check could use three Expressions to identify the re
movedcontent,thecontenttokeepandtheuniquekey,whichalsocanbegenerated.Alessgeneral
implementation that knows about the format of the messages could be implemented using only
one Expression and compute all other necessary information. For example, one that can only
handleXMLdataandusesanXPathExpressiontoidentifythecontenttofilter,andwherethefil
teredmessagecontentiscomputedandtheuniquekeyisgenerated.
Such general implementations would require each instance to have its own storage, especially in
the case of generated keys, so that the filtered content of the different instances is not mixed.
Listing 19 below shows how such a general implementation of the Claim Check pattern, which
handles XML messages, uses an XPath expression to identify the data to filter and identifies its
persistentstorageviaauniquestring,couldbeusedinCamelsJavaDSL.
1
2
3
4
5
6
7

Processor myClaimCheck
= new MyClaimCheck ("/my/xpath/expression",
"myClaimCheck1");
from("myComponent:endpointA1")
.process(myClaimCheck)
.to("myComponent:endpointB1");
Listing19:PossibleClaimCheckimplementationinApacheCamel

3.5.5

Normalizer

TheNormalizerisnotimplementedinApacheCamel,butasitisacomposedpatternconsistingof
aContentBasedRouterandseveralMessageTranslators,itcanbeimplementedbyusingCamels

1
2

org.apache.camel.Processor
org.apache.camel.Expression

29

EAIPATTERNSINAPACHECAMEL

implementationofthosepatterns.BecausetheNormalizerisaseparatepatternandthusitscom
ponentscanandshouldbetightlycoupled,onecouldrenouncetheusageofpipes,i.e.ofchannels,
(see chapter 3.3 Pipes and Filters above) between the ContentBased Router and the Message
Translators. A Normalizer would then be configured in Camels Java DSL as demonstrated in
listing20below.
1
2
3
4
5
6
7
8
9
10
11

from("myComponent:endpointA").choice()
.when(myMessageFormat1Predicate)
.process(myXformProcessor1).to("myComponent:endpointB")
.when(myMessageFormat2Predicate)
.setBody(myXformExpression2).to("myComponent:endpointB")
.when(myMessageFormat3Predicate)
.process(myXformProcessor3).to("myComponent:endpointB")
.when(myMessageFormat4Predicate)
.setBody(myXformExpression4).to("myComponent:endpointB")
.otherwise()
.to("myComponent:invalidMessageChannel");
Listing20:NormalizerinApacheCamel

3.6
3.6.1

Messaging Endpoint
Messaging Gateway

Apache Camel itself provides a lowlevel Messaging Gateway as it abstracts from the infrastruc
tureandmessagingsystemswhichApacheCamelsComponentsinterfacewith.Cameloffersgen
eralmessagingsemanticsthroughgenericinterfacesthatcanbeusedindependentlyfromtheun
derlyingmessaginginfrastructure.IncaseoftheJMSComponentCamelsimplyusestheJMSAPI
[HBS+],whichisalsoalowlevelMessagingGateway.
Camels documentation mentions that the Messaging Gateway is supported using Camels Bean
Component which offers the ProxyHelper 1 class that can generate proxyclasses to invoke me
thods on remote JavaBeans (i.e. remote Java classes). But as the proxy offers only synchronous
remoteinvocationviamessaging,andasthegeneratedproxyclassdoesntperformanyerrorhan
dlingbutexposestheapplicationtomessagingspecificexceptions,thisapproachisonlysuitableto
implementverybasicMessaging Gateways.ButApacheCamelcanbeusedtoimplementhigher
levelMessagingGatewaysthathidethemessagingsemanticsfromanapplication,bydevelopinga
domainspecificAPIthatusestheCamelAPItosendmessages.Bothapproachesareonlypossible
ofcourse,iftheapplication,wewanttoprovideagatewayfor,iswritteninJava.

org.apache.camel.component.bean.ProxyHelper

30

3.6MessagingEndpoint

3.6.2

Messaging Mapper

The Messaging Mapper pattern is not implemented inApache Camel, but Camel can be used to
implementaMessaging MapperifthetargetapplicationisaJavaapplicationbyprovidingauni
fied interface to different messaging infrastructures. For example the Messaging Mapper could
implement Camels Processor 1 interface that handles incoming message exchanges and map
themtoapplicationspecificevents.

3.6.3

Polling Consumer

ThePollingConsumerpatternisimplementedinApacheCamelbythePollingConsumer 2 inter
face which offers blocking as well as nonblocking methods to poll for new messages.
PollingConsumer 3 instances are obtained using the createPollingConsumer() method of
the Endpoint 4 interface as Camels Java DSL doesnt offer support for Polling Consumers yet.
Listing21belowdemonstrateshowapollingconsumerthatpollsfornewmessagesinablocking
wayisimplementedinCamel.NotethatthePollingConsumeronendpointscreatedbyCamels
JMSComponent has a bug that makes the blocking receive() method, used in the example
below, act like a nonblocking receive, which means that the method might return immediately
withanullvalueasresult.
1
2
3
4
5
6

Endpoint endpoint = context.getEndpoint("myComponent:endpointA");


PollingConsumer pollingConsumer = endpoint.createPollingConsumer();
while(true) {
Exchange exchange = pollingConsumer.receive();
// process message here
}
Listing21:PollingConsumerinApacheCamel

3.6.4

Event-Driven Consumer

The EventDriven Consumer pattern is implemented in Apache Camels Processor 5 interface


andistheconsumermodelusedwhenroutesarecreatedusingCamelsJavaDSL.Eachtimeanew
message arrives the Consumer 6 invokes the process() method of the Processor registered
withtheConsumer.TheEventDrivenConsumeristherecommendedconsumermodelinApache

org.apache.camel.Processor
org.apache.camel.PollingConsumer
3org.apache.camel.PollingConsumer
4org.apache.camel.Endpoint
5org.apache.camel.Processor
6org.apache.camel.Consumer
1
2

31

EAIPATTERNSINAPACHECAMEL

CamelbecauseCameloffersaThreadProcessorwhichallowspoolingandmanagementofthe
threads that are used to process messages by a Processor. But note that although Camels
Consumers 1 usetheProcessorinterfacetonotifytheattachedmessageprocessorsofincoming
messagesand thus seemto make these message processors EventDriven Consumers they inter
nally implement the Polling Consumer pattern. This is for example true for the FileComponent
andtheSEDAComponentbutnotfortheJMSComponent.Listing22belowdemonstrateshowan
EventDrivenConsumerisimplementedinCamel.
1
2
3
4
5

from("myComponent:endpointA").process(new Processor() {
public void process(Exchange exchange) {
// process message here
}
});
Listing22:EventDrivenConsumerinApacheCamel

3.6.5

Competing Consumers

Competing ConsumerscanbeimplementedinApacheCamelbysimplycreatingtworoutesthat
havethesameendpoint,whichhastobeanendpointonaPointtoPointChannel,astheirincom
ing channel. The JMSComponent also supports the Competing Consumer pattern using a single
routeif the incoming JMSEndpoint is configuredto support concurrent consuming,as done for
theendpointinlisting23below.
6

from("jms:queue:myQueueA?concurrentConsumers=5").process(myProcessor);
Listing23:CompetingConsumerusingtheJMSComponentinApacheCamel

3.6.6

Message Dispatcher

TheMessage DispatcherpatternisnotimplementedinApacheCamel,butcouldbeimplemented
by developing a custom Processor 2 that delegates the message processing to some child
Processorsthatrunintheirownthread.Thepatterncanalsobeimplementedbycombininga
ChoiceProcessor 3 , which basically implements a Content Based Router and a
ThreadProcessor 4 which enables asynchronous processing of its child Processors using a
thread pool. Because a Consumer is only done processing a message when the whole route has

Consumersarecreatedviaorg.apache.camel.Endpoint.createConsumer(Processor processor)
org.apache.camel.Processor
3org.apache.camel.processor.ChoiceProcessor
4org.apache.camel.processor.ThreadProcessor
1
2

32

3.6MessagingEndpoint

been processed (see chapter 2.2.7 above for details) the Message Dispatcher can only be imple
mented if the incoming Endpoint support Competing Consumers, as the JMSComponents End
points do, if configured appropriately. Note that using asynchronous processing doesnt change
thisbehavioritjustpreventstheConsumersthreadfromblocking.Allthisisalsotrueforacus
tom implementation of a Message Dispatcher as a custom Processor, as long as the Processor
behaves like intended by Camels architecture. This means it should return only after the
Processor,itdispatchedto,returnedtoo.Butifneeded,thatrulecouldbeviolatedandthecus
tomProcessor 1 couldreturnfromtheprocess()methodwithoutwaitingforthecompletion
of its child processor. The drawback would be thatInOut 2 message exchanges wouldnt be sup
portedbysuchaRouteandthattheDispatcherwouldsuccessfullyconsumemessagesbeforethe
processingiscompleteandthusbeforethemessagehasbeenaddedtothefollowingchannel.This
couldcausemessagestogetlostincasetheDispatchercrashes.
Another approach could be to implement a custom Message Dispatcher as a Polling Consumer.
Heretherestrictionsjustmentioneddontapply,asthePolling ConsumerdoesntsupportInOut
exchangesanywayandthemessagesareimmediatelyconsumedanywaybythePollingconsumer,
unlessanacknowledgementmechanismliketheoneofJMSisused.ThussuchaDispatchercould
delegatetheprocessingtoitschildProcessorsinseparatethreads.
Listing24 below demonstrates howaMessage Dispatcher can be implemented inApacheCamel
usingaContentBased RouterandanEndpointthatallowsCompeting Consumers,asmentioned
before.
1
2
3
4
5
6
7
8

from("jms:queue:myDestination?concurrentConsumers=5").thread(5).choice()
.when(header("type").isEqualTo("A"))
.process(myProcessorForTypeA)
.when(header("type").isEqualTo("B"))
.process(myProcessorForTypeB)
.when(header("type").isEqualTo("C"))
.process(myProcessorForTypeC)
.otherwise().to("jms:queue:myInvalidMessageQueue");
Listing24:MessageDispatcherusingaContentBasedRouter

3.6.7

Selective Consumer

TheSelectiveConsumerpatternisnotimplementedinApacheCamelanditcantbeimplemented
withoutsupportbytheunderlyingmessagingsystem.Iftheusedmessagingsystemandthecor
respondingCamelComponentsupporttheSelective Consumerpattern,asthisisthecaseforthe
JMSComponent,thentheEndpointhasjusttobeconfiguredaccordinglyusuallyviaitsURI.If
themessagingsystemdoesntsupporttheSelectiveConsumerpatternbutsupportsmessagepeek

1
2

org.apache.camel.Processor
org.apache.camel.ExchangePattern.InOut

33

EAIPATTERNSINAPACHECAMEL

ing, i.e. the receiving of a message without to consume it, the pattern could be implemented by
extendingaComponentwiththeavailabilitytopeekformessagesthatmatchsomeExpressionand
to deliver and consume only those. If the Message Channel is a PublishSubscribe Channel the
SelectiveConsumercanalsobeimplementedwithoutsupportbythemessagingsystem,byusinga
MessageFilter.Ifthemessagingsystemdoesntsupportselectiveconsumersnormessagepeeking
and the channel is not a PublishSubscribe Channel, then a Message Dispatcher could be consi
deredinsteadofaSelectiveConsumer.
AsJMSsupportstheSelective Consumerpatternbyusingaselector,whichisaSQL92predicate
onmessageheaderscalledpropertiesinJMS.AndastheJMSComponentsupportsthisfeature,
theSelectiveConsumerpatterncanbeimplementedonJMSEndpointsasdemonstratedinlisting
25below.NotethattheselectorhastobeescapedfortheendpointURItobevalid.
1
2

from("jms:queue:myDestination?selector=type%3D%27A%27")
.process(myProcessor); // selector: type=A
Listing25:SelectiveConsumerusingApacheCamelsJMSComponent

3.6.8

Durable Subscriber

LiketheSelectiveConsumer,theDurableSubscriberisamessagingsystemspecificpatternandis
implemented for example in Camels JMSComponent. Listing 26 below demonstrates how an
EndpointonaJMStopiccanbemadeaDurableSubscriber.Notethat,whenusingJMSdirectly,a
uniqueclientIDandauniquesubscriptionnamemustbeprovidedtoregisterasaDurable Sub
scriber.IfaComponentdoesntsupportDurableSubscribers,Camelcanalsobeusedtoimplement
a Durable Subscriber by creating a route from a PublishSubscribe channel to a PointtoPoint
Channel,fromwhichtheclient,thatneedsadurablesubscription,canreceiveitsmessages.
3
4

from("jms:queue:myDestination?clientId=myClientId1&durableSubscriptionNam
e=mySubscriptionName1").process(myProcessor);
Listing26:DurableSubscriberusingApacheCamelsJMSComponent

3.6.9

Idempotent Receiver

TheIdempotent ReceiverpatternisimplementedinCamelbytheIdempotentConsumer 1 class,


which uses an Expression 2 to extract or generate a unique identifier for an incoming message
exchangeandaninstanceoftheMessageIdRepository 3 interfacetostoretheuniqueidentifiers

org.apache.camel.processor.idempotent.IdempotentConsumer
org.apache.camel.Expression
3org.apache.camel.processor.idempotent.MessageIdRepository
1
2

34

3.6MessagingEndpoint

forlater comparison withincoming messages.A simple Expression could just returna messages
uniquemessageIDwhichisoftengeneratedbythemessaginginfrastructure.Usingthesetwogen
eral interfaces Camels Idempotent Receiver can be adapted to fit the current requirements. The
implementation of the MessageIdRepository interface, that Camel offers, is an inmemory
basedimplementationthatalsoallowsthesettingofamaximumcachesize.Ifpersistentstorageof
the receive message identifiers is required, a custom implementation of the
MessageIdRepository interface storing the values can be used. Listing 27 below shows how
CamelsIdempotent ReceivercanbeconfiguredusingCamelsJavaDSL.Inthisexamplethemes
sages "MyMessageId"header is used as unique identifier and Camels inmemory
MessageIdRepository with a maximum capacity of 100 entries isusedfor storing these iden
tifiers.
1
2
3
4
5

from("myComponent:endpointA")
.idempotentConsumer(header("MyMessageId"),
MemoryMessageIdRepository
.memoryMessageIdRepository(100))
.process(myProcessor);
Listing27:ApacheCamelsIdempotentReceiver

3.6.10 Service Activator

The Service Activator pattern is implemented by Camels BeanComponent and Camels


BeanProcessor 1 .TheybothenabletheprocessingofmessagesbysomearbitraryJavaBean.The
BeanComponentcanbeusedtosendmessagestosomeBeanEndpoint,whereCamelqueriesthe
JNDIcontext associated with the Camel Context for the bean. In case of the BeanProcessor a
beaninstanceorthebeansclassarepassedonconstructionoftheBeanProcessor.Inbothcases
themethodtoinvokeisdiscoveredusingseveralways.Onepossibilityistospecifythemethodto
invokeinthemessageheaderorintheBeanEndpointsURI.AslastresortCameltriestofindan
appropriatemethodaccordingtothemessagetype,usingintrospection.Fordetailsabouttheme
thoddiscoveryseeCamelsdocumentation[Cam].Listing28belowdemonstratestheusageofthe
BeanComponent, specifying the method to invoke in the EndpointURI, and the usage of the
BeanProcessorviaCamelsJavaDSL.NotethatfortheBeanComponenttowork,thebeanhas
tobestoredinCamelContextsJNDIcontextunderthename"myService".

org.apache.camel.component.bean.BeanProcessor

35

EAIPATTERNSINAPACHECAMEL

1
2
3
4
5
6
7

from("myComponent:endpointA")
.to("bean:myService?methodName=myMethod")
.to("myComponent:endpointB"); // using the Bean-Component
from("myComponent:endpointC")
.bean(new MyService(), "myMethod")
.to("myComponent:endpointD"); // using the BeanProcessor
Listing28:TheServiceActivatorpatterninApacheCamel

36

Implementation

In chapter 3 the Enterprise Application Integration (EAI) Patterns from [HW03] were evaluated
regardingifandhowtheyareimplementedinApacheCamel.Inthispartoftheworktheresults
fromchapter3areusedtoextendtheEclipsebasededitorwhichwascreatedaspartofthediplo
ma thesis from [Dru07]. This Eclipse based editor was developed as an Eclipse plugin which
enablesthegraphicalmodelingofmessagingsystems.Thegraphicaleditorallowscombiningthe
differentEAIpatternstomodelamessagingsystemthatimplementsthePipesandFiltersarchi
tecture.ThismessagingsystemmodelisthenusedtogenerateaWSBPEL[AAA+07]processthat
implementsthemessagingsystemmodeled.ThegeneratedWSBPELprocessuseswebservicesto
providemostofthefunctionalityofferedbythedifferentpatternsandinturnofferstheexecution
ofthatprocessaswebservice.
ThegoalofextendingtheEclipseplugin,developedbyDruckenmller[Dru07],istoaddtheabili
ty to generate Apache Camel based Javacode out of the messaging system modeled. This Java
codeshallimplementastandaloneapplicationthatusesanunderlyingmessageorientedmiddle
waretoimplementtheMessage ChannelsandthatusesApacheCameltoimplementtherouting
andthetransformationlogicaswellasthemessageendpoints.
LikethegeneratedWSBPEL[AAA+07]process,alsothegeneratedCamelbasedapplicationshall
usewebservicestosupportthevariousEAIpatternimplementations.Althoughthemodeledmes
sagingsystemwouldntneedtoofferitsfunctionalityaswebservice,becauseitcouldinteractwith
theoutsideworldusingmessaging,thesolutiondevelopedinthisworkshallalsobeabletopro
videitsfunctionalityasawebservice.Thereasonthesolutionhastobeabletodoso,isthatthe
generatedJavaapplicationshouldhavethesamesemanticsandinterfacestotheoutsideworldas
theWSBPELprocessgeneratedbytheEclipseplugin.

4.1

Concept

Apache Camels implementation of the Enterprise Integration Patterns, evaluated in chapter 3


above, relies in most cases on some sort of custom Javacode. For example, often the parameters
neededbyapatternrequireacustomimplementationofsomeinterface.Patternsthatarenotornot
completelyimplementedinCamelalsooftenrequireacustomProcessor 1 implementation.The
implementation from [Dru07] uses some common web standards based on XML [BPS+06] to im
plementtheidentifiedparametersofthedifferentEAIpatterns.Thesecommonwebstandardsare
XPath[CD99],XSLT[Cla99]andwebservices[BL07]whicharewidelyusedin[Dru07]toimple
mentsomelogicrequiredbythepatterns.

org.apache.camel.Processor

37

IMPLEMENTATION

TofillthegapbetweentheJavacodecentricpatternimplementationofCamelandthewebtech
nologybasedimplementationof[Dru07]aframeworkisbeingdeveloped.Thisframeworkconsists
ofclassesthatimplementthedifferentEAIpatternsorsupportCamelsimplementationofthepat
terns.TheseclassesareallbasedonCamelandaimtoextendCamelinaconsistentandreusable
fashion, while using web based technology like XPath, XSLT and web services to implement the
patterns.Usingthesetechnologiesaddstheconstraint,thatallprocessedmessageshavetobeXML
messages.ButasXMLisawidelyacceptedstandardthisisnodrawbackinthesenseofcompatibil
itywithothersolutions.
Byusingthisframework,theJavacodegenerationprocess,whichistheactualgoalofextending
the Eclipse plugin, is reduced to the generation of Javacode that instantiates the classes of the
frameworkcorrespondingtothepatterns.Theclassesareinstantiatedusingtheparametersofthe
correspondingpatternandareconnectedbybuildingApacheCamelRoutes.
TheextensionoftheEclipsepluginfrom[Dru07]isdonebyaddingacustomsocalledActionDe
legate 1 tothepluginwhichiteratesthroughthemodeledmessagingsystemandtherebygenerates
theappropriateJavacode.Becausethetimeconstraintsonthisworkdontallowtheimplementa
tionofallEAIpatterns,thecodegenerationisbeingimplementedinanextensiblefashiontoallow
easy completion by future works. Thecode generation being done by an Eclipse plugin and Ec
lipse being also a Java development environment just calls for an implementation that generates
theJavacodeusingEclipsesJavaDevelopmentTools[Jdt].ThatwayaJavaprojectiscreatedin
sideEclipsecontainingapackagewiththegeneratedJavacode.BeinggeneratedasaJavaproject
inEclipse,themessagingsystemcanconvenientlybemodifiedandbuildinsideofEclipse.

4.2

Used Technologies

The implementation, done in this work, uses several technologies. These technologies were used
together withApache Camel to implement the framework mentioned above as well as to imple
ment the code generator. In the following these technologies exceptApache Camel, which was
describedinitsownchapteraredescribed:

JAX-WS 2.0
TheJavaAPIforXMLBasedWebServices(JAXWS)[CHM06]offersastandardizedinterfacefor
invokingandprovidingwebservicesusingtheJavaprogramminglanguage.JAXWSoffersahigh
levelandalowlevelAPI,wherethehighlevelAPIcanbeusedtocomfortablyinvokeorprovidea
webservicebybindingaJavainterfacetoawebservicedefinedinaWSDLfile[BL07].Thehigh
levelAPI handles things like type conversion and enables the programmer to use a web service
throughasimplemethodcall,ortoprovideawebservicebysimplyimplementingaJavamethod.
The lowlevel API provided by JAXWS enables the programmer to work on the message level.
HereawebservicecanbeinvokedbycreatingeitheracompleteSOAPmessage[ML07]orbyjust

org.eclipse.ui.IWorkbenchWindowActionDelegate

38

4.3TheEAI2CamelFramework

providing the message payload (i.e. the message body) and letting JAXWS handle the message
headers.ThelowlevelinvocationofwebservicesisofferedbyJAXWSsService 1 interface.Pro
vidingawebserviceusingJAXWSslowlevelAPIenablestheimplementertoworkonthemes
sagelevelinthesamewayasforthelowlevelinvocation.Thismeansthatthewebserviceprovid
ercaneitherworkwiththewholemessageorjustwiththemessagepayload.Suchalowlevelweb
serviceproviderneedstoimplementJAXWSsProvider 2 interface.

JAXP 1.4
TheJavaAPIforXMLProcessing(JAXP)offersseveralAPIsforthevalidation,parsing,transfor
mationandextractionofcontentfromXMLdocuments.Intheframework,implementedaspartof
this work, XML transformation using XSLT [Cla99] stylesheets is done using JAXPs XML trans
formation API located in the javax.xml.transform package. This is the main technology used to
implement the Message Translator pattern and isalso used frequently in thisframework in con
junctionwiththeinvocationofwebservices.AnotherJAXPAPIfrequentlyusedinthisframework
isJAXPs XPathAPI which is foundin the javax.xml.xpath package. ThisAPI is used to evaluate
XPathexpressions[CD99]toselectaspecificportionofanXMLdocument.

Eclipse Visual Editor 1.2.0


TheEclipseVisualEditor[Vep]isanEclipsepluginthatprovidesgraphicaluserinterfaceforthe
implementation of graphicalJavaapplications. In this workit is used to implement graphicaldi
alogsfortheinteractionwiththeuserduringthegenerationoftheApacheCamelbasedJavacode.

Eclipse JDT 3.2.2


TheEclipseJavaDevelopmentTools(JDT)providetheEclipsePlatform[Ecl]withthecapabilityto
serveasanintegrateddevelopmentenvironment(IDE)forJavaapplications.TheJDTCore,which
isthepartoftheJDTusedforthiswork,providestheinfrastructureoftheJavaIDEbyprovidinga
modelfortheJavaprojecttreeandanAPItomodifythismodel.FortheimplementationoftheJava
code generator the JDT CoreAPI is used to create and manipulate the java classes and packages
needed for the generated system to be able to run.Also the required libraries needed to run the
generatedmessagingsystemareaddedtotheJavaprojectsclasspathusingtheJDTCoreAPI.

4.3

The EAI-2-Camel Framework

TheEAI2CamelframeworkwasimplementedtofillthegapbetweentheJavacodecentricpattern
implementationofCamelandthewebtechnologybasedimplementationof[Dru07].Itconsistsof
severalclasses,eitherimplementingoneoftheEAIpatternsorsupportingtheimplementationof
theEAIpatterns.

1
2

javax.xml.ws.Service
javax.xml.ws.Provider

39

IMPLEMENTATION

4.3.1

Helper Classes

The framework contains some helper classes that are used to support the implementation of the
patterns in the framework. One of these helper classes is the Eai2CamelNamespaceContext 1
whichisasimpleimplementationofJAXPsNamespaceContext 2 interface.Thisinterfaceisused
byJAXPtoresolvenamespaceprefixesusedforexampleinXPathexpressions.
ThesecondhelperclassistheWebServiceFilter 3 classthatisthebasicclasswhichisextended
by all patterns that invoke a web service in their implementation. The WebServiceFilter im
plementsCamelsProcessor 4 interfaceandisthusanEventDrivenConsumer.ItusesJAXWSs
lowlevelAPItoinvokeawebservicebysendingtheincomingmessagesasthemessagebodyof
thewebserviceinvocation.Becauseawebserviceinvocationcantakesometime,thewebserviceis
invoked asynchronously. It is using JAXWSs callback mechanism to get notification about the
completionoftheinvocation.FortheProcessornottoblockwhilethewebserviceisinvoked,the
WebServiceFilteralsoimplementsCamelsAsyncProcessor 5 interface,whichenablesCamel
to invoke the WebServiceFilter asynchronously. This enables the complete asynchronous
processingofmessages.TheWebServiceFilteralsousesJAXPsmessagetranslatortotranslate
theresponsemessageofthewebserviceinvocationtoadifferentJavatype,requiredbytheimple
mentation. Here the identity transformation is done, but classes extending the
WebServiceFiltermightchoosetotransformaccordingtoanXSLTstylesheet.
Despite the WebServiceFilter being used to implement the EAI patterns that are using web
servicesfortheirimplementation,italsoimplementsapartoftheExternalServicepatternintro
ducedby[Dru07].ThisExternalServicepatternisbasicallyafilterinthePipesandFiltersarchi
tecturethatisimplementedbyawebservice,i.e.thewholemessageisprocessedbythewebser
vice. In addition to the invocation this External Service pattern also allows to provide a web
servicetotheoutside.ThisisnotimplementedbytheWebServiceFilterbutbytheWebService
Providermentionedbelow.
The framework also contains the Eai2CamelContext 6 class which extendsApache Camels de
faultimplementationoftheCamel Context.ThisextendedCamel Contextallowsaddingservices,
i.e. classes implementing Camels Service 7 interface, to the Camel Context. These Services life
cyclewillthenbemanagedbytheCamel Contexttogetherwithitsownlifecycle.Particularlythe
Camel Contextwillstarttheservicesafteritwasstarteditselfandwillstopthembeforestopping
itself.

de.unistuttgart.iaas.framework.eai2camel.Eai2CamelNamespaceContext
javax.xml.namespace.NamespaceContext
3de.unistuttgart.iaas.framework.eai2camel.WebServiceFilter
4org.apache.camel.Processor
5org.apache.camel.AsyncProcessor
6de.unistuttgart.iaas.framework.eai2camel.Eai2CamelContext
7org.apache.camel.Service
1
2

40

4.3TheEAI2CamelFramework

4.3.2

Message Producer Template

Theframeworkoffersamessageproducertemplatethatfacilitatesthecreationofamessagepro
ducer. Itis provided by the abstract class MessageProducerTemplate 1 which extends Camels
CamelTemplate 2 andimplementstheService 3 interfaceenablingCameltomanageitslifecycle.
ClassesextendingtheMessageProducerTemplateneedtoimplementtherun()methodfrom
theRunnableinterfacewhichisinvokedinaseparatethreadwhentheCamel Contextisstarted.
Theimplementationoftherun()methodmustregularly,inparticularbeforeproducingmessages,
checkiftheCamelContextisstillrunningbyusingtheisRunAllowed()method.Theadvantage
ofthismessageproducertemplateisthatitprovidesseveraleasytousemethodstosendmessages
tosomeEndpoint.Theexampleinlisting29belowdemonstratesanimplementationoftherun()
method which sends messages to the default Endpoint, passed to the constructor of this
MessageProducerTemplateinstance.
1
2
3
4
5
6
7
8

public void run() {


while (this.isRunAllowed()) { // check if Camel Context is running
try {
this.sendBody("some message content");
Thread.sleep(5000); // try to sleep 5 seconds
} catch (InterruptedException e) { } // can be ignored
}
}
Listing29:UsingtheMessageProducerTemplateoftheEAI2CamelFramework

4.3.3

Web Service Endpoint

TheEAI2CamelframeworkalsoaddsanewEndpointtoApacheCamelthatcanbeusedtoin
vokewebservices.TheWebServiceEndpointworksinasimilarwayastheWebServiceFilter
class mentioned in chapter 4.3.1 above. It also uses JAXWSs Service class to invoke the web
serviceasynchronouslyandJAXPtotransformtheresponsemessagetoarequiredtype.TheWeb
ServiceEndpointisimplementedusingthreeclasses,onefortheEndpoint,onefortheConsumer
and one for the Producer. The implementation is located in the following package:
de.unistuttgart.iaas.framework.eai2camel.component.ws.
Note that this is just theimplementation ofan Endpoint not of a complete Component. Thus the
useofURIstocreateWeb Service Endpointsisnotsupported.AfutureworkcouldcreateaWeb
Service Component which would enable Apache Camel to use web services as a channel. This
couldbeusefulforexampletoperformtransformationonthewirebyawebserviceortoimple
mentaMessageChannelthatprovidesGuaranteedDeliveryusingawebservice.ThisComponent
couldalsoaddtheabilitytoprovideawebservicetotheoutsideworldwhichisimplementedus

de.unistuttgart.iaas.framework.eai2camel.endpoint.MessageProducerTemplate
org.apache.camel.CamelTemplate
3org.apache.camel.Service
1
2

41

IMPLEMENTATION

ingaCamelRoute.TosupportthisalsotheWeb Service Endpointofthisworkwouldneedtobe


extended.

4.3.4

Web Service Provider

TheEAI2CamelframeworkenablesApacheCameltoofferawebservicewhichisimplemented
byprocessingamessagethroughaCamelRoute.AstheWebServiceProvideroffersawebservice
totheoutsideitisamessageconsumerfromtheinvokerspointofview.ButtoApacheCamelthe
Web Service Provider is in first place a message producer, as it implements the web service by
producingamessageandsendingittosomeEndpoint.OntheotherhandtheWebServiceProvid
ersupportssendingaresponsemessagetoareceivedrequest,thusitisalsoaconsumerofmessag
esfromCamelspointofview.Thisisbecausetheresponse,whichwillbesenttotheinvokerofthe
webservice,isreceivedandconsumedbysomeEndpoint.
TheWebServiceProviderisimplementedbytheWebServiceProvider 1 classoftheframework.
This class supports the implementation of a web service which sends the request message to an
Endpoint,andexpectstheresponsemessageonadifferentEndpointtoforwardtheresponsetothe
web service invoker. The Web Service Provider is intentionally not implemented using Camels
abilitytoprocessmessagesasInOutExchangesduetotheincompleteimplementationmentioned
in chapter 3.2.2 (RequestReply pattern). The WebServiceProvider implements Camels
Processor 2 interfacetoactasanEventDrivenConsumerontheEndpointtheWebServicePro
vider expects the reply message. When the web service is invoked the WebServiceProvider
packs therequest message ina CamelExchange and sends it tothe Endpoint passed in the con
structor. Because JAXWS 2.0 does only support synchronous web service implementations the
WebServiceProvider blocks till it receives the answer via its process() method of the
Processorinterface.Thisisnotanidealimplementation,butJAXWS2.1,whichsupportsasyn
chronousimplementationsofwebservices,isnotimplementedyetbyallJAXWSproviders.And
evenwithJAXWS2.1thewebserviceclientstaysconnectedduringtheexecutionofthewebser
vice, weather executed synchronously or asynchronously. This is because messagingstyle web
serviceinvocationisnotsupportedbyJAXWSyet.
The WebServiceProvider implementation also supports the implementation of a web service
where the invoker doesnt expect any response. In this case the web service just creates a Camel
Exchange,sendsittotheEndpointandreturns.
ToallowCameltomanageitslifecycle,whichmeansprovidingornotprovidingthewebservice,
theWebServiceProviderimplementsCamelsService 3 interface.

de.unistuttgart.iaas.framework.eai2camel.endpoint.WebServiceProvider
org.apache.camel.Processor
3org.apache.camel.Service
1
2

42

4.3TheEAI2CamelFramework

4.3.5

Message Translator

To support the Message Translator pattern from [HW03] using web technologies the
MessageTranslator 1 class was implemented in the EAI2Camel framework. This class is an
EventDriven Consumer and thus implements Camels Processor 2 interface. It supports the
transformationbyeitherawebserviceorbyanXSLTstylesheet.Whichofthosetechnologiesare
used for the transformation depends on which constructor is used to instantiate the
MessageTranslator.
If the transformation by a web service is chosen, the MessageTranslator simply forwards its
incomingmessagesandexpectsthetranslatedmessageasresponse.Thewebserviceinvocationis
donebyextendingtheWebServiceFilter 3 classwhichalreadyprovidesthatfunctionality.
In case of transformation using XSLT, the MessageTranslator uses JAXPs TransformAPI 4 to
performtheXSLTtransformationusingthesuppliedXSLTstylesheet.

4.3.6

Content Enricher

TheContent EnricherisaspecialcaseofaMessage Translator,thustheContent Enricherimple


mentation of the EAI2Camel framework extends the MessageTranslator 5 class and reuses
partofit.TheContentEnricher,whichisimplementedintheContentEnricher 6 class,provides
its functionality using different approaches. What approach is used is determined according to
whichconstructorisusedtoinstantiatetheContentEnricher.
Oneoptionofferedistodelegatethewholecontentenrichingprocesstoawebservice.Inthatcase
thewholemessageissendtoawebservicewhichenrichesthemessageandreturnstheresulting
message.Thisapproachdoesntdifferatallfromawebservicebasedtransformationimplemented
by the MessageTranslator or from the general processing of a message by a web service im
plementedbytheWebServiceFilter3class.
Another option is to send the whole incoming message to a web service which returns the data
neededtoenrichthatmessage.ThisreturneddataisthenusedtoenrichthedatausinganXSLT
stylesheet.FortheXSLTprocessingtobeabletousethedatawhichissubjectoftheenrichmentit
needs to be madeavailable somehow to the XSLT processor. In order to do this, two approaches
have been implemented in the ContentEnricher. One approach provides a custom
URIResolver 7 to the XSLT processor that resolves a special URL to a document containing the
dataneeded.UsingthisapproachaXSLTstylesheetcansimplyaccessthedatabyloadingadocu

de.unistuttgart.iaas.framework.eai2camel.transformation.MessageTranslator
org.apache.camel.Processor
3de.unistuttgart.iaas.framework.eai2camel.WebServiceFilter
4javax.xml.transform
5de.unistuttgart.iaas.framework.eai2camel.transformation.MessageTranslator
6de.unistuttgart.iaas.framework.eai2camel.transformation.ContentEnricher
7javax.xml.transform.URIResolver
1
2

43

IMPLEMENTATION

ment residing on that special URL. This is demonstrated in the XSLT snippet in listing 30 below
whereyoucanalsoseethespecialURLused.
1
2

<xsl:copy-of select="document('http://contentenricher.transformation
.eai2camel.framework.iaas.unistuttgart.de')" />
Listing30:RetrievingthedatatoenrichinanXSLTstylesheetviaaspecialURL
AlternativelythedatareturnedfromthewebserviceisalsomadeavailabletotheXSLTprocessor
using a XSLT parameter. Using this approach a XSLT stylesheet could reference to this data by
declaring the parameter NewData and using the XSLT variable $NewData that contains the
datareturnedbythewebservice.ThisisdemonstratedintheXSLTsnippetinlisting31below.

3
4
5

<xsl:param name="NewData" />

<xsl:copy-of select="$NewData" />


Listing31:RetrievingthedatatoenrichinanXSLTstylesheetviaanXSLTparameter
The two options of using the ContentEnricher just mentioned have a drawback in common.
Namelytheyrequireawebservicewhichisabletohandleinputofamessagetypespecifictothe
inputmessagetypeoftheContentEnricher.Thusthethirdapproachenablestouseamoregeneric
webservicewhichacceptsaparameterlikeaprimarykeyinsomedatabasetableforexample
andreturnsthecorrespondingdata.FortheContent Enricherbeingabletosendthatmessagean
XPathexpressionisusedtoidentifytheparameterinthemessagepayload.TheXPathexpressionis
evaluatedusingJAXPsXPathAPI 1 .Tobeabletoresolvethenamespaceprefixesusedinsuchan
XPathexpressiontheconstructoroftheContentEnricheralsoprovidesthepossibilitytosupply
aNamespaceContext 2 .

4.3.7

Recipient List

Like suggested in the evaluation of the Recipient List pattern(see3.4.4Recipient List),a custom
CamelExpressionisdevelopedaspartoftheEAI2Camelframework.ThisExpression 3 creates
a list of recipients depending on the message received and is implemented in the
RecipientListExpression 4 class.TheRecipientListExpressionsupportsthreepossibili
tiestocreatethelistofrecipients.
Onepossibilityistosendthemessagewhichissubjecttotheevaluationtoawebservicethatre
turns a list of recipients. The RecipientListExpression doesnt require the web service to
returnalistofrecipientsofaspecificXMLSchema[FW04].Itjustrequiresittoreturnamessage

javax.xml.xpath
javax.xml.namespace.NamespaceContext
3org.apache.camel.Expression
4de.unistuttgart.iaas.framework.eai2camel.routing.RecipientListExpression

1
2

44

4.3TheEAI2CamelFramework

whosepayloadcontainsanarbitraryXMLrootelementwhichcontainsoneormorearbitrarychild
elements.ThestringvaluesofthesechildelementsarethenmappedtoApacheCamelEndpoint
URIs.ThewebserviceimplementationcouldbedeemedtoreturnCamelEndpointURIsdirectly,
but this would tightly couple the web service toApache Camel. Thus the indirection of using a
mapping between the channel identifiers returned by the web service and the Camel Endpoint
URIs is introduced. This mapping can be passed to the constructor as a Map 1 instance or can be
created by multiple calls to the setMapping() method of the RecipientListExpression.
ThewebserviceisinvokedusingtheJAXWSAPIasdescribedfortheWebBasedFilterabove.
Theonlydifferenceisthatthewebserviceisinvokedsynchronouslybecausetheprocessingcant
continuewhiletheExpressionisevaluated.ParticularlyApacheCameldoesntofferanasynchron
ousversionoftheExpression 2 interface.
Another possibility is to extract the recipient list from the message which is subject to routing.
Thereforethemessageneedstocontainalreadyalistoftherecipients.Thislistcouldforexample
beaddedtothemessageusingaContent Enricher.Likeforthewebservicebasedapproach,the
recipientlistcontainedinthemessageneedsnottobeofaspecificXMLSchema.Itjustneedsto
haveonerootelementwithseveralchildelementswhosestringvaluesaremappedtoCamelEnd
pointURIsusingthesamemappingmechanismadescribedbefore.Thispreventsatightcoupling
betweenthecomponentthataddstherecipienttothemessageandtheRecipientListimplementa
tion. The recipient list contained in themessage payload isidentified usinganXPath expression.
This XPath expression is evaluated using JAXPs XPathAPI and, like described for the Content
Enricher (4.3.6),a NamespaceContext 3 is needed to resolve thenamespace prefixesused in the
XPathexpression.
Thethirdpossibilityistodeterminetowhichrecipienttosendamessageto,basedonasetofCa
melPredicates.EachPredicateisassociatedwithaCamelEndpointURIandifamessagemeetsa
Predicate, that message is sent to the corresponding EndpointURI. This implementation resem
bles Camelsimplementation of the ChoiceProcessor, i.e. theContentBased Router. The only
differenceisthatacopyofthemessageissenttoallrecipients,notonlytotheonewiththefirst
matchingPredicate.

4.3.8

Aggregator

TheAggregatorpatternisimplementedintheEAI2Camelframeworkassuggestedintheevalua
tion of the pattern in chapter 3.4.6 above. This means it is implemented using a custom
AggregationCollection 4 thathidestheaggregatestoCamelsAggregator 5 tilltheaggregate
is complete. This custom AggregationCollection is implemented in the frameworks
ExtendedAggregationCollection 6 class.As mentioned by [HW03] and in the evaluation of

java.util.Map
org.apache.camel.Expression
3javax.xml.namespace.NamespaceContext
4org.apache.camel.processor.aggregate.AggregationCollection
5org.apache.camel.processor.Aggregator
6de.unistuttgart.iaas.framework.eai2camel.routing.aggregator.ExtendedAggregationCollection
1
2

45

IMPLEMENTATION

theAggregatorpattern(chapter3.4.6),animplementationoftheAggregatorpatternneedstospeci
fythreeproperties:Acorrelationbetweenthemessagestoaggregate,acompletenessconditionto
decidewhenanaggregateiscompleteandanaggregationalgorithmthatcomputestheaggregated
message.ApacheCameloffersinterfacesfortheimplementationoftheaggregationalgorithmand
ofthecorrelationidentifieraswellasforthecompletenesscondition.Theseinterfacesareusedby
theExtendedAggregationCollectionimplementationofthisframework.
The aggregation algorithm is implemented in Apache Camel by classes implementing the
AggregationStrategy 1 interface.Thisinterfaceimplementsaniterativeaggregationapproach.
Each time a new message in form of an Exchange 2 arrives, the AggregationStrategys
aggregate()methodisinvokedthatshallthencomputeanewExchangeormodifytheexist
ingonetorepresenttheaggregationofthemessagesarrivedtillthen.Thisiterativeapproachsaves
storageastheaggregateiskeptsmallbyperformingtheaggregationeachtimeamessagearrives.
Butsomeaggregationstrategiesmightrequireperformingtheaggregationafterallmessagesofan
aggregate arrived. To accommodate for those aggregation strategies and to support the
ExtendedAggregationCollections implementation of aggregate timeouts, all aggregates
are wrapped in an AggregateExchange 3 . The AggregateExchange transparently offers all
methods of the wrapped Exchange and adds some useful functionality that can be used to im
plementanaggregationstrategy.Amongthisfunctionalityistheabilitytostorealistofthemes
sageswhichbelongtothisaggregate.Italsostorestheamountofmessagesthatwereaggregatedin
this aggregate, which can be useful when implementing a completeness condition based on the
amountofaggregatedmessages.
TheEAI2Camelframeworkdevelopedinthisworkimplementsalreadytwoaggregationstrate
gies.OneofthemistheAggregationStrategyBest 4 thatperformstheaggregationbychoosing
the best message as the aggregated message. The best message is selected according to a value
contained in the message which is identified using an XPath expression. The messages are then
aggregatedbycomparingthisdesignatedvalueofanincomingmessagewiththecurrentaggregate
and choosing the highest or the lowest value. The comparison is done numerically if possible or
lexicographicallyotherwise.Theotheraggregationstrategyimplementedintheframeworkisthe
AggregationStrategyMostRecent. This strategy uses the most recently arrived message as
theaggregatedmessage.
TheExtendedAggregationCollectionusesaCamelPredicatetoimplementthecompleteness
condition.ThiscompletenessconditionPredicate 5 canuseallinformationavailablethroughthe
AggregateExchange interface. Especially it can use the message count or a possible message
historystoredthere.ThreecompletenessPredicatesarealreadyimplementedintheframework.
Two of them are simple Predicates that never respectively always hold. The
CompletnessPredicateNever 6 is particularlyusefulinconjunction with the timeout mechan

org.apache.camel.processor.aggregate.AggregationStrategy
org.apache.camel.Exchange
3de.unistuttgart.iaas.framework.eai2camel.routing.aggregator.AggregateExchange
4de.unistuttgart.iaas.framework.eai2camel.routing.aggregator.AggregationStrategyBest
5org.apache.camel.Predicate
6de.unistuttgart.iaas.framework.eai2camel.routing.aggregator.CompletnessPredicateNever
1
2

46

4.4GenerationofApacheCamelbasedJavacode

ism implemented in the ExtendedAggregationCollection. This timeout mechanism allows


overridingacompletenessconditionafteracertainamountoftimepassed,andthusmarkingthe
exchange as complete. This functionality is not implemented in a completeness condition as the
completenessconditionisevaluatedeachtimeamessagearrivesforacertainaggregate.Ifapossi
ble timeout would only be checked on incoming messages, then the timeout might never be de
tectedifnomessageisarrivinganymoreforanaggregate.Thiswouldrenderthetimeoutmechan
ism useless, thus it is implemented directly in the ExtendedAggregationCollection,
supported by the AggregateExchange. The third completeness condition implemented in the
frameworkistheoneimplementedintheCompletnessPredicateMessageCount 1 .Thissimple
completenessconditionsappliestoaggregatesthataggregatedacertainamountofmessages.
To correlate an incoming message to an aggregate, i.e. to the messages it should be aggregated
with,theExtendedAggregationCollectionusesaCamelExpression.Asalreadydiscussedin
chapter3(3.4.6Aggregator)thisExpressionneedstoreturnanidentifierthatcanbecomparedto
theonereturnedbyothermessages.InconjunctionwiththisframeworktheXPathExpression 2
ofApacheCamelcanbeusedtoidentifyavalueinthemessagesXMLbodyascorrelationidentifi
er.

4.4

Generation of Apache Camel based Java-code

ThissectiondescribeshowtheactualgenerationofApacheCamelbasedJavacodeisdone.Itde
scribeshowthegeneratorcodeisintegratedinthegraphicaleditorimplementedby[Dru07],and
howthemessagingsystemmodelistraversedtogeneratethecode.

4.4.1

Parameterization of the EAI patterns

Intheworkof[Dru07]theEAIpatternswereanalyzedregardingwhatparametersareneededto
usethepatterns.Theseparameterswerefirstanalyzedtheoreticallyandthenusedfortheimple
mentationoftheEclipsebasededitorimplementedby[Dru07].Toimplementthemodeledmessag
ingsystemsasCamelbasedJavaapplicationstheparametersstoredinthemessagingsystemmod
el,developedby[Dru07],hadtobeused.Butforsomepatternsthesuppliedparameterswerenot
sufficienttogenerateasolutionthatexecutesthismessagingsystem.Thereasonstheparameters
didnt suffice were mostly not because the theoretical parameterization was lacking a parameter,
butbecausesomeparametersintheimplementationoftheeditordidntcontaindeploymentspecif
icinformationwhichwasarequirementtotheeditordesign.Inparticularthepatternsthatusea
web service had only the WSDL porttype and the WSDL operation specified. But to actually in
vokethewebservicewithoutusinganydiscoverymechanism,theconcreteWSDLserviceandthe
concreteWSDLport,theoperationshallbeinvokedon,needstobeknown.

1de.unistuttgart.iaas.framework.eai2camel.routing.aggregator
.CompletnessPredicateMessageCount
2org.apache.camel.model.language.XPathExpression

47

IMPLEMENTATION

OnlytheAggregatorpatternwaslackingaparameterthatisnotadeploymentspecificparameter.
Namelyintheworkof[Dru07]theAggregatorpatternislackingacorrelationidentifier.Therea
sonthisparameterwasomittedisprobablybecausetheimplementationofthisworkwastargeted
to WSBPEL. A WSBPEL process is instance based, i.e. the data flowing through a WSBPEL
processalwaysbelongstoacertainprocessinstance.ThustheAggregatorimplementationinWS
BPELdoesntneedtocorrelatethemessagestoanaggregateastheyarealreadycorrelatedbythe
processinstancetheybelongto.
Togettheneededadditionalparametersforthewebservice,agraphicaldialogwascreatedinthis
work.ThisdialogisimplementedintheEai2CamelWebServiceConfigurationDialog 1 class
and is shown for each pattern, needing the information during the code generation. This is not
reallyauserfriendlywayofcollectingtherequiredparameters,andcouldbeimprovedbyfuture
works.ThesameapproachisusedtocollecttherequiredcorrelationidentifierfortheAggregator,
wherethedialogisimplementedintheEai2CamelAggregatorConfigurationDialog 2 class.

4.4.2

Integration into the Eclipse based Editor

The integration into the Eclipse based Editor from [Dru07] is being done in a minimal invasive
fashion.ThegeneratorintegratesintotheeditorbyimplementingasocalledActionDelegate 3 .
ThisprovidesanadditionalactioninformofabuttoninEclipsestoolbarandanadditionalentry
in the menu bar. All classes invoked by the ActionDelegate are independent of the Eclipse
basededitorimplementation.Theyjustrelyonthemodel 4 usedtostorethemessagingsystem.

4.4.3

Generation of the Code

ThegenerationstartswhentheGenerateCamelActionDelegate 5 isinvoked.Itchecksthemes
saging system for errors in the same way the corresponding ActionDelegate of the WSBPEL
generatingpartdoes.ThenitcreatesaCamelWriter 6 instanceandinvokesitswrite()method.
This method adds the JavaNature to the project the current messaging model is located in. This
means it makes the project a java project. Then it adds the libraries that are required to run the
generated messaging solution to the Java project. Theselibrariesare listedinsection4.4.4below.
AftertheJavaprojecthasbeeninitializedapackageundertheeai2camel.generatedSystems 7
iscreatedandthecreatedpackageispopulatedwithsometemplates.
The actual messaging system is then generated by traversing the messaging system model in a
breathfirstmanner,startingfromanodethatisaninterfacetotheoutsideworld.Usuallythisisan
ExternalServicepatternthathasonlyanoutgoingchannelconnectedtoit.Thereasonfortravers

de.unistuttgart.iaas.eaiparam.editors.dialogs.Eai2CamelWebServiceConfigurationDialog
de.unistuttgart.iaas.eaiparam.editors.dialogs.Eai2CamelAggregatorConfigurationDialog
3org.eclipse.ui.IWorkbenchWindowActionDelegate
4de.unistuttgart.iaas.eaiparam.model.*
5de.unistuttgart.iaas.eaiparam.actions.GenerateCamelActionDelegate
6de.unistuttgart.iaas.eaiparam.actions.CamelWriter
7de.unistuttgart.iaas.eaiparam.eai2camel.generatedSystems
1
2

48

4.5ExampleMessagingSystem

ingthemessagingsystemusingbreathfirstsearchistogenerateamessagingsystemthatishuman
readable.Usingthisapproachthepatternsappearinthegeneratedsourcecodeintheorderofthe
messageflow.
While traversing the messaging system a generator method for each filter (in the sense of the
PipesandFilters architecture) of the messagingsystem isinvoked. Thesegenerator methodsare
implemented in a separate class, the CamelFilterPatternGenerator 1 class. To create an ex
tensiblesolutiontheappropriategeneratormethodforafilterdoesntneedtobeinvokeddirectly.
Instead the CamelFilterPatternGenerator offers a getGeneratorMethod() method
whichusesintrospectiontodiscovertheappropriategeneratormethodforthecurrentfilter.This
enables the implementation of additional patterns by simply adding an appropriate generator
methodtotheCamelFilterPatternGeneratorclass.

4.4.4

Required Libraries

ThegeneratedmessagingsystemrequiressomeJavalibrariestobeabletorun.Theselibrariesand
theversionusedwhiledevelopingtheEAI2Camelgeneratorarelistedinthefollowing:
ApacheCamel1.2.0[Cam]isneededasthegeneratedJavaapplicationisbasedonthisApache
Camel.
TheSpringFramework2.5[Spr]isaframeworkthatisusedbyApacheCamelandisthusre
quired.
TheEAI2Camelframework,whichwasdevelopedaspartofthisworkandcontainstheac
tualimplementationoftheEAIpatterns,isalsoneeded.
ApacheActiveMQ4.1.1[Act]whichisrequiredasitisusedasJMSproviderforthegenerated
messagingsystems.
Apache CXF 2.0.3 [Cxf] which is used as JAXWS provider and is thus needed to invoke the
webservicesthedifferentpatternsuse.

4.5

Example Messaging System

To demonstrate the Java generator and the EAI2Camel framework developed in this work an
example messaging system has been created. This created example implements the LoanBroker
scenario,whereamessagingsystemismodeledthatprovidesawebservice.Thiswebserviceim
plementstheLoanBrokerscenariobysendingtheloanquoterequestthroughachainofEAIpat
terns and returning the resulting message to the web service client. Figure 2 shows the modeled
messagingsystem.

de.unistuttgart.iaas.eaiparam.actions.CamelFilterPatternGenerator

49

IMPLEMENTATION

Figure2:TheLoanBrokermessagingsystem
The modeled messaging system starts with a pair of External Service patterns that provide the
webservice.IncomingrequestmessagesaresenttoaContent Enricher thatenrichestherequest
with a credit score by asking a credit bureau for the customers credit standing. Then the list of
banksthatfitthecustomerprofileiscomputedbyanXSLTstylesheetandaddedtothemessage.
Here,aMessage Translator isused, because the computationis done by an XSLT stylesheet, but
actuallythecreationoftherecipientlistimplementstheContent Enricherpattern.Afterthisstep
the message is distributed to the banks according to the recipient list contained in the message,
whereupontheresponsesreceivedfromthebanksareaggregatedtoasinglemessagebyselecting
the best loan offer. Finally the aggregated message is translated to fit the web services response
messagetype,andthensentasresponsetothewebserviceclient.
To be able to run the generated messaging system implementation of this example, all necessary
webservicesandXSLTstylesheetswereimplementedaspartofthiswork.

50

Bibliography
[AAA+07]

Alexandre Alves, Assaf Arkin, Sid Askary, Charlton Barreto, Ben Bloch, Francisco
Curbera,MarkFord,YaronGoland,AlejandroGuzar,NeelakantanKartha,Canyang
Kevin Liu, Rania Khalaf, Dieter Knig, Mike Marin, Vinkesh Mehta, Satish Thatte,
DannyvanderRijn,PrasadYendluriandAlexYiu.Web Services Business Process
Execution Language, Version 2.0. Comitee Specification,April 2007.Available elec
tronicallyat:
http://docs.oasisopen.org/wsbpel/2.0/wsbpelv2.0.pdf
Accessedon:07.04.2008

[Act]

ApacheActiveMQ,Version4.1.1.Availableelectronicallyat:
http://activemq.apache.org/
Accessedon:02.04.2008

[BL07]

DavidBoothandCanyangKevinLiu.WebServicesDescriptionLanguage(WSDL),
Version: 2.0. W3C Recommendation, June 2007. Available electronically at:
http://www.w3.org/TR/wsdl20primer/
Accessedon:13.04.2008

[BO06]

RahulBiswas,EdOrt:The Java Persistence API A Simpler Programming Model


forEntityPersistence.SunMicrosystemsInc.,2006.Availableelectronicallyat:
http://java.sun.com/developer/technicalArticles/J2EE/jpa/
Accessedon:07.04.2008

[BPS+06]

Tim Bray, Jean Paoli, C. M. SperbergMcQueen, Eve Maler and Franois Yergeau.
ExtensibleMarkupLanguage(XML)1.0(FourthEdition).W3CRecommendation,
September2006.Availableelectronicallyat:
http://www.w3.org/TR/xml/
Accessedon:13.04.2008

[Cam]

ApacheCamel,Version:1.2.0.Availableelectronicallyat:
http://activemq.apache.org/camel/index.html
Accessedon:02.04.2008

[CD99]

James Clark and Steve DeRose. XML Path Language (XPath), Version: 1.0. W3C
Recommendation,November1999.Availableelectronicallyat:
http://www.w3.org/TR/xpath/
Accessedon:07.04.2008

51

BIBLIOGRAPHY
[CHM06]

[Cla99]

Roberto Chinnici, Marc Hadley and Rajiv Mordani. The Java API for XMLBased
WebServices(JAXWS)2.0.Specification,April2006.Availableelectronicallyat:
http://jcp.org/aboutJava/communityprocess/final/jsr224/index.html
Accessedon:13.04.2008
James Clark. XSL Transformations (XSLT), Version: 1.0. W3C Recommendation,
November1999.Availableelectronicallyat:
http://www.w3.org/TR/xslt/
Accessedon:13.04.2008

[Cxf]

ApacheCXF,Version2.0.3.Availableelectronicallyat:
http://incubator.apache.org/cxf/
Accessedon:02.04.2008

[DK06]

Linda DeMichiel and Michael Keith. Enterprise JavaBeans,Version: 3.0. Specifica


tion,May2006.Availableelectronicallyat:
http://jcp.org/aboutJava/communityprocess/final/jsr220/index.html
Accessedon:07.04.2008

[Dru07]

BettinaDruckenmller.ParametrisierungvonEAIPatterns.DiplomarbeitNr.2583,
UniversittStuttgart,2007.

[Ecl]

EclipseDevelopmentPlatform,Version:3.2.2.Availableelectronicallyat:
http://www.eclipse.org/
Accessedon:22.11.2007

[FW04]

DavidC.FallsideandPriscillaWalmsley.XML Schema, Second Edition.W3CRec


ommendation,October2004.Availableelectronicallyat:
http://www.w3.org/TR/xmlschema0/
Accessedon:13.04.2008

[HBS+]

MarkHapner,RichBurridge,RahulSharma,JosephFialliandKateStout.JavaMes
sage Service Specification Final Release 1.1. Specification, April 2002. Available
electronicallyat:
http://jcp.org/aboutJava/communityprocess/final/jsr914/index.html
Accessedon:07.04.2008

[HW03]

Gregor Hohpe, Bobby Woolf: Enterprise Integration Patterns, AddisonWesley


Professional,2003,ISBN0321200683

[Jdt]

Eclipse:JavaDevelopmentTools(JDT),Version:3.2.2.Availableelectronicallyat:
http://www.eclipse.org/jdt/
Accessedon:13.04.2008

[Min]

ApacheMINA.Availableelectronicallyat:
http://mina.apache.org/
Accessedon:02.04.2008

52

[ML07]

NiloMitraandYvesLafon.SOAP,Version:1.2.W3CRecommendation,April2007.
Availableelectronicallyat:
http://www.w3.org/TR/soap12part0/
Accessedon:13.04.2008

[Ode]

ApacheODE.Availableelectronicallyat:
http://ode.apache.org/
Accessedon:18.04.2008

[Ser]

ApacheServiceMix.Availableelectronicallyat:
http://servicemix.apache.org/
Accessedon:02.04.2008

[Spr]

SpringFramework,Version2.5.Availableelectronicallyat:
http://www.springframework.org/
Accessedon:04.04.2008

[Vep]

Eclipse:VisualEditorProject,Version:1.2.Availableelectronicallyat:
http://www.eclipse.org/vep/
Accessedon:13.04.2008

[Wal06]

NormanWalsh.JavaAPIforXMLProcessing.Specification,August2006.Available
electronicallyat:
http://jcp.org/aboutJava/communityprocess/mrel/jsr206/
Accessedon:13.04.2008

53

Appendix
A.1

Camel example using built-in Pipeline

This example demonstrates the differences discussed in chapter 3.3 using Camels Pipeline with
synchronousorasynchronousComponents,wheretheasynchronousComponentdoesntsupport
InOut 1 messageExchanges.TheexampleconfigurestwodifferentPipelines 2 ,onestartingfrom
the Endpoint seda:endpointA using the SEDAComponent which implements inmemory
queuesandisthusasynchronousandonestartingfromtheEndpointdirect:endpointAus
ingtheDirectComponentwhoseProducerdirectlyinvokesitsConsumerandthusissynchronous.
When executed, this example sends five test messages to each ofthe two Pipelines andprints
themessagesreceivedasoutputfromthePipelinetotheconsoleincludingthereceivingthreads
ID. Also the two Filter Processors print a message to the console on processing, including their
threads ID. The second Filter Processor also waits for 0.5 seconds to provoke the parallel
processingofthedifferenttestmessages.TheJavacodeofthisexampleiscompleteandreadytobe
compiled.Afterthecodeyoucanfindapossibleoutputandadiscussionoftheoutput.

A.1.1
import
import
import
import
import
import
import

Java Code
org.apache.camel.CamelContext;
org.apache.camel.CamelTemplate;
org.apache.camel.Exchange;
org.apache.camel.Message;
org.apache.camel.Processor;
org.apache.camel.builder.RouteBuilder;
org.apache.camel.impl.DefaultCamelContext;

public class PipesAndFiltersExample {


public static void main(String[] args) {
try {
// create the camel context:
CamelContext context = new DefaultCamelContext();
// add the routes:
context.addRoutes(new RouteBuilder() {
public void configure() {

1
2

org.apache.camel.ExchangePattern.InOut
org.apache.camel.processor.Pipeline

55

APPENDIX

// create the message processor for filter 1:


Processor myFilter1Processor = new Processor() {
public void process(Exchange e) {
// get the inbound request message:
Message inboundMessage = e.getIn();
System.out.println("
Filter 1 ["
+ Thread.currentThread().getId()
+ "] processing:"
+ inboundMessage.getBody(String.class)
.split("\n")[0]);
// create the new body:
String responseBody
= inboundMessage.getBody(String.class)
+ " message processed by filter 1"
+ "\n";
// set the outbound response message:
Message outboundMessage = e.getOut();
outboundMessage.setBody(responseBody);
}
};
// create the message processor for filter 2:
Processor myFilter2Processor = new Processor() {
public void process(Exchange e) {
// get the inbound request message:
Message inboundMessage = e.getIn();
try {
// try to sleep 0.5 seconds:
Thread.sleep(500);
} catch (InterruptedException ex) {}
System.out.println("
Filter 2 ["
+ Thread.currentThread().getId()
+ "] processing:"
+ inboundMessage.getBody(String.class)
.split("\n")[0]);
// create the new body:
String responseBody
= inboundMessage.getBody(String.class)
+ " - message processed by filter 2"
+ "\n";
// set the outbound response message:
Message outboundMessage = e.getOut();
outboundMessage.setBody(responseBody);
}
};
// create the message processor for endpoint B:
Processor myEndpointBProcessor
= new Processor() {
public void process(Exchange e) {
// get the inbound request message:
Message inboundMessage = e.getIn();
System.out.println("Receiving message ["
56

A.1CamelexampleusingbuiltinPipeline

+ Thread.currentThread().getId()
+ "]: \n"
+ inboundMessage
.getBody(String.class));
}
};

// create the routes for async-processing:


from("seda:endpointFilter1")
.process(myFilter1Processor);
from("seda:endpointFilter2")
.process(myFilter2Processor);
from("seda:endpointB")
.process(myEndpointBProcessor);
// create the pipeline for async-processing:
from("seda:endpointA")
.pipeline("seda:endpointFilter1",
"seda:endpointFilter2",
"seda:endpointB");

// create the routes for sync-processing:


from("direct:endpointFilter1")
.process(myFilter1Processor);
from("direct:endpointFilter2")
.process(myFilter2Processor);
from("direct:endpointB")
.process(myEndpointBProcessor);
// create the pipeline for sync-processing:
from("direct:endpointA")
.pipeline("direct:endpointFilter1",
"direct:endpointFilter2",
"direct:endpointB");
}
});
// create a camel template for sending messages:
CamelTemplate camelTemplate = new CamelTemplate(context);
// start the camel context
context.start();
// send messages to async pipeline:
System.out.println(
"#### Example with asynchronous endpoints: ####"
+ "\n\n");
for (int i = 1; i <= 5; i++) {
camelTemplate.sendBody("seda:endpointA",
57

APPENDIX

"message body #" + i + "\n");


}
Thread.sleep(3000); // wait for 3 seconds
// send messages to sync pipeline:
System.out.println("\n\n\n\n"
+ "#### Example with synchronous endpoints: ####"
+ "\n\n");;
for (int i = 1; i <= 5; i++) {
camelTemplate.sendBody("direct:endpointA",
"message body #" + i + "\n");
}
Thread.sleep(5000); // wait for 5 seconds
context.stop();
} catch (Exception e) {
// this is an example -> don't handle exceptions:
e.printStackTrace();
}
}
}

A.1.2

Output

#### Example with asynchronous endpoints: ####

Filter 1 [8] processing:message body #1


Receiving message [10]:
message body #1
Filter 1 [8] processing:message
Filter 1 [8] processing:message
Filter 1 [8] processing:message
Filter 1 [8] processing:message
Receiving message [10]:
message body #2
Receiving message [10]:
message body #3
Receiving message [10]:
message body #4
Receiving message [10]:
message body #5

58

body
body
body
body

#2
#3
#4
#5

A.1CamelexampleusingbuiltinPipeline

Filter
Filter
Filter
Filter
Filter

2
2
2
2
2

[9]
[9]
[9]
[9]
[9]

processing:message
processing:message
processing:message
processing:message
processing:message

body
body
body
body
body

#1
#2
#3
#4
#5

#### Example with synchronous endpoints: ####

Filter 1 [1] processing:message body #1


Filter 2 [1] processing:message body #1
Receiving message [1]:
message body #1
message processed by filter 1
- message processed by filter 2
Filter 1 [1] processing:message body #2
Filter 2 [1] processing:message body #2
Receiving message [1]:
message body #2
message processed by filter 1
- message processed by filter 2
Filter 1 [1] processing:message body #3
Filter 2 [1] processing:message body #3
Receiving message [1]:
message body #3
message processed by filter 1
- message processed by filter 2
Filter 1 [1] processing:message body #4
Filter 2 [1] processing:message body #4
Receiving message [1]:
message body #4
message processed by filter 1
- message processed by filter 2
Filter 1 [1] processing:message body #5
Filter 2 [1] processing:message body #5
Receiving message [1]:
message body #5
message processed by filter 1
- message processed by filter 2

A.1.3

Discussion

Theoutputshowstwothings:FirstyoucanseetheproblemofusingasynchronousComponents
thatdontimplementtheInOutmessageexchangepatternwithCamelsPipeline,whichwasmen
59

APPENDIX

tioned in chapter 3.3, in the first part of the results (#### Example with asynchronous endpoints
####). You can see that the messages leave the Pipeline unaltered due to the fact that the Filters
outputisnotreusedbythefollowingFilter,neitheritisreceivedbythefinalEndpoint(foranex
planationonwhythisis,seechapter3.3).Alsoyoucanseethatthetestmessagesarereceivedby
thefinalEndpointevenbeforetheyareprocessedbythesecondFilterProcessor(thisisalsodis
cussed in chapter 3.3). Second you can see in the second part of the results (#### Example with
synchronous endpoints ####) that due to the DirectComponent, which is synchronous, there is
onlyonemessageinthePipelineateachpointintime(foradiscussionseechapter3.3).

60

Erklrung

Icherklrehiermit,dassichdievorliegendeArbeitselbstn
dig und ohne fremde Hilfe verfasst und keine anderen als
dieangegebenenHilfsmittelverwendethabe.

Stuttgart,24.04.2008

_______________________________
(PascalKolb)

61

Das könnte Ihnen auch gefallen