Scala DSL - EIP
===============

[TIP]
====
*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
https://svn.apache.org/repos/asf/camel/trunk/components/camel-scala/src/test/scala/[unit
test source code] for the Scala Component to find more examples.
====

* 1 link:#ScalaDSL-EIP-Messagingsystems[Messaging systems]
** 1.1 link:#ScalaDSL-EIP-Pipelinepipeline[Pipeline]
** 1.2 link:#ScalaDSL-EIP-Filterfilter[Filter]
* 2 link:#ScalaDSL-EIP-Messagingchannels[Messaging channels]
** 2.1 link:#ScalaDSL-EIP-Deadletterchannel[Dead letter channel]
* 3 link:#ScalaDSL-EIP-Messagerouting[Message routing]
** 3.1 link:#ScalaDSL-EIP-Aggregator[Aggregator]
** 3.2 link:#ScalaDSL-EIP-Contentbasedrouter[Content based router]
** 3.3 link:#ScalaDSL-EIP-Delayer[Delayer]
** 3.4 link:#ScalaDSL-EIP-Loadbalancer[Load balancer]
** 3.5 link:#ScalaDSL-EIP-Multicast[Multicast]
** 3.6 link:#ScalaDSL-EIP-Recipientlist[Recipient list]
** 3.7 link:#ScalaDSL-EIP-Resequencer[Resequencer]
** 3.8 link:#ScalaDSL-EIP-Splitter[Splitter]
** 3.9 link:#ScalaDSL-EIP-Throttler[Throttler]
* 4 link:#ScalaDSL-EIP-Messagetransformation[Message transformation]
** 4.1 link:#ScalaDSL-EIP-Contentenricher[Content enricher]

[[ScalaDSL-EIP-Messagingsystems]]
Messaging systems
-----------------

[[ScalaDSL-EIP-Pipelinepipeline]]
Pipeline
~~~~~~~~

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

[source,java]
----------------------------------------------------------
"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 `→`.

[source,java]
----------------------------------------------------------
"direct:e" ==> {
  --> ("mock:e")
  --> ("mock:f")
}

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

[[ScalaDSL-EIP-Filterfilter]]
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.

[source,scala]
----------------------------------------------------------
"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.

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

[[ScalaDSL-EIP-Messagingchannels]]
Messaging channels
^^^^^^^^^^^^^^^^^^

[[ScalaDSL-EIP-Deadletterchannel]]
Dead letter channel
+++++++++++++++++++

The http://www.eaipatterns.com/DeadLetterChannel.html[dead letter
channel] can be created with the syntax similar to the one used in
http://camel.apache.org/dead-letter-channel.html[Java DSL].

[source,java]
------------------------------------------------------------------
"jms:in" errorHandler(deadLetterChannel("jms:error")) to "jms:out"
------------------------------------------------------------------

You can also use different error handler available for the
http://camel.apache.org/error-handler.html[Java DSL]. In particular
Scala DSL supports
http://camel.apache.org/defaulterrorhandler.html[DefaultErrorHandler]
and
http://camel.apache.org/error-handler.html#ErrorHandler-LoggingErrorHandler[LoggingErrorHandler].

[source,java]
----------------------------------------------------------------------------------------------------------------
// DefaultErrorHandler
"jms:in" errorHandler(defaultErrorHandler) to "jms:out"

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

[[ScalaDSL-EIP-Messagerouting]]
Message routing
^^^^^^^^^^^^^^^

[[ScalaDSL-EIP-Aggregator]]
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.

[[ScalaDSL-EIP-Contentbasedrouter]]
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 link:scala-dsl-supported-languages.html[supported
languages]. The example below routes a given message based on the
language of the message body.

[source,java]
----------------------------------------------------------------------------------------------------------------
"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")
  }
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Delayer]]
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...

[source,java]
----------------------------------------------------------------------------------------------------------------
"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`

[source,java]
----------------------------------------------------------------------------------------------------------------
"seda:b" ==> {
  to ("mock:b")
  delay(1 seconds) {
    to ("mock:c")
  }
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Loadbalancer]]
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`

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:a" ==> {
  loadbalance roundrobin {
    to ("mock:a")
    to ("mock:b")
    to ("mock:c")
  }
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Multicast]]
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:

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:a" --> ("mock:a", "mock:b") --> "mock:c"
"direct:d" to ("mock:d", "mock:e") to "mock:f"
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Recipientlist]]
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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"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:

[source,java]
----------------------------------------------------------------------------------------------------------------
"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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:c" ==> {
  to("mock:c")
  recipients(jxpath("./in/body/destination"))
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Resequencer]]
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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:a" resequence (_.in) to "mock:a"
----------------------------------------------------------------------------------------------------------------

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

[source,java]
----------------------------------------------------------------------------------------------------------------
"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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:d" ==> {
  to ("mock:d")
  resequence(_.in).batch(5) {
    to ("mock:e")
  }
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Splitter]]
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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:a" as(classOf[Document]) split(xpath("/persons/person")) to "mock:a"
----------------------------------------------------------------------------------------------------------------

[source,java]
----------------------------------------------------------------------------------------------------------------
"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.

[[ScalaDSL-EIP-Throttler]]
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:

[source,java]
----------------------------------------------------------------------------------------------------------------
"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.

[source,java]
----------------------------------------------------------------------------------------------------------------
"seda:b" ==> {
  to ("mock:b")
  throttle (3 per (2 seconds)) {
    to ("mock:c")
  }
}
----------------------------------------------------------------------------------------------------------------

[[ScalaDSL-EIP-Messagetransformation]]
Message transformation
^^^^^^^^^^^^^^^^^^^^^^

[[ScalaDSL-EIP-Contentenricher]]
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:

[source,java]
----------------------------------------------------------------------------------------------------------------
"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:

[source,java]
----------------------------------------------------------------------------------------------------------------
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-component,Velocity>>) to enrich the content and add it to a
pipeline


[source,java]
----------------------------------------------------------------------------------------------------------------
"direct:c" to ("velocity:org/apache/camel/scala/dsl/enricher.vm") to ("mock:c")
----------------------------------------------------------------------------------------------------------------
