Emmanuel Vinel
Toulouse Java User Group
December 11, 2018
1
Apache Camel
About me
• Emmanuel Vinel
• Freelance
• @EmmanuelVinel
2
Connected
• Business
• Legal
• Technical
Client 1 Service 3
Service 1 Service NService 2
App 4Client/service 2
3
History
File
transfert
Shared
database
RPC
EAI
Message
Broker
Corba
SOA, ESB
4
Enterprise Service Bus
5
Client 1 Service 3
Service 1 Service NService 2
Client/service 2
Enterprise Service Bus
• Routes
• Transformation
• Error management
• Governance
• Security
• Repository
• Loose coupling
• Re-use
• Version
6
7
8
9
Ibsen, Claus; Anstey, Jonathan (2010), Camel in Action
, Manning Publications,
Community rock !
Implementation EIP
More than 200 components
10
Integration Framework
Application
A
Application
B
11
Camel in Action Book 12
Getting Started
Spring boot camel-archetype-spring-boot
CDI camel-archetype-cdi
Java camel-archetype-java
web camel-archetype-web
mvn archetype:generate 
-DarchetypeGroupId=org.apache.camel.archetypes 
-DarchetypeArtifactId=camel-archetype-spring-boot
13
DEMO
14
Exchange
Exchange ID
Message Exchange Pattern
Exception
Properties
In Message
Out Message
15
Message
ID
Header
Attachement
Fault Flag
Body
16
Processor
@Component
public class UpperCaseProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
Message inMessage = exchange.getIn();
String stringMessage = inMessage.getBody(String.class);
exchange.getOut().setBody(stringMessage.toUpperCase());
}
}
17
Processor
<beans ...>
<routeContext id="cssbContext" xmlns="http://camel.apache.org/schema/spring">
<route id="clientServiceAToClientServiceB">
<!-- receive Message Rabbit MQ -->
<from uri="rabbitmq:{{serviceAqueue}}"/>
<!-- Transform -->
<process ref="upperCaseProcessor"/>
<to uri="rabbitmq:{{other}}"/>
</route>
....
</ routeContext>
...
</ beans >
18
Bean
@Component
public class UpperCaseService {
public void toUpperCase(Exchange exchange) throws Exception {
Message inMessage = exchange.getIn();
String stringMessage = inMessage.getBody(String.class);
exchange.getOut().setBody(stringMessage.toUpperCase());
}
}
@Override
public void configure() {
from("timer:hello?period={{timer.period}}").routeId("hello")
.setBody().simple("hello world")
.bean(UpperCaseService.class)
.to("stream:out");
}
19
Component
Enterprise
• File
SQL/JPA
MongoDB
KAFKA
RabbitMQ
HDFS
JBPM
LDAP
SAAS
• Facebook
Twitter
LinkedIn
SalesForce
SAP
GoogleDrive
GitHub
CLOUD
• AWS
Google
Azure
IoT
• MQTT
PubNub
CoAP
Ops
• •K8s
•Zipkins
•Docker
•Openshift
•…
Format
• AVRO
CSV
Base64
JSON
JAXB
Protobuf
XML
20
21
22
Content Base Router
from(newOrder)
.choice()
.when(isWidget).to(widget)
.otherwise().to(gadget)
.end();
23
Content Base Router
Endpoint newOrder = endpoint("activemq:queue:newOrder");
Predicate isWidget = xpath("/order/product = 'widget'");
Endpoint widget = endpoint("activemq:queue:widget");
Endpoint gadget = endpoint("activemq:queue:gadget");
from(newOrder)
.choice()
.when(isWidget).to(widget)
.otherwise().to(gadget)
.end();
24
Publish/subscribe
Enpoint
• JMS
• Amzon SNS/SQS
• Amqp
• Mqtt
• Multicast
• Redis
• Hazelcast
• Xmpp
• SEDA
• Google -PubSub
• ...
25
Recipient list
<route id="notifyRoute">
<from uri="seda:notify"/>
<recipientList>
<simple>http4://${property.AppUrlNotif}</simple>
</recipientList>
[...]
</route>
from("direct:a")
.recipientList(
header("myHeader", "; "))
.parallelProcessing();
26
Splitter
from("file:inbox")
.split().tokenize("n").streaming()
.to("activemq:queue:order");
<route>
<from uri="file:inbox"/>
<split streaming="true">
<tokenize token="n"/>
<to uri="activemq:queue:order"/>
</split>
</route>
27
Monitoring
28
History
File transfert
Shared
database
RPC
EAI Message
Broker Corba
SOA, ESB
Microservices
29
MICROSERVICES
30
MS-1 MS-3MS-2
Gw
Service registry
Config server
Service discovery
Configuration
Securité
Logging
Metriques
Tracing
Fault Tolerance
Scaling
Gateway
31
Tracing server
With Camel
32
MS-1 MS-3MS-2
Gw
Service registry
Config server
Service call EIP
Tracing server
Circuit breaker
33
34
Service
KO
Client
35
Service
KO
Client
Client
Client
36
Service
KO
Client
Circuit
breaker
Life Cycle
37
https://doc.akka.io/docs/akka/2.5/common/circuitbreaker.html
Camel
38
from("timer:trigger?period=1s")
.hystrix()
.to("http://localhost:9090/service1")
// onFallback() immediate response
// use onFallbackViaNetwork() other response
.onFallbackViaNetwork()
.to("direct:inform-service")
.end();
Transaction
39
car
hotel
Flight
Travel
service
Rent
Book
Book
40
car
hotel
Flight
Travel
service
Rent
Book
Book TX
41
car
hotel
Flight
Travel
service
Rent
Book
Book
42
43
2 phase commit
car
hotel
Flight
Travel
service
Prepare
commit
44
Prepare
commit
Prepare
commit
45
SAGA
A Long lived transactions (LLTs) is a saga if it can be written as a
sequence of transactions that can be interleaved with other
transactions.
The database management system guarantees that either all the
transactions in a saga are successfully completed or compensating
transactions are run to amend a partial execution
we only discuss sagas in a centralized system, although clearly they
can be implemented in a distributed database system.
46
SAGA Execution Coordinator
car
hotel
Flight
Travel
service
SEC
47
SAGA Execution Coordinator
car
hotel
Flight
Travel
service
SEC
48
SAGA with Camel
from("direct:buy")
.saga() //start saga
.to("direct:rentCar")
.to("direct:bookHotel")
.to("direct:bookFlight");
car
hotel
Flight
49
SAGA with Camel
from("direct:buy")
.saga() //start saga
.to("direct:rentCar")
.to("direct:bookHotel")
.to("direct:bookFlight");
car
hotel
Flight
from("direct:rentCar")
.saga()
.propagation(SagaPropagation.MANDATORY)
.compensation("direct:cancelRentCar")
.bean(rentCarService, "rentCar")
.log("Car reserved ${header.vehicle.icense_plate}");
50
SAGA with Camel
from("direct:buy")
.saga() //start saga
.to("direct:rentCar")
.to("direct:bookHotel")
.to("direct:bookFlight");
car
hotel
Flight
from("direct:rentCar")
.saga()
.propagation(SagaPropagation.MANDATORY)
.compensation("direct:cancelRentCar")
.bean(rentCarService, "rentCar")
.log("Car reserved ${header.vehicle.icense_plate}");
// action
from("direct:cancelRentCar")
.saga()
.bean(rentCarService, "cancelRentCar")
.log("${header.vehicle.icense_plate}");
51
Conclusions
ESB is dead, long live ESB
Apache Camel Rock !
Connect everything
Microservices
52
53
?
Refs
• GOTO 2015 • Applying the Saga Pattern • Caitie McCaffrey
• https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
• https://www.nicolaferraro.me/2018/04/25/saga-pattern-in-apache-
camel/
• https://github.com/apache/camel/tree/master/camel-
core/src/main/docs/eips
• https://fr.slideshare.net/davsclaus/getting-started-with-apache-camel
•
54

Toulouse Java User Group