Rc047-010d-Enterprise Integration Patterns 1
Rc047-010d-Enterprise Integration Patterns 1
Rc047-010d-Enterprise Integration Patterns 1
CONTENTS INCLUDE:
By Claus Ibsen
Problem A single event often triggers a sequence of processing steps
About Enterprise Integration Patterns
Solution Use Pipes and Filters to divide a larger processing steps (filters) that are
connected by channels (pipes)
Integration is a hard problem. To help deal with the complexity
Camel Camel supports Pipes and Filters using the pipeline node.
of integration problems the Enterprise Integration Patterns
Java DSL from(“jms:queue:order:in”).pipeline(“direct:transformOrd
(EIP) have become the standard way to describe, document er”, “direct:validateOrder”, “jms:queue:order:process”);
and implement complex integration problems. Hohpe & Where jms represents the JMS component used for consuming JMS messages
on the JMS broker. Direct is used for combining endpoints in a synchronous
Woolf’s book the Enterprise Integration Patterns has become fashion, allow you to divide routes into sub routes and/or reuse common routes.
the bible in the integration space – essential reading for any Tip: Pipeline is the default mode of operation when you specify multiple
integration professional. outputs, so it can be omitted and replaced with the more common node:
from(“jms:queue:order:in”).to(“direct:transformOrder”,
“direct:validateOrder”, “jms:queue:order:process”);
Apache Camel is an open source project for implementing
TIP: You can also separate each step as individual to nodes:
the EIP easily in a few lines of Java code or Spring XML from(“jms:queue:order:in”)
configuration. This reference card, the first in a two card series, .to(“direct:transformOrder”)
.to(“direct:validateOrder”)
guides you through the most common Enterprise Integration .to(“jms:queue:order:process”);
Patterns and gives you examples of how to implement them Spring DSL <route>
<from uri=”jms:queue:order:in”/>
either in Java code or using Spring XML. This Refcard is
www.dzone.com
<pipeline>
<to uri=”direct:transformOrder”/>
targeted for software developers and enterprise architects, but <to uri=”direct:validateOrder”/>
<to uri=”jms:queue:order:process”/>
anyone in the integration space can benefit as well. </pipeline>
</route>
<route>
ABout apache camel <from uri=”jms:queue:order:in”/>
<to uri=”direct:transformOrder”/>
<to uri=”direct:validateOrder”/>
<to uri=”jms:queue:order:process”/>
Apache Camel is a powerful open source integration platform </route>
Data Formats for various popular formats such as: CSV, EDI, Problem Pipes and Filters route each message in the same processing steps. How can we
route messages differently?
FIX, HL7, JAXB, Json, Xstream. Camel is an integration API that
Solution Filter using predicates to choose the right output destination.
can be embedded in any server of choice such as: J2EE Server,
Camel Camel supports Message Router using the choice node. For more details see the
ActiveMQ, Tomcat, OSGi, or as standalone. Camels Bean Content Based router pattern.
Integration let you define loose coupling allowing you to fully
separate your business logic from the integration logic. Camel
Are you using Apache Camel, Apache ActiveMQ,
is based on a modular architecture allowing you to plugin your
Apache ServiceMix, or Apache CXF?
own component or data format, so they seamlessly blend in
with existing modules. Camel provides a test kit for unit and Progress FUSE products are Apache-licensed,
integration testing with strong mock and assertion capabilities. certified releases based on these Apache SOA
projects.
Essential Patterns
Synchronized with Apache projects
This group consists of the most essential patterns that anyone Enterprise support by Apache committers
working with integration must know. Online and on-site training
Pipes and Filters
Register for a FREE webinar & learn
How can we perform complex processing on a message while maintaining how to build & deploy integration
independence and flexibility? flows, web services & RESTful
services with Apache Camel, Apache
Pipe Pipe Pipe Pipe CXF, and Apache ServiceMix
Decrypt Authenticate De-Dup
Content-Based Router Camel Camel supports the message translator using the processor, bean or
transform nodes.
How do we handle a situation where the implementation of a single logical
function (e.g., inventory check) is spread across multiple physical systems?
TIP: Camel routes the message as a chain of processor nodes.
Problem How do we ensure a Message is sent to the correct recipient based on from(“direct:transformOrder”)
information from its content? .process(new OrderTransformProcessor());
Solution Use a Content-Based Router to route each message to the correct recipient Bean
based on the message content. Instead of the processor we can use Bean (POJO). An advantage of using a
Bean over Processor is the fact that we do not have to implement or use any
Camel Camel has extensive support for Content-Based Routing. Camel supports Camel specific interfaces or types. This allows you to fully decouple your beans
content based routing based on choice, filter, or any other expression. from Camel.
Java DSL Choice
public class OrderTransformerBean {
from(“jms:queue:order”) public StringtransformOrder(String body) {
.choice()
// do message translation here
.when(header(“type”).in(“widget”,“wiggy”))
}
.to(“jms:queue:order:widget”) }
.when(header(“type”).isEqualTo(“gadget”))
.to(“jms:queue:order:gadget”) Object transformer = new OrderTransformerBean();
.otherwise().to(“jms:queue:order:misc”) from(“direct:transformOrder”).bean(transformer);
.end();
TIP: In the route above end() can be omitted as its the last node and we do not TIP: Camel can create an instance of the bean automatically; you can just refer
route the message to a new destination after the choice. to the class type.
TIP: You can continue routing after the choice ends.
from(“direct:transformOrder”)
Spring Choice .bean(OrderTransformerBean.class);
DSL <route>
<from uri=”jms:queue:order”/>
TIP: Camel will try to figure out which method to invoke on the bean in
<choice> case there are multiple methods. In case of ambiguity you can specify which
<when> methods to invoke by the method parameter:
<simple>${header.type} in ‘widget,wiggy’</simple>
<to uri=”jms:queue:order:widget”/>
from(“direct:transformOrder”)
</when> .bean(OrderTransformerBean.class, “transformOrder”);
<when>
<simple>${header.type} == ‘gadget’</simple> Transform
<to uri=”jms:queue:order:gadget”/>
Transform is a particular processor allowing you to set a response to be
</when>
returned to the original caller. We use transform to return a constant ACK
<otherwise>
response to the TCP listener after we have copied the message to the JMS
<to uri=”jms:queue:order:misc”/>
queue. Notice we use a constant to build an “ACK” string as response.
</otherwise>
</choice> from(“mina:tcp://localhost:8888?textline=true”)
</route> .to(“jms:queue:order:in”)
.transform(constant(“ACK”));
TIP: In Spring DSL you cannot invoke code, as opposed to the Java DSL that is
100% Java. To express the predicates for the choices we need to use a language.
We will use simple language that uses a simple expression parser that supports Spring DSL Processor
a limited set of operators. You can use any of the more powerful languages <route>
supported in Camel such as: JavaScript, Groovy, Unified EL and many others. <from uri=”direct:transformOrder”/>
<process ref=”transformer”/>
TIP: You can also use a method call to invoke a method on a bean to evaluate the </route>
predicate. Lets try that:
<bean id=”transformer” class=”com.mycompany.
<when> OrderTransformProcessor”/>
<method bean=”myBean” method=”isGadget”/>
... In Spring DSL Camel will look up the processor or POJO/Bean in the registry
</when> based on the id of the bean.
Bean
<bean id=”myBean” class=”com.mycomapany.MyBean”/>
<route>
<from uri=”direct:transformOrder”/>
public boolean isGadget(@Header(name = “type”) String <bean ref=”transformer”/>
type) {
</route>
return type.equals(“Gadget”);
} <bean id=”tramsformer”
Notice how we use Bean Parameter Binding to instruct Camel to invoke this class=”com.mycompany.OrderTransformBean”/>
method and pass in the type header as the String parameter. This allows your
Transform
code to be fully decoupled from any Camel API so its easy to read, write and
<route>
unit test.
<from uri=”mina:tcp://localhost:8888?textline=true”/>
<to uri=”jms:queue:order:in”/>
Message Translator <transform>
<constant>ACK</constant>
How can systems using different data formats communicate with each other </transform>
using messaging? </route>
Translator Annotation You can also use the @Consume annotation for transformations. For
DSL example in the method below we consume from a JMS queue and do
the transformation in regular Java code. Notice that the input and output
parameters of the method is String. Camel will automatically coerce the
payload to the expected type defined by the method. Since this is a JMS
example the response will be sent back to the JMS reply-to destination.
Message Filter Annotation TIP: Notice how we used Bean Parameter Binding to bind the parameters to
DSL, the route method based on an @XPath expression on the XML payload of the
How can a component avoid receiving unwanted messages? continued JMS message. This allows us to extract the customer id as a string parameter.
@Header wil bind a JMS property with the key location. Document is the XML
payload of the JMS message.
TIP: Camel uses its strong type converter feature to convert the payload to the
type of the method parameter. We could use String and Camel will convert
the body to a String instead. You can register your own type converters as well
Widget Gadget Widget Message Widget Widget using the @Converter annotation at the class and method level.
Quote Quote Quote Filter Quote Quote
Spring For the Spring DSL we use XPath to evaluate the predicate. The $test is a special Problem How can we route messages based on a static or dynamic list of
DSL shorthand in Camel to refer to the header with the given name. So even if the destinations?
payload is not XML based we can still use XPath to evaluate predicates.
Solution Define a channel for each recipient. Then use a Recipient List to inspect an
<route> incoming message, determine the list of desired recipients and forward the
<from uri=”jms:queue:inbox”/> message to all channels associated with the recipients in the list.
<filter>
<xpath>$test = ‘false’</xpath> Camel Camel supports the static Recipient List using the multicast node, and the
<to uri=”jms:queue:inbox”/> dynamic Recipient List using the recipientList node.
</filter>
</route> Java DSL Static
In this route we route to a static list of two recipients, that will receive a copy
Dynamic Router of the same message simultaneously.
from(“jms:queue:inbox”)
How can you avoid the dependency of the router on all possible destinations .multicast().to(“file://backup”, “seda:inbox”);
while maintaining its efficiency?
Dynamic
Dynamic Router Output Channel In this route we route to a dynamic list of recipients defined in the message
A header [mails] containing a list of recipients as endpoint URLs. The bean
Message Router processMails is used to add the header[mails] to the message.
Input Channel Output Channel
from(“seda:confirmMails”).beanRef(processMails)
B .recipientList(“destinations”);
Output Channel And in the process mails bean we use @Headers Bean Parameter Binding to
provide a java.util.Map to store the recipients.
C public void confirm(@Headers Map headers, @Body String
body} {
Dynamic
String[] recipients = ...
Rule Base
headers.put(“destinations”, recipients);
}
Control Channel
Spring DSL Static
Problem How can we route messages based on a dynamic list of destinations? <route>
<from uri=”jms:queue:inbox/>
Solution Use a Dynamic Router, a router that can self-configure based on special
<multicast>
configuration messages from participating destinations.
<to uri=”file://backup”/>
Camel Camel has support for Dynamic Router using the Dynamic Recipient List <to uri=”seda:inbox”/>
combined with a data store holding the list of destinations. </multicast>
</route>
Java DSL We use a Processor as the dynamic router to determine the destinations. We
could also have used a Bean instead. Dynamic
from(“jms:queue:order”) In this example we invoke a method call on a Bean to provide the dynamic
.processRef(myDynamicRouter)
list of recipients.
.recipientList(“destinations”); <route>
<from uri=”jms:queue:inbox/>
public class MyDynamicRouter implements Processor { <recipientList>
public void process(Exchange exchange) {
<method bean=”myDynamicRouter” method=”route”/>
// query a data store to find the best match of the </recipientList>
// endpoint and return the destination(s) in the </route>
// header exchange.getIn()
// .setHeader(“destinations”, list); <bean id=”myDynamicRouter”
}
class=”com.mycompany.MyDynamicRouter”/>
} public class myDynamicRouter {
public String[] route(String body) {
Spring DSL <route> return new String[] { “file://backup”, .... }
<from uri=”jms:queue:order”/> }
<process ref=”myDynamicRouter”/>
}
<recipientList>
<header>destinations</destinations> Annotation In the CustomerService class we annoate the whereTo method with
</recipientList> DSL @RecipientList, and return a single destination based on the customer id.
</route> Notice the flexibility of Camel as it can adapt accordingly to how you define
what your methods are returning: a single element, a list, an iterator, etc.
Annotation public class MyDynamicRouter {
DSL @Consume(uri = “jms:queue:order”) public class CustomerService {
@RecipientList @RecipientList
public List<String> route(@XPath(“/customer/id”) public String whereTo(@Header(“customerId”) id) {
String customerId, @Header(“location”) String location, return “jms:queue:customer:” + id;
Document body) { }
// query data store, find best match for the }
//endpoint and return destination (s) And then we can route to the bean and it will act as a dynamic recipient list.
} from(“jms:queue:inbox”)
} .bean(CustomerService.class, “whereTo”);
How do we combine the results of individual, but related messages so that they Notice how we can use Bean Binding Parameter to get hold of the aggregation
can be processed as a whole? size as a parameter, instead of looking it up in the message.
Resequencer
How can we get a stream of related but out-of-sequence messages back into the
Inventory Inventory correct order?
Inventory
Item 1 Item 2 Item 3 Inventory
Aggregator Order
Solution Use a stateful filter, an Aggregator, to collect and store individual messages until it
receives a complete set of related messages to be published.
Resequencer
Camel Camel has support for the Aggregator using the aggregate node. Camel uses a
stateful batch processor that is capable of aggregating related messaged into a Problem How do we ensure ordering of messages?
single combined message. A correlation expression is used to determine which
messages should be aggregated. An aggregation strategy is used to combine Solution Use a stateful filter, a Resequencer, to collect and reorder messages so that they
aggregated messages into the result message. Camel’s aggregator also supports can be published in a specified order.
a completion predicate allowing you to signal when the aggregation is complete.
Camel also supports other completion signals based on timeout and/or a number Camel Camel has support for the Resequencer using the resequence node. Camel uses
of messages already aggregated. a stateful batch processor that is capable of reordering related messages. Camel
Delivery Fails
Camel Camel has support for Wire Tap using the wireTap node, that supports two
Reroute Delivery modes: traditional and new message. The traditional mode sends a copy of the
original message, as opposed to sending a new message. All messages are sent
as Event Message and runs in parallel with the original message.
Spring Traditional
DSL <route> Conclusion
<from uri=”jms:queue:order”/>
<wireTap uri=”seda:tappedOrder”/> The twelve patterns in this Refcard cover the most used
<to uri=”bean:processOrder”/>
</route>
patterns in the integration space, together with two of the
most complex such as the Aggregator and the Dead Letter
New Message
<route> Channel. In the second part of this series we will take a further
<choice> look at common patterns and transations.
<when>
<xpath>/order/priority = ‘high’</xpath> Get More Information
<wireTap uri=”seda:from”>
Camel Website The home of the Apache Camel project. Find downloads,
<body><xpath>/order/from</xpath></body> tutorials, examples, getting started guides, issue tracker,
</wireTap> http://camel.apache.org
roadmap, mailing lists, irc chat rooms, and how to get
<to uri=”bean:processHighOrder”/> help.
</when>
<otherwise> FuseSource Website The home of the FuseSource company, the professional
company behind Apache Camel with enterprise offerings,
<to uri=”bean:processOrder”/> http://fusesource.com
support, consulting and training.
</otherwise>
</choice> About Author The personal blog of the author of this reference card.
</route> http://davsclaus.blogspot.com
Bro
ugh
t to
you
by...
Professional Cheat Sheets You Can Trust
tt erns “Exactly what busy developers need:
n Pa
ld
ona
sig son
McD
simple, short, and to the point.”
De
Ja
By
#8
ired
Insp e
by th
GoF ller con
tinu
ed
ndle
r doe
sn’t
have
to
in tab
Cha d ultip ecific o should cep pat
this if the m up the
man
n M
an ac
z.co
n
sp s ents
be a ject ime. d is see passed
Download Now
Com reter of ob at runt handle plem ks to de to
...
n
uest som tion proces e no m
Itera tor ore req
n A g in metho
d
cep
dm ndlin
e e ar
tho e to ptio th
Exce ion is sm to ha up th tered or
e ca
n
Ob
se Me S renc ral
Refcardz.com
plate RN refe listed in mp
le ce pt ni
echa n pa ssed co un avio
Beh
TTE
n
ex
is en
ick
BIRT Windows Powershell
am
Tem Exa he .
A s has ack. W tion uest to ject
NP a qu s, a ct- cep Ob
it
n
st q
IG e s e rn b je call e ex e re
vid patt able O le th nd th
DES
! V is
pro s, hand s to ha
UT ard ign us ram .
des diag
JSF 2.0 Dependency Injection with EJB 3
ct
ABO refc oF) f Re le obje
erns ts o lass exa
mp oke
r
Patt ur (G lemen es c Inv
arz
n F o d rl d h
Des
ig go
f s: E inclu al w
o suc
Th is G a n
l 23 sign Pa
tt e rn e rn
patt , and a
re je ts
t ob mentin
c g AN
D
Adobe AIR Netbeans IDE JavaEditor
c
a h c M M
ef
in c u
orig kD
e
re.
Ea tion ons
tr ple CO ma
nd
boo Softwa rma to c their im om
BPM&BPMN Getting Started with Eclipse
re R
( low
e x p o n la rg cute is al ch
ati an b rm ts. +exe . Th
bject nship
s su
Cre y c fo je c an o
t th
e
ed
to ob ms, d as ed rela
tio
Get
nsh
ips
that
can psu
Enca quest
the
re
late
sa
and
e ha
to b llbacks
ca
.
nalit
y.
riant
times
or in
varia
ling
the
invo
catio
ing
n.
DZone, Inc. ISBN-13: 978-1-934238-50-9
ra o pose uing nctio led at va hand
io n ti ct cess be
av ,a la P ur
as q
ue
ack
fu je pro
Beh nships t re
1251 NW Maynard
ob
rela
tio
with
ob je c
s th
at c
a n b e
ed
You ne s need
st
callb
to
que
b
nd
e ha eded.
ne
sts is couple n
d fro m the
e th
ynch
e as the fu
ro nous nality
nctio
itho
to
y ne
ut an is
ed
ISBN-10: 1-934238-50-3
eals
it
ship Reque y of re de ar
ld be litat pattern ssing w tation articul
e: D tion faci
50795
or
e. Use
n
A hist shou d ce en p
ed to mman for pro implem ents its ting.
cop runtim rela type
ker
Cary, NC 27513
n
S s Whe invo y us
n
s co al m pec
jec t at cla Pro
to Th e
w id el th e ue ue
ac tu
d im
p le ex
are utilizing a job q of the ue is
Ob ged with
n
C ues ueue e que
han eals me.
y dge enq
que s. B en to th
e c : D P roxy Job orithm be giv knowle that is terface
b e ti
cop
g n ct
pile r S in
rato er mp
le of al ed ca to have d obje of the
ss S at com serv
888.678.0399
Exa ut
Deco nes
an
.com
919.678.0300
one
Abst tory
C C
Fac
B
State
t
pte
r eigh y
teg
Ada Flyw Stra od
z
Meth
more than 2 million software developers, architects and decision
S S r B
w. d
e rp rete plate
ridg
Refcardz Feedback Welcome
B B
Inte Tem
S B
er tor or
ww
C B r B
NSIB
ILIT
Y B
S
Com
po si te
P O succ
ess
or Sponsorship Opportunities 9 781934 238509
RES
“DZone is a developer’s dream,” says PC Magazine.
F
CH
AIN
O
ace
>> [email protected]
terf r
<<in andle
H st ( )
re
ndle
+ha
ern
1 ki ng
ler by lin .c o
m
and uest one
teH req z
cre () le a w.d
Con uest hand | ww