Using Enterprise Integration Patterns as Your Camel Jockey

4,236 views
4,055 views

Published on

Using Enterprise Integration Patterns as Your Camel Jockey

  1. 1. Using Enterprise Integration Patterns as Your Camel Jockey Bruce Snyder bsnyder@apache.org IASA Denver September 2009 1
  2. 2. Integration is everywhere! 2
  3. 3. Just Because You Can, Doesn’t Mean You Should 3
  4. 4. And Then There’s the Llama Car 4
  5. 5. Options For Integration 1 2 3 5
  6. 6. Option One - DIY Do It Yourself 6
  7. 7. Option Two - Buy It Buy It 7
  8. 8. Option Three - Adopt It Adopt It 8
  9. 9. What Are Design Patterns? A design pattern is a formal way of documenting a solution to a design problem in a particular field of expertise. (Wikipedia) 9
  10. 10. Enterprise Integration Patterns Got EIP?
  11. 11. Pattern Overview 11
  12. 12. Visualizing EIPs :: Stencils exist for Visio and OmniGraffle :: http://www.eaipatterns.com/downloads.html 12
  13. 13. What is Apache Camel? A framework for simplifying integration through the use of the Enterprise Integration Patterns for message mediation, processing, http://camel.apache.org/ routing and transformation 13
  14. 14. Apache Camel is Focused on EIP => http://camel.apache.org/ http://eaipatterns.com/ 14
  15. 15. History of Apache Camel 15
  16. 16. Message Routing from("A").to("B"); 16
  17. 17. Simple Routing from("file:///tmp/myFile.txt"). to("jms:TEST.Q"); 17
  18. 18. Slightly More Complex Routing from("file:///tmp/myFile.txt"). to("bean:MyBean?method=handleMessage"). to("jms:TEST.Q"); 18
  19. 19. Multicast Routing from("file:///tmp/myFile.txt"). choice().when(). method("MyBean", "matches"). to("Q"). end(). multicast("B", "C", "D"); 19
  20. 20. Pipeline Routing from("file:///tmp/myFile.txt"). choice().when(). method("MyBean", "matches"). to("Q"). end(). pipeline("B", "C", "D"); 20
  21. 21. Camel Components :: 70+ components supported 21
  22. 22. Pattern Examples 22
  23. 23. Patterns Again 23
  24. 24. Content Based Router RouteBuilder builder = new RouteBuilder() { public void configure() { from("activemq:NewOrders") .choice() .when(header("order-type").isEqualTo("widget")) .to("activemq:Orders.Widgets") .when(header("order-type").isEqualTo("gadget")) .to("activemq:Orders.Gadgets") .otherwise() .to("file:errors"); } }; Java DSL 24
  25. 25. Content Based Router <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="activemq:NewOrders"/> <choice> <when> <xpath>/order/product = 'widget'</xpath> <to uri="activemq:Orders.Widgets"/> </when> <when> <xpath>/order/product = 'gadget'</xpath> <to uri="activemq:Orders.Gadgets"/> </when> <otherwise> <to uri="activemq:Orders.Bad"/> </otherwise> </choice> </route> </camelContext> Spring DSL 25
  26. 26. Message Filter public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:topic:Orders) .filter().xpath("/order/product = ʻwidgetʼ") .to("ftp://bsnyder@host:2223/widgets/orders"); } } Java DSL 26
  27. 27. Message Filter <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="activemq:topic:Orders"/> <filter> <xpath>/order/product = ʻwidgetʼ</xpath> <to uri="ftp://bsnyder@host:2223/widgets/orders"/> </filter> </route> </camelContext> Spring DSL 27
  28. 28. Splitter public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file:///orders") .splitter(body(String.class).tokenize("n")) .to("activemq:Order.Items"); } } Java DSL 28
  29. 29. Splitter <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file:///orders" /> <split> <tokenize token="n" /> <to uri="activemq:Order.Items" /> </split> </route> </camelContext> Spring DSL 29
  30. 30. Aggregator public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:STOCKS") .aggregator(header("symbol")) .batchSize(10) .to("activemq:MY.STOCKS"); } } Java DSL 30
  31. 31. Aggregator <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file:///orders" /> <aggregate> <correlationExpression> <simple>header.symbol</simple> </correlationExpression> <batchSize>10</batchSize> <to uri="activemq:MY.STOCKS" /> </aggregate> </route> </camelContext> Spring DSL 31
  32. 32. Throttler public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”) .throttler(3).timePeriodMillis(30000) .to("seda:b"); } } Java DSL 32
  33. 33. Delayer public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”) .delayer(header("JMSTimestamp", 3000) .to("seda:b"); } } Java DSL 33
  34. 34. Load Balancer public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file:/path/to/file") .loadBalance().roundRobin() .to("file:///one", "activemq:MY.Q", "http://host1:8181/fooApp"); } } Policy Description Round Robin Balance the exchange load across the available endpoints Random Randomly choose an endpoint to send the exchange Sticky Sticky load balancing of exchanges using an expression Topic Send exchange to all endpoints (JMS topic semantics) Java DSL 34
  35. 35. Multicast public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a") .multicast() .to("direct:x", "mock:y", "file:///tmp/bar?fileName=test.txt"); } } Java DSL 35
  36. 36. More Patterns 36
  37. 37. Wire Tap public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a") .to("log:com.mycompany.messages?level=info") .to("mock:foo"); } } Java DSL 37
  38. 38. Content Enricher public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:My.Queue") .to("velocity:com/acme/MyResponse.vm") .to("activemq:Another.Queue"); } } Java DSL 38
  39. 39. More Content Enricher public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:My.Queue") .beanRef("myPojo", “methodName”) .to("activemq:Another.Queue"); } } Java DSL 39
  40. 40. Content Filter public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:start").process(new Processor() { public void process(Exchange exchange) { Message in = exchange.getIn(); in.setBody(in.getBody(String.class) + " World!"); } }).to("mock:result"); } } Java DSL 40
  41. 41. Combine Patterns public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”). resequencer(header("JMSGroupSeq")). delayer(3000). to("mock:x"); } } Java DSL 41
  42. 42. Error Handling in Camel :: Global Error Handler: RouteBuilder builder = new RouteBuilder() {     public void configure() {         errorHandler(deadLetterChannel("file:errors"));         from("bean:foo").to("seda:b");   } }; :: Local Error Handler: RouteBuilder builder = new RouteBuilder() {     public void configure() {       from("seda:a").         errorHandler(loggingErrorHandler("FOO.BAR")).         to("seda:b");       from("seda:b").to("seda:c");   } Java DSL }; 42
  43. 43. Exception Policies in Camel RouteBuilder builder = new RouteBuilder() {     public void configure() {         exception(IOException.class)           .initialRedeliveryDelay(5000L)           .maximumRedeliveries(3)           .maximumRedeliveryDelay(30000L)           .backOffMultiplier(1.0)           .useExponentialBackOff()           .setHeader(MESSAGE_INFO, constant("Damned IOException!"))           .to("activemq:errors");         from("seda:a").to("seda:b");    } };  Java DSL 43
  44. 44. Make Context Discover Beans package com.mycompany.beans; public class MyBean { public void someMethod(String name) { ... } } <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <package>com.mycompany.beans</package> </camelContext> 44
  45. 45. Bean as a Message Translator public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:Incoming”). beanRef("myBean"). to("activemq:Outgoing"); } } Java DSL 45
  46. 46. Bean as a Message Translator *With Method Name public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:Incoming”). beanRef("myBean", "someMethod"). to("activemq:Outgoing"); } } Java DSL 46
  47. 47. Binding Beans to Camel Endpoints public class Foo { @MessageDriven(uri=”activemq:cheese”) public void onCheese(String name) { ... } } Java DSL 47
  48. 48. Binding Method Arguments public class Foo { public void onCheese( @XPath(“/foo/bar/”) String name, @Header(“JMSCorrelationID”) String id) { ... } } Java DSL 48
  49. 49. Injecting Endpoints Into Beans public class Foo { @EndpointInject(uri= “activemq:foo.bar”) ProducerTemplate producer; public void doSomething() { if (whatever) { producer.sendBody(“<hello>world</hello>”); } } } Java DSL 49
  50. 50. Type Convertors public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:start").process(new Processor() { public void process(Exchange exchange) { Message in = exchange.getIn(); in.setBody(in.getBody(String.class) + " World!"); } }).to("mock:result"); } } Support for the following types: • File • String • byte[] and ByteBuffer • InputStream and OutputStream • Reader and Writer • Document and Source 50
  51. 51. Type Conversion @Converter public class IOConverter { @Converter public static InputStream toInputStream(File file) throws FileNotFoundException { return new BufferedInputStream( new FileInputStream(file)); } } 51
  52. 52. Business Activity Monitoring (BAM) public class MyActivities extends ProcessBuilder { public void configure() throws Exception { // lets define some activities, correlating on an // XPath query of the message body ActivityBuilder purchaseOrder = activity("activemq:PurchaseOrders") .correlate(xpath("/purchaseOrder/@id").stringResult()); ActivityBuilder invoice = activity("activemq:Invoices") .correlate(xpath("/invoice/@purchaseOrderId").stringResult()); // now lets add some BAM rules invoice.starts().after(purchaseOrder.completes()) .expectWithin(seconds(1)) .errorIfOver(seconds(2)).to("activemq:FailedProcesses"); } } 52
  53. 53. The Camel Truck! 53
  54. 54. Ride the Camel! http://camel.apache.org/ bsnyder@apache.org http://twitter.com/brucesnyder 54

×