Containers: from development to production at DevNation 2015
Cooking with Apache Camel: Tips and Tricks - DevNation 2014
-
Upload
scott-cranton -
Category
Software
-
view
668 -
download
3
description
Transcript of Cooking with Apache Camel: Tips and Tricks - DevNation 2014
![Page 1: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/1.jpg)
![Page 2: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/2.jpg)
Get Cooking with Apache Camel
Cookbook of Tips and Tricks
Scott Cranton
![Page 3: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/3.jpg)
@scottcranton • Red Hat Middleware (technical) sales • Over 5 years working with Camel
– Joined FuseSource Feb, 2009 • https://github.com/FuseByExample • https://github.com/CamelCookbook
![Page 4: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/4.jpg)
Apache Camel Developer’s Cookbook • 100+ Recipes • 424 pages • Published Dec 2013 • Camel 2.12.2 • https://github.com/
CamelCookbook
![Page 5: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/5.jpg)
Why a Camel Cookbook? • Help beginner to intermediate users get
productive by example with follow on references • Break common Camel tasks into Recipes • Each recipe contains:
• Introduction • How to do it (task oriented) • How it works • There’s more
![Page 6: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/6.jpg)
How Do I Control Route Startup Order? • Introduction
– Sometimes order matters, and routes need to start and stop in a defined order • How to do it
– Set route startupOrder attribute – XML DSL: <route startupOrder="20" routeId="myRoute">...</route> – Java DSL: from("direct:in").startupOrder(20).routeId("myRoute")...;
• How it works – Routes started in ascending order, and stopped in descending order
• http://camel.apache.org/configuring-route-startup-ordering-and-autostartup.html
• There’s more – You can programmatically startup and shutdown routes in response to events
• exchange.getContext().startRoute("myRoute");
![Page 7: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/7.jpg)
Camel Cookbook Tasting Menu
• Route Design • Routing messages (EIP) • Transactions • Unit Testing • Monitoring • Calling Camel Routes
![Page 8: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/8.jpg)
Interconnecting Routes Camel supports breaking routes up into re-usable sub-routes, and synchronously or asynchronously calling those sub-routes.
![Page 9: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/9.jpg)
Interconnecting Routes
Within CamelContext
Within JVM
Synchronous direct: direct-vm:
Asynchronous seda: vm:
![Page 10: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/10.jpg)
Interconnecting Routes CamelContext-1
from("activemq:queue:one").to("direct:one"); from("direct:one").to("direct-vm:two");
CamelContext-2
from("direct-vm:two").log("Direct Excitement!");
– Run on same thread as caller
– direct-vm within JVM, including other OSGi Bundles
Direct and Direct-VM
![Page 11: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/11.jpg)
Interconnecting Routes CamelContext-1
from("activemq:queue:one").to("seda:one"); from("seda:one").to("vm:two");
CamelContext-2
from("vm:two").log("Async Excitement!");
– Run on different thread from caller – concurrentConsumers=1 controls thread count
– vm within JVM, including other OSGi Bundles
SEDA and VM
![Page 12: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/12.jpg)
Interconnecting Routes from("activemq:queue:one").to("seda:one"); from("seda:one?multipleConsumers=true").log("here"); from("seda:one?multipleConsumers=true").log("and there");
– Publish / Subscribe like capability – Each route gets its own copy of the Exchange – Multicast EIP better for known set of routes
– https://issues.apache.org/jira/browse/CAMEL-6451
SEDA and VM
![Page 13: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/13.jpg)
Wire Tap To create an asynchronous path from your main route. Useful for audit and logging operations.
![Page 14: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/14.jpg)
Wire Tap from("direct:start") .wiretap("direct:tap") .to("direct:other"); from("direct:tap") .log("something interesting happened"); from("direct:other") .wiretap("activemq:queue:tap") .to("direct:other");
– Runs on different thread / thread pool – Default Thread Pool - initial 10; grows to 20
![Page 15: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/15.jpg)
Wire Tap from("direct:start") .wiretap("direct:tap-mod") .delay(constant(1000)) .log("Oops! Body changed unexpectedly"); from("direct:tap-mod") .bean(BodyModifier.class, "changeIt"); // Modifies message body
– Message, Header, and Properties passed by reference
![Page 16: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/16.jpg)
Wire Tap from("direct:start") .wiretap("direct:tap-mod").onPrepare(new DeepCloningProcessor()) .delay(constant(1000)) .log("Yay! Body not changed."); from("direct:tap-mod") .bean(BodyModifier.class, "changeIt");
– onPrepare calls Processor before wiretap endpoint
![Page 17: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/17.jpg)
Throttler For when you need to limit the number of concurrent calls made a sequence of actions. For example, limit calls to a back-end ERP.
![Page 18: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/18.jpg)
Throttler from("direct:start") .throttle(constant(5)) // max per period expression .to("direct:throttled") // step(s) being throttled .end() // end of step(s) .to("direct:post-throttle");
– Example limits to 5 messages per 1,000 ms (default)
– Should use end() to delimit steps being throttled
![Page 19: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/19.jpg)
Throttler from("direct:start") .throttle(header("message-limit")) // expression .to("direct:throttled") .end() .to("direct:post-throttle");
– Example throttles to value in header "message-limit"
– Will use last value if Expression evaluates to null
![Page 20: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/20.jpg)
Throttler from("direct:start") .throttle(constant(5)).timePeriodMillis(2000) // value in milliseconds .to("direct:throttled") .end() .to("direct:post-throttle");
– Example limits to 5 messages per 2,000 ms
![Page 21: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/21.jpg)
Throttler from("direct:start") .throttle(constant(5)).asyncDelayed() .to("direct:throttled") .end() .to("direct:post-throttle");
– asyncDelayed() causes throttled requests to be queued for future processing, releasing calling thread (non-blocking)
![Page 22: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/22.jpg)
Transactions For local transaction control within your routes to commit data or rollback on error. Includes fine grained support for scoping of transactions.
![Page 23: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/23.jpg)
Transactions Setup Transaction manager reference (requires Spring). <bean id="sql" class="org.apache.camel.component.sql.SqlComponent"> <property name="dataSource" ref="auditDataSource"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="auditDataSource"/> </bean> <bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="transactionManager"/> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> </bean>
![Page 24: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/24.jpg)
Transactions Mark a route as transacted. Will commit local transaction at route completion or automatically rollback if an error is thrown and not handled. from("direct:transacted") .transacted() .setHeader("message", body()) .to("sql:insert into audit_log (message) values(:#message)") .to("mock:out");
![Page 25: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/25.jpg)
Transactions Can also explicitly scope transactions. from("direct:policies") .setHeader("message", body()) .policy("PROPAGATION_REQUIRED") // Transaction 1 .to("sql:insert into audit_log (message) values (:#message)") .to("mock:out1") .end() .policy("PROPAGATION_REQUIRED") // Transaction 2 .to("sql:insert into messages (message) values (:#message)") .to("mock:out2") .end();
![Page 26: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/26.jpg)
XSLT Camel supports many different ways to transform data, for example using XSLT to transform XML.
![Page 27: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/27.jpg)
XSLT from("direct:start") .to("xslt:books.xslt");
– Example uses books.xslt on classpath: (default) – Also supports file: and http:
![Page 28: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/28.jpg)
XSLT from("direct:start") .to("xslt:books.xslt?output=DOM");
– output controls output data type – Supports: string (default), bytes, DOM, and file
– output=file writes directly to disk; path must exist – File name controlled by header "CamelXsltFileName"
![Page 29: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/29.jpg)
XSLT from("direct:start").setHeader("myParamValue", constant("29.99")).to("xslt:books-with-param.xslt"); <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="myParamValue"/> <xsl:template match="/"> <books> <xsl:attribute name="value"> <xsl:value-of select="$myParamValue"/> </xsl:attribute> <xsl:apply-templates select="/bookstore/book/title[../price>$myParamValue]"> <xsl:sort select="."/> </xsl:apply-templates> </books> </xsl:template> </xsl:stylesheet>
![Page 30: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/30.jpg)
Mock Endpoints Camel provides some very powerful Unit Testing capabilities. Its MockEndpoint class supports complex expressions to validate your routes.
![Page 31: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/31.jpg)
Mock Endpoints from("direct:start") .filter().simple("${body} contains 'Camel'") .to("mock:camel") .end(); public class ContentBasedRouterTest extends CamelTestSupport { @Test public void testCamel() throws Exception { getMockEndpoint("mock:camel").expectedMessageCount(1); template.sendBody("direct:start", "Camel Rocks!"); assertMockEndpointsSatisfied(); } }
![Page 32: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/32.jpg)
Mock Endpoints MockEndpoint mockCamel = getMockEndpoint("mock:camel"); mockCamel.expectedMessageCount(2); mockCamel.message(0).body().isEqualTo("Camel Rocks"); mockCamel.message(0).header("verified").isEqualTo(true); mockCamel.message(0).arrives().noLaterThan(50).millis().beforeNext(); mockCamel.allMessages().simple("${header.verified} == true"); template.sendBody("direct:start", "Camel Rocks"); template.sendBody("direct:start", "Loving the Camel"); mockCamel.assertIsSatisfied(); Exchange exchange0 = mockCamel.assertExchangeReceived(0); Exchange exchange1 = mockCamel.assertExchangeReceived(1); assertEquals(exchange0.getIn().getHeader("verified"), exchange1.getIn().getHeader("verified"));
![Page 33: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/33.jpg)
Mock Endpoints from("direct:start").inOut("mock:replying").to("mock:out"); getMockEndpoint("mock:replying") .returnReplyBody(SimpleBuilder.simple("Hello ${body}")); getMockEndpoint("mock:out").expectedBodiesReceived("Hello Camel"); template.sendBody("direct:start", "Camel"); assertMockEndpointsSatisfied();
Mock Responding
![Page 34: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/34.jpg)
Mock Endpoints from("direct:start").to("activemq:out"); public class ContentBasedRouterTest extends CamelTestSupport { @Override public String isMockEndpoints() { return "activemq:out"; } @Test public void testCamel() throws Exception { getMockEndpoint("mock:activemq:out").expectedMessageCount(1); template.sendBody("direct:start", "Camel Rocks!"); assertMockEndpointsSatisfied(); } }
Auto Mocking
![Page 35: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/35.jpg)
Naming your Routes in JMX Camel by default exposes your routes through JMX. You should provide explicit names for your routes to make it easier for yourself and others to monitor.
![Page 36: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/36.jpg)
Naming your Routes in JMX from("direct:start") .routeId("first-route") .log("${body}") .to("mock:result"); JMX Name org.apache.camel:context=localhost/contextName,type=routes,name=first-route
• By default, Camel will name "route-N" • It will use the route id if provided as part of the JMX name
![Page 37: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/37.jpg)
![Page 38: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/38.jpg)
POJO Producing Camel’s ProducerTemplate is seen mostly in Unit Tests, and it provides a great way to interact with Camel from your existing code.
![Page 39: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/39.jpg)
POJO Producing public class ProducePojo { @Produce private ProducerTemplate template; public String sayHello(String name) { return template.requestBody("activemq:sayhello", name, String.class); } }
– Send (InOnly) or Request (InOut) to Endpoint or Route
![Page 40: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/40.jpg)
POJO Producing public interface ProxyPojo { String sayHello(String name); } public class ProxyProduce { @Produce(uri = "activemq:queue:sayhello") ProxyPojo myProxy; public String doSomething(String name) { return myProxy.sayHello(name); } }
– Proxy template Java interface to make use clearer
![Page 41: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/41.jpg)
Parameter Binding Camel was designed to work well with calling POJOs. Parameter Binding allows you to, within the route, map the message to the method parameters. This makes it even easier to call POJOs from Camel.
![Page 42: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/42.jpg)
Parameter Binding public String myMethod( @Header("JMSCorrelationID") String id, @Body String message) { ... } public String myOtherMethod( @XPath("/myDate/people/@id") String id, @Body String message) { ... }
![Page 43: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/43.jpg)
Parameter Binding public class MyBean { public String sayHello(String name, boolean fanboy) { return (fanboy) ? ("Hello iPhone") : ("Hello " + name); } } from("direct:fanboy").bean(MyBean.class, "sayHello(${body}, true)"); from("direct:undecided") .bean(MyBean.class, "sayHello(${body}, ${header.fanboy})");
– Send (InOnly) or Request (InOut) to Endpoint or Route
![Page 44: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/44.jpg)
Questions?
![Page 45: Cooking with Apache Camel: Tips and Tricks - DevNation 2014](https://reader030.fdocuments.net/reader030/viewer/2022020115/548c4e96b4795927058b457a/html5/thumbnails/45.jpg)
Apache Camel Developer’s Cookbook • 100+ Recipes • 424 pages • Published Dec 2013 • Camel 2.12.2 • https://github.com/
CamelCookbook