Date post: | 07-Nov-2014 |
Category: |
Technology |
Upload: | bruce-snyder |
View: | 6,239 times |
Download: | 1 times |
Protocol Integration is Common
Data Format Integration is Common
Integration is Messy!
SOA = Spaghetti Oriented Architecture
Options For Integration
1 2
3
Too Many Choices!
The Easiest Solution - Apache Camel
http://activemq.apache.org/camel/
What is Apache Camel?
Enterprise Integration Patterns
http://enterpriseintegrationpatterns.com/
Message Routing
Patterns
History of Apache Camel
Camel Components
http://activemq.apache.org/camel/components.html
Camel Components
Simple Routing
More Simple Routing
Pipeline Routing
Multicast Routing
Multicast-to-Many Pipeline Routes
Language Support For Message Processing
• BeanShell• Javascript• Groovy• Python• PHP• Ruby
• JSP EL• OGNL• SQL• XPath• XQuery
Getting Started - The Camel Context
<camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <package>com.acme.quotes</package></camelContext>
CamelContext context = new DefaultCamelContext();context.addRoutes(new MyRouteBuilder());context.start();
PatternExamples
Patterns
Content Based Router
RouteBuilder builder = new RouteBuilder() { public void configure() { from("seda:a").choice().when(header("foo") .isEqualTo("bar")).to("seda:b") .when(header("foo").isEqualTo("cheese")) .to("seda:c").otherwise().to("seda:d"); } };
<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>
Content Based Router
Message Filter
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:topic:Quotes). filter().xpath("/quote/product = ‘widget’"). to("mqseries:WidgetQuotes"); }}
Message Filter
<camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="activemq:topic:Quotes"/> <filter> <xpath>/quote/product = ‘widget’</xpath> <to uri="mqseries:WidgetQuotes"/> </filter> </route> </camelContext>
Splitter
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file://orders").
splitter(body().tokenize("\n")). to("activemq:Order.Items"); }}
Splitter Using XQuery
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file://orders").
splitter().xquery("/order/items"). to("activemq:Order.Items"); }}
Aggregator
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:Inventory.Items"). aggregator(header("symbol").isEqualTo("IBM"). to("activemq:Inventory.Order"); }}
Message Translator
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file://incoming”).
to("xslt:com/acme/mytransform.xsl"). to("http://outgoing.com/foo"); }}
Resequencer
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a”).
resequencer(header("customerRank")). to("seda:b"); }}
Routing Slip
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a”).routingSlip();
}}
Throttler
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”).
throttler(3).timePeriodMillis(30000). to("seda:b"); }}
Delayer
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”).
delayer(header("JMSTimestamp", 3000). to("seda:b"); }}
Load Balancerpublic class MyRouteBuilder extends RouteBuilder { public void configure() { from("file:/path/to/file"). loadBalance().roundRobin(). to("seda:a", "seda:b", "seda:c"); }}
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)
Multicast
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a"). multicast(). to("direct:x?x=y&1=2", "direct:y", "direct:z");
}}
Demo
MorePatterns
Wire Tap
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("direct:a"). to("log:com.mycompany.messages?level=info"). to("mock:foo");
}}
Content Enricher
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:My.Queue"). to("velocity:com/acme/MyResponse.vm"). to("activemq:Another.Queue");
}}
More Content Enricher
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:My.Queue"). beanRef("myBeanName", "myMethodName"). to("activemq:Another.Queue");
}}
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"); }}
Combine Patterns
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("seda:a”). resequencer(header("JMSGroupSeq")).
delayer(3000). to("mock:x"); }}
Configure Error Handling
Global Error Handler:
RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("file:errors")); from("bean:foo").to("seda:b"); }};
Configure Error Handling
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"); }};
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("Damned IOException!")) .to("activemq:errors");
from("seda:a").to("seda:b"); }};
Beans
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>
Bean as a Message Translator
public class MyRouteBuilder extends RouteBuilder { public void configure() {
from("activemq:Incoming”). beanRef("myBean"). to("activemq:Outgoing"); }}
Bean as a Message Translator
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:Incoming”). beanRef("myBean", "someMethod"). to("activemq:Outgoing"); }}
*With Method Name
Binding Beans to Camel Endpoints
public class Foo {
@MessageDriven(uri="activemq:cheese") public void onCheese(String name) { ... }}
Binding Method Arguments
public class Foo {
public void onCheese( @XPath("/foo/bar") String name, @Header("JMSCorrelationID") String id) { ... }}
Injecting Endpoints Into Beans
public class Foo { @EndpointInject(uri="activemq:foo.bar") ProducerTemplate producer;
public void doSomething() { if (whatever) { producer.sendBody("<hello>world!</hello>"); } }}
Type Conversion
Type Conversion
@Converterpublic class IOConverter {
@Converter public static InputStream toInputStream(File file) throws FileNotFoundException { return new BufferedInputStream(
new FileInputStream(file)); }}
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
Message Mapper
Message Translator
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("file://incoming”).
to("xslt:com/acme/mytransform.xsl"). to("http://outgoing.com/foo"); }}
Another Message Translator
public class MyRouteBuilder extends RouteBuilder { public void configure() { from("activemq:FOO.TEST”). transform(body().append(getDynamicText())). to("http://outgoing.com/foo"); }}
Business Activity Monitoring (BAM)
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"); }}
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”);
Finally, the Camel Truck!
Ride the Camel!
http://activemq.apache.org/camel/
Ride the Camel!