Taking Apache Camel For A Ride

3,852 views
3,720 views

Published on

Presentation from ApacheCon US 2008

Published in: Technology

Taking Apache Camel For A Ride

  1. 1. Taking Apache Camel For A Ride Bruce Snyder bsnyder@apache.org 7 Nov 2008 New Orleans, Louisiana
  2. 2. Protocol Integration is Common
  3. 3. Data Format Integration is Common
  4. 4. Integration is Messy!
  5. 5. SOA = Spaghetti Oriented Architecture
  6. 6. Options For Integration 1 2 3
  7. 7. Too Many Choices!
  8. 8. The Easiest Solution - Apache Camel http://activemq.apache.org/camel/
  9. 9. What is Apache Camel?
  10. 10. Enterprise Integration Patterns http://enterpriseintegrationpatterns.com/
  11. 11. Message Routing
  12. 12. Patterns
  13. 13. History of Apache Camel
  14. 14. Camel Components http://activemq.apache.org/camel/components.html
  15. 15. Camel Components
  16. 16. Simple Routing
  17. 17. More Simple Routing
  18. 18. Pipeline Routing
  19. 19. Multicast Routing
  20. 20. Multicast-to-Many Pipeline Routes
  21. 21. Language Support For Message Processing • BeanShell • JSP EL • Javascript • OGNL • Groovy • SQL • Python • XPath • PHP • XQuery • Ruby
  22. 22. Getting Started - The Camel Context CamelContext context = new DefaultCamelContext(); context.addRoutes(new MyRouteBuilder()); context.start(); <camelContext xmlns=quot;http://activemq.apache.org/camel/schema/springquot;> <package>com.acme.quotes</package> </camelContext>
  23. 23. Pattern Examples
  24. 24. Patterns
  25. 25. Content Based Router RouteBuilder builder = new RouteBuilder() { public void configure() { from(quot;seda:aquot;).choice().when(header(quot;fooquot;) .isEqualTo(quot;barquot;)).to(quot;seda:bquot;) .when(header(quot;fooquot;).isEqualTo(quot;cheesequot;)) .to(quot;seda:cquot;).otherwise().to(quot;seda:dquot;); } };
  26. 26. Content Based Router <camelContext xmlns=quot;http://activemq.apache.org/camel/schema/springquot;> <route> <from uri=quot;activemq:NewOrdersquot;/> <choice> <when> <xpath>/order/product = 'widget'</xpath> <to uri=quot;activemq:Orders.Widgetsquot;/> </when> <when> <xpath>/order/product = 'gadget'</xpath> <to uri=quot;activemq:Orders.Gadgetsquot;/> </when> <otherwise> <to uri=quot;activemq:Orders.Badquot;/> </otherwise> </choice> </route> </camelContext>
  27. 27. Message Filter public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:topic:Quotes). filter().xpath(quot;/quote/product = ‘widget’quot;). to(quot;mqseries:WidgetQuotesquot;); } }
  28. 28. Message Filter <camelContext xmlns=quot;http://activemq.apache.org/camel/schema/springquot;> <route> <from uri=quot;activemq:topic:Quotesquot;/> <filter> <xpath>/quote/product = ‘widget’</xpath> <to uri=quot;mqseries:WidgetQuotesquot;/> </filter> </route> </camelContext>
  29. 29. Splitter public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;file://ordersquot;). splitter(body().tokenize(quot;nquot;)). to(quot;activemq:Order.Itemsquot;); } }
  30. 30. Splitter Using XQuery public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;file://ordersquot;). splitter().xquery(quot;/order/itemsquot;). to(quot;activemq:Order.Itemsquot;); } }
  31. 31. Aggregator public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:Inventory.Itemsquot;). aggregator(header(quot;symbolquot;).isEqualTo(quot;IBMquot;). to(quot;activemq:Inventory.Orderquot;); } }
  32. 32. Message Translator public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;file://incoming”). to(quot;xslt:com/acme/mytransform.xslquot;). to(quot;http://outgoing.com/fooquot;); } }
  33. 33. Resequencer public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:a”). resequencer(header(quot;customerRankquot;)). to(quot;seda:bquot;); } }
  34. 34. Routing Slip public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:a”).routingSlip(); } }
  35. 35. Throttler public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;seda:a”). throttler(3).timePeriodMillis(30000). to(quot;seda:bquot;); } }
  36. 36. Delayer public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;seda:a”). delayer(header(quot;JMSTimestampquot;, 3000). to(quot;seda:bquot;); } }
  37. 37. Load Balancer public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;file:/path/to/filequot;). loadBalance().roundRobin(). to(quot;seda:aquot;, quot;seda:bquot;, quot;seda:cquot;); } } 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 (like a JMS topic)
  38. 38. Multicast public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:aquot;). multicast(). to(quot;direct:x?x=y&amp;1=2quot;, quot;direct:yquot;, quot;direct:zquot;); } }
  39. 39. Demo
  40. 40. More Patterns
  41. 41. Wire Tap public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:aquot;). to(quot;log:com.mycompany.messages?level=infoquot;). to(quot;mock:fooquot;); } }
  42. 42. Content Enricher public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:My.Queuequot;). to(quot;velocity:com/acme/MyResponse.vmquot;). to(quot;activemq:Another.Queuequot;); } }
  43. 43. More Content Enricher public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:My.Queuequot;). beanRef(quot;myBeanNamequot;, quot;myMethodNamequot;). to(quot;activemq:Another.Queuequot;); } }
  44. 44. Content Filter public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:startquot;).process(new Processor() { public void process(Exchange exchange) { Message in = exchange.getIn(); in.setBody(in.getBody(String.class) + quot; World!quot;); } }).to(quot;mock:resultquot;); } }
  45. 45. Combine Patterns public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;seda:a”). resequencer(header(quot;JMSGroupSeqquot;)). delayer(3000). to(quot;mock:xquot;); } }
  46. 46. Configure Error Handling Global Error Handler: RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel(quot;file:errorsquot;)); from(quot;bean:fooquot;).to(quot;seda:bquot;); } };
  47. 47. Configure Error Handling Local Error Handler: RouteBuilder builder = new RouteBuilder() { public void configure() { from(quot;seda:aquot;). errorHandler(loggingErrorHandler(quot;FOO.BARquot;)). to(quot;seda:bquot;); from(quot;seda:bquot;).to(quot;seda:cquot;); } };
  48. 48. Configure Exception Policies RouteBuilder builder = new RouteBuilder() { public void configure() { exception(IOException.class) .initialRedeliveryDelay(5000L) .maximumRedeliveries(3) .maximumRedeliveryDelay(30000L) .backOffMultiplier(1.0) .useExponentialBackOff() .setHeader(MESSAGE_INFO, constant(quot;Damned IOException!quot;)) .to(quot;activemq:errorsquot;); from(quot;seda:aquot;).to(quot;seda:bquot;); } };
  49. 49. Beans
  50. 50. Make Context Discover Beans package com.mycompany.beans; public class MyBean { public void someMethod(String name) { ... } } <camelContext xmlns=quot;http://activemq.apache.org/camel/schema/springquot;> <package>com.mycompany.beans</package> </camelContext>
  51. 51. Bean as a Message Translator public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:Incoming”). beanRef(quot;myBeanquot;). to(quot;activemq:Outgoingquot;); } }
  52. 52. Bean as a Message Translator *With Method Name public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:Incoming”). beanRef(quot;myBeanquot;, quot;someMethodquot;). to(quot;activemq:Outgoingquot;); } }
  53. 53. Binding Beans to Camel Endpoints public class Foo { @MessageDriven(uri=quot;activemq:cheesequot;) public void onCheese(String name) { ... } }
  54. 54. Binding Method Arguments public class Foo { public void onCheese( @XPath(quot;/foo/barquot;) String name, @Header(quot;JMSCorrelationIDquot;) String id) { ... } }
  55. 55. Injecting Endpoints Into Beans public class Foo { @EndpointInject(uri=quot;activemq:foo.barquot;) ProducerTemplate producer; public void doSomething() { if (whatever) { producer.sendBody(quot;<hello>world!</hello>quot;); } } }
  56. 56. Type Conversion
  57. 57. Type Conversion @Converter public class IOConverter { @Converter public static InputStream toInputStream(File file) throws FileNotFoundException { return new BufferedInputStream( new FileInputStream(file)); } }
  58. 58. Type Convertors public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;direct:startquot;).process(new Processor() { public void process(Exchange exchange) { Message in = exchange.getIn(); in.setBody(in.getBody(String.class) + quot; World!quot;); } }).to(quot;mock:resultquot;); } } Support for the following types: • File • String • byte[] and ByteBuffer • InputStream and OutputStream • Reader and Writer • Document and Source
  59. 59. Message Mapper
  60. 60. Message Translator public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;file://incoming”). to(quot;xslt:com/acme/mytransform.xslquot;). to(quot;http://outgoing.com/fooquot;); } }
  61. 61. Another Message Translator public class MyRouteBuilder extends RouteBuilder { public void configure() { from(quot;activemq:FOO.TEST”). transform(body().append(getDynamicText())). to(quot;http://outgoing.com/fooquot;); } }
  62. 62. Business Activity Monitoring (BAM)
  63. 63. 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(quot;activemq:PurchaseOrdersquot;) .correlate(xpath(quot;/purchaseOrder/@idquot;).stringResult()); ActivityBuilder invoice = activity(quot;activemq:Invoicesquot;) .correlate(xpath(quot;/invoice/@purchaseOrderIdquot;).stringResult()); // now lets add some BAM rules invoice.starts().after(purchaseOrder.completes()) .expectWithin(seconds(1)) .errorIfOver(seconds(2)).to(quot;activemq:FailedProcessesquot;); } }
  64. 64. Complex Routing is Easier from(“http://localhost:8080/requests/”). tryBlock(). to(“activemq:queue:requests”). setOutBody(constant(“<ack/>”)). handle(Throwable.class). setFaultBody(constant(“<nack/>”)); from((“activemq:queue:requests?transacted=true”). process(requestTransformer). to(“http://host:8080/Request”). filter(xpath(“//nack”)). process(nackTransformer). to(“jdbc:store”); from(“http://localhost:8080/responses/”). tryBlock(). to(“activemq:queue:responses”). setOutBody(constant(“<ack/>”)). handle(Throwable.class). setFaultBody(constant(“<nack/>”)); from(“activemq:queue:responses?transacted=true”). process(responseTransformer). to(“jdbc:store”); from(“http://localhost:8080/pull/”). to(“jdbc:load”);
  65. 65. Finally, the Camel Truck!
  66. 66. Ride the Camel! http://activemq.apache.org/camel/

×