Scala DSL and camel spring schema

http://camel.apache.org/scala-dsl.html

Just like the Java DSL, the Scala DSL has a RouteBuilder class (org.apache.camel.scala.builder.RouteBuilder) that you can extend to implement your own routes. This example shows two very simple routes:

class MyRouteBuilder extends RouteBuilder {
  "direct:a" --> "mock:a"
  "direct:b" to "mock:b"      
}

If you compare this to the Java DSL, you notice:

  • there is no configure() method to override
  • a route starts directly with a URI instead of from(uri)
  • is just an alias for to

Setting the route ID

To assign the unique ID to the Scala route, insert the routeId method invocation after the "from" part of the DSL.

 "direct:a" routeId "route-b" to "mock:b"

 

DSL supported
The Scala DSL supports every DSL from the Java DSL.

On this page we have examples for a number of the EIPs.
You can check the unit test source code for the Scala Component to find more examples.

Messaging systems

Pipeline

There is a simple syntax available for specifying pipeline, by simple putting to or between the different steps in the pipeline.

"direct:a" --> "mock:a" --> "mock:b"
"direct:c" to "mock:c" to "mock:d"

For more advanced use cases, you can also use a block-based syntax, where every step in the pipeline starts with either to or .

"direct:e" ==> {
  --> ("mock:e")
  --> ("mock:f")
}

"direct:g" ==> {
  to ("mock:g")
  to ("mock:h")
}
Filter

For a message filter, use the when() method with a parameter of type The Exchange ⇒ Boolean. In the example below, we use a Scala convenience method named in to access the 'in' message body; only messages where the 'in' message is <hello/> will arrive at the mock:a endpoint.

"direct:a" when(_.in == "<hello/>") to("mock:a")

Once again, if you need to specify a more advanced route, you can use the more elaborate syntax.

"direct:b" ==> {
  when(_.in == "<hallo/>") {
    --> ("mock:b")
    to ("mock:c")
  } otherwise {
    to ("mock:e")
  }
  to ("mock:d")
}

Messaging channels

Dead letter channel

The dead letter channel can be created with the syntax similar to the one used in Java DSL.

"jms:in" errorHandler(deadLetterChannel("jms:error")) to "jms:out"

You can also use different error handler available for the Java DSL. In particular Scala DSL supports DefaultErrorHandler and LoggingErrorHandler.

// DefaultErrorHandler
"jms:in" errorHandler(defaultErrorHandler) to "jms:out"

// LoggingErrorHandler
"jms:in" errorHandler(loggingErrorHandler.level(LoggingLevel.INFO).logName("com.example.MyLogger")) to "jms:out"

Message routing

Aggregator

The aggregator EIP aggregates messages based on some message correlation criteria. In the Scala DSL, the aggregate method takes a function Exchange ⇒ Any to determine the correlation value for the exchange. In the sample below, message are being aggregated if the first 7 letters in the message body are the same.

"direct:b" ==> {
  aggregate(_.in[String].substring(0,7), new UseLatestAggregationStrategy()).completionSize(100) {
    to ("mock:b")
  }
}
Content based router

Similar to the Filter , the content based router uses when methods with Exchange ⇒ Boolean function literals and an optional otherwise. The function literal can contain plain Scala code as well as any of the supported languages . The example below routes a given message based on the language of the message body.

 "direct:a" ==> {
 to ("mock:polyglot")
 choice {
    when (_.in == "<hello/>") to ("mock:english")
    when (_.in == "<hallo/>") {
      to ("mock:dutch")
      to ("mock:german")
    } 
    otherwise to ("mock:french")
  }
}
Delayer

Unlike a throttler, which only slows down messages if the rate exceeds a treshold, a delayer delays every messages with a fixed amount of time. An example: to delay every message going from seda:a to mock:a with 1 second, you write...

"seda:a" delay(1 seconds) to ("mock:a")

Our second example will delay the entire block (containing mock:c) without doing anything to mock:b

"seda:b" ==> {
  to ("mock:b")
  delay(1 seconds) {
    to ("mock:c")
  }
}
Load balancer

To distribute the message handling load over multiple endpoints, we add a loadbalance to our route definition. You can optionally specify a load balancer strategy, like roundrobin

"direct:a" ==> {
  loadbalance roundrobin {
    to ("mock:a")
    to ("mock:b")
    to ("mock:c")
  }
}
Multicast

Multicast allows you to send a message to multiple endpoints at the same time. In a simple route, you can specify multiple targets in the to or method call:

"direct:a" --> ("mock:a", "mock:b") --> "mock:c"
"direct:d" to ("mock:d", "mock:e") to "mock:f"
Recipient list

You can handle a static recipient list with a multicast or pipeline , but this EIP is usually applied when you want to dynamically determine the name(s) of the next endpoint(s) to route to. Use the recipients() method with a function literal (Exchange => Any) that returns the endpoint name(s). In the example below, the target endpoint name can be found in the String message starting at position 21.

"direct:a" recipients(_.in[String].substring(21))

Because the recipients() method just takes a function literal, you can basically use any kind of valid Scala code to determine the endpoint name. Have a look at the next example which uses pattern matching to figure out where to send the message:

"direct:b" recipients(_.getIn().getBody() match {
  case Toddler(_) => "mock:playgarden"
  case _ => "mock:work"
})

Again, we can also use the same thing in a more block-like syntax. For this example, we use the Scala DSL's support for JXPath to determine the target.

"direct:c" ==> {
  to("mock:c")
  recipients(jxpath("./in/body/destination"))
}
Resequencer

Use the resequence method to add a resequencer to the RouteBuilder. The method takes a function (Exchange ⇒ Unit) that determines the value to resequence on. In this example, we resequence messages based on the 'in' message body.

"direct:a" resequence (_.in) to "mock:a"

The same EIP can also be used with a block-like syntax...

"direct:b" ==> {
  to ("mock:b")
  resequence (_.in) {
    to ("mock:c")
  }
}

... and with configurable batch size. In this last example, messages will be send to mock:e whenever a batch of 5 messages is available.

"direct:d" ==> {
  to ("mock:d")
  resequence(_.in).batch(5) {
    to ("mock:e")
  }
}
Splitter

To handle large message in smaller chunks, you can write a Scala Exchange ⇒ Any* method and add it to your route with the splitter method. As with many other EIPs, we support a short, in-line version as well as a more elaborate block based one.

"direct:a" as(classOf[Document]) split(xpath("/persons/person")) to "mock:a"
"direct:b" ==> {
  as(classOf[Document])
  split(xpath("/persons/person")) {
    to("mock:b")
    to("mock:c")
  }
}

The above examples also show you how other languages like XPath can be within the Scala DSL.

Throttler

The throttler allows you to slow down messages before sending them along. The throttle methods allows you to specify the maximum throughput rate of message:

"seda:a" throttle (3 per (2 seconds)) to ("mock:a")

It can also be used in front of block to throttle messages at that point. In the example below, message are passed on to mock:b in a normal rate (i.e. as fast as possible), but a maximum 3 messages/2 seconds will arrive at the mock:c endpoint.

"seda:b" ==> {
  to ("mock:b")
  throttle (3 per (2 seconds)) {
    to ("mock:c")
  }
}

Message transformation

Content enricher

Using a processor function (Exchange → Unit), you can alter/enrich the message content. This example uses a simple function literal to append " says Hello" to the message content:

"direct:a" process(_.in += " says hello") to ("mock:a")

However, you can also define a separate method/function to handle the transformation and pass that to the process method instead. The example below uses pattern matching to enrich the message content:

val myProcessor = (exchange: Exchange) => {
  exchange.in match {
    case "hello" => exchange.in = "hello from the UK"
    case "hallo" => exchange.in = "hallo vanuit Belgie"
    case "bonjour" => exchange.in = "bonjour de la douce France"
  }
}    

"direct:b" process(myProcessor) to ("mock:b")

Off course, you can also use any other Camel component (e.g. Velocity) to enrich the content and add it to a pipeline

"direct:c" to ("velocity:org/apache/camel/scala/dsl/enricher.vm") to ("mock:c")   
 

Support for other languages inside the Scala DSL routes is delivered through traits. The org.apache.camel.scala.dsl.languages package currently offers traits to support XPath. To use any given language, you can mix-in the trait when creating your RouteBuilder.

You can use any of the supported Camel Languages in the Scala DSL; see below for a couple of examples:

Using XPath

With the XPath trait, you have an additional method available on an Exchange to do XPath queries against the message. Just look at this Splitter example, where the xpath method is used in a Exchange ⇒ Any* function literal

"direct:b" ==> {
  as(classOf[Document])
  split(xpath("/persons/person")) {
    to("mock:b")
    to("mock:c")
  }
}
Using JXPath

With the org.apache.camel.scala.dsl.languages.JXPath trait, you can an additional jxpath method on the Exchange. In the Recipient List example below, JXPath is used for getting the next endpoint's name out of the message body.

"direct:c" ==> {
  to("mock:c")
  recipients(jxpath("./in/body/destination"))
}
 
=================================
 

Routes

Camel supports the definition of routing rules using a Java DSL (domain specific language) which avoids the need for cumbersome XML using a RouteBuilder.

For example a simple route can be created as follows.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a").to("direct:b");
    }
};

As you can see from the above Camel uses URIs to wire endpoints together.

URI String formatting

Available as of Camel 2.0

If you have endpoint URIs that accept options and you want to be able to substitute the value, e.g. build the URI by concat the strings together, then you can use the java.lang.String.format method. But in Camel 2.0 we have added two convenient methods in the Java DSL so you can do fromF and toF that uses String formatting to build the URI.

from("direct:start").toF("file://%s?fileName=%s", path, name);

fromF("file://%s?include=%s", path, pattern).toF("mock:%s", result);

Filters

You can combine simple routes with filters which can be arbitrary Predicate implementations.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a")
            .filter(header("foo").isEqualTo("bar"))
                .to("direct:b");
    }
};

Choices

With a choice you provide a list of predicates and outcomes along with an optional default otherwise clause which is invoked if none of the conditions are met.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a")
            .choice()
                .when(header("foo").isEqualTo("bar"))
                    .to("direct:b")
                .when(header("foo").isEqualTo("cheese"))
                    .to("direct:c")
                .otherwise()
                    .to("direct:d");
    }
};
Using a custom processor

Here is an example of using a custom Processor

myProcessor = new Processor() {
    public void process(Exchange exchange) {
        log.debug("Called with exchange: " + exchange);
    }
};

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a")
            .process(myProcessor);
    }
};

You can mix and match custom processors with filters and choices.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a")
            .filter(header("foo").isEqualTo("bar"))
                .process(myProcessor);
    }
};
Interceptors

Here is an example of adding a few custom InterceptorProcessor objects to a processing pipeline:

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));

        from("direct:a")
            .filter(header("foo").isEqualTo(123))
                .to("direct:b");
    }
};

When you start defining and interceptor stack with intercept(), you must follow up with the subsequent .target() so that the target of the interceptor stack is properly registered.

 
 
 
=======================================================================================
 
Element : camelContext
Content Model : (properties?, propertyPlaceholder?, package*, packageScan?, contextScan?,
 jmxAgent?, (template | consumerTemplate | proxy | export | errorHandler)*, routeBuilder*,
 routeContextRef*, threadPoolProfile*, threadPool*, endpoint*, dataFormats?,
 redeliveryPolicyProfile*, onException*, onCompletion*, intercept*, interceptFrom*,
 interceptSendToEndpoint*, route*)
 
<xs:attribute name="depends-on" type="xs:string" />
  <xs:attribute name=" trace" type="xs:string" />
  <xs:attribute name="streamCache" type="xs:string" />
  <xs:attribute name="delayer" type="xs:string" />
  <xs:attribute name="handleFault" type="xs:string" />
  <xs:attribute name=" errorHandlerRef" type="xs:string" />
  <xs:attribute name="autoStartup" type="xs:string" />
  <xs:attribute name="useMDCLogging" type="xs:string" />
  <xs:attribute name="useBreadcrumb" type="xs:string" />
  <xs:attribute name="managementNamePattern" type="xs:string" />
  <xs:attribute name="shutdownRoute" type="tns:shutdownRoute" />
  <xs:attribute name="shutdownRunningTask" type="tns:shutdownRunningTask" />
  <xs:attribute name="lazyLoadTypeConverters" type="xs:boolean" />
 
 
 Element : route
Content Model : ((description?), ( from*, (aop | aggregate | bean | doCatch | when | choice | otherwise
 | convertBodyTo | delay | dynamicRouter | enrich | filter | doFinally | idempotentConsumer | inOnly |
 inOut | intercept | interceptFrom | interceptToEndpoint | loadBalance | log | loop | marshal | multicast |
 onCompletion | onException | pipeline | policy | pollEnrich | process | recipientList | removeHeader |
 removeHeaders | removeProperty | resequence | rollback | route | routingSlip | sample | setBody |
 setExchangePattern | setFaultBody | setHeader | setOutHeader | setProperty | sort | split | stop |
 threads | throttle | throwException | to | transacted | transform | doTry | unmarshal | validate |
 wireTap)*))
 
< xs:attribute name =" autoStartup " type =" xs:string " />
  < xs:attribute name =" delayer " type =" xs:string " />
  < xs:attribute name =" errorHandlerRef " type =" xs:string " />
  < xs:attribute name =" group " type =" xs:string " />
  < xs:attribute name =" handleFault " type =" xs:string " />
  < xs:attribute name =" routePolicyRef " type =" xs:string " />
  < xs:attribute name =" shutdownRoute " type =" tns:shutdownRoute " />
  < xs:attribute name =" shutdownRunningTask " type =" tns:shutdownRunningTask " />
  < xs:attribute name =" startupOrder " type =" xs:int " />
  < xs:attribute name =" streamCache " type =" xs:string " />
  < xs:attribute name =" trace " type =" xs:string " />
 
 Element : setHeader
Content Model : ((description?), ((expressionDefinition | constant | el | groovy | header | jxpath |
 javaScript | language | method | mvel | ognl | php | property | python | ref | ruby | simple | spel | sql |
 tokenize | xpath | xquery), (aop | aggregate | bean | doCatch | when | choice | otherwise |
 convertBodyTo | delay | dynamicRouter | enrich | filter | doFinally | idempotentConsumer | inOnly |
 inOut | intercept | interceptFrom | interceptToEndpoint | loadBalance | log | loop | marshal | multicast |
 onCompletion | onException | pipeline | policy | pollEnrich | process | recipientList | removeHeader |
 removeHeaders | removeProperty | resequence | rollback | route | routingSlip | sample | setBody |
 setExchangePattern | setFaultBody | setHeader | setOutHeader | setProperty | sort | split | stop |
 threads | throttle | throwException | to | transacted | transform | doTry | unmarshal | validate |
 wireTap)*))
 
 <xs:attribute name=" headerName" type="xs:string" use="required" />
 
EElement : filter
Content Model : ((description?), ((expressionDefinition | constant | el | groovy | header | jxpath |
 javaScript | language | method | mvel | ognl | php | property | python | ref | ruby | simple | spel | sql |
 tokenize | xpath | xquery), (aop | aggregate | bean | doCatch | when | choice | otherwise |
 convertBodyTo | delay | dynamicRouter | enrich | filter | doFinally | idempotentConsumer | inOnly |
 inOut | intercept | interceptFrom | interceptToEndpoint | loadBalance | log | loop | marshal | multicast |
 onCompletion | onException | pipeline | policy | pollEnrich | process | recipientList | removeHeader |
 removeHeaders | removeProperty | resequence | rollback | route | routingSlip | sample | setBody |
 setExchangePattern | setFaultBody | setHeader | setOutHeader | setProperty | sort | split | stop |
 threads | throttle | throwException | to | transacted | transform | doTry | unmarshal | validate |
 wireTap)*))
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值