LoginSignup
6
6

More than 5 years have passed since last update.

camel-scalaの基本的なDSL

Last updated at Posted at 2015-03-23

前提

  • 基本文法をJavaDSLとScalaDSLの比較。
  • JavaDSLはApacheCamel本家からコピってちょっと改変しているので動作確認まではしていない。
  • Java:1.7.0_25
  • Scala:2.11.6
  • Camel:2.14.0
    執筆途中から2.15.0へVup RouteBuilderの派生元が変わっている。
    org.apache.camel.scala.dsl.builder.RouteBuilder
    org.apache.camel.scala.dsl.builder.ScalaRouteBuilder

Route定義

  • scala は クラスのメンバーとしてRouteとなるDSLを定義する。
    Routeを記述している DSLはクラスの最下部に定義する 必要がある。
  • java は configureメソッド内にRouteとなるDSLを定義する。
  • from は "Route定義" ==>、to は -->("Route 定義")で記述する。
  • java は ;まで、scalaは{}内がRoute定義となる。
  • java scalaともにRouteBuilderを継承するのは同じだけど、 パッケージが違う ので注意。
    ※camel-scala2.15.0からはorg.apache.camel.scala.dsl.builder.RouteBuilder@deprecatedとなり、org.apache.camel.scala.dsl.builder.ScalaRouteBuilderを使うようにする。
import org.apache.camel.builder.RouteBuilder;

class MyRouteBuilder extends RouteBuilder {
    public void configure() {
        from("direct:a")
            .to("direct:b");
    }
}
import org.apache.camel.scala.dsl.builder.RouteBuilder

class MyRouteBuilder extends RouteBuilder {
  from("direct:a") {
    to("direct:b")
  }

  // from - to を記号を使っても書ける。
  // こっちの方がscalaっぽい気がする。
  "direct:aa" ==> {
    -->("direct:bb")
  }
}


以下、特筆が無ければ以下の前提で記述する

  • JavaDSLはconfigureメソッド内。
  • ScalaDSLのfrom - to は ==> --> 形式

filter (if)

  • if文のみで else文は書けない
  • headerのオブジェクトの有無でも判断出来る
  • headerやbodyがBooleanの場合は、式を省略することが出来る
  • booleanを返すprocessorを引数に渡すことが出来る
  • Scalaの場合、header("key")_.in(key)とも書けるが、違いはよく分からない
from("direct:filter")
    .filter(body().isEqualTo("foo"))
        .to("mock:foo")
    .end()
    .to("mock:result");
"direct:filter" ==> {
  filter(body(_) == "foo") {
    -->("mock:foo")
  }
  -->("mock:result")
}

choice - when - otherwise (if - elseif - else)

  • if elseに使う。if のみの場合はchoiceは省略できる。( = fileter)
  • scalaDSLでは、end() の代わりにブロック内が条件合致時の処理。
  • 条件の記述方法はfilterと(多分)同じ。
from("direct:if-else-body")
    .choice()
        .when(body().isEqualTo("foo")).to("mock:foo")
        .when(body().isEqualTo("bar")).to("mock:bar").stop()
        .otherwise().to("mock:otherwise")
    .end()
    .to("mock:result");
"direct:if-else-body" ==> {
  choice {
    when(body(_) == "foo") {
      -->("mock:foo")
    }
    when(body(_) == "bar") {
      -->("mock:bar")
      stop
    }
    otherwise {
      -->("mock:otherwise")
    }
  }
  -->("mock:result")
}

loop (for or while)

  • 回数は固定で途中でブレイク出来ない
  • 固定回数の場合は引数にそのまま数値を記述出来る
  • 条件式は_.in("key").asInstansOf[Seq[Any]].lengthとか書けば、Seqの長さでループ出来る。
    ※loop内でSeqの長さを変えてもloopする回数は変わらない。
from("direct:b")
    .loop(header("loop"))
        .to("mock:result");
"direct:b" ==> {
  loop(_.in("loop"))
    -->("mock:result")
}

try - catch

  • attemp - handle - ensureで記述する
  • multi catchは対応していない
from("direct:direct:attempt-handle")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IllegalStateException.class, NullPointerException.class)
        .to("mock:illegalstate-or-nullpointer-exception")
    .doCatch(Exception.class)
        .to("mock:exception")
    .doFinally()
        .to("mock:finally")
    .end();
  "direct:attempt-handle" ==> {
    attempt {
      process(occurException)
      -->("mock:result")
    } handle (classOf[IllegalStateException]) apply {
      -->("mock:illegal-state-exception")
    } handle (classOf[Exception]) apply {
      -->("mock:exception")
    } ensure {
      -->("mock:finally")
    }
  }

Tips

HeaderとBody

誤解を恐れずいえば、Exchange(箱)の中はInメッセージ(HTTPで言えば、Request)とOutメッセージ(同 Response)に分かれている。
また、InとOutはそれぞれ、HeaderとBodyでデータを保持してる。

Header

  • Map[String, Any]のような物。
  • J2EEでいうと、Sessionオブジェクトのような存在。
  • directsedaコンポネントで別Routeを呼んだ場合、Headerの値は引き継がれる。
    Routeが長く肥大化してくると、Headerも肥大化しやすいので実装時に注意が必要。
  • DSLで取得する場合は_.in("header key") (or header("header key"))で取得出来る。
  • DSLで設定する場合はsetHeader("header key", [value])で設定出来る。

Body

メッセージ本体。

  • fromでRouteが呼ばれた時にはBody部にメッセージが詰められている。
    • fileコンポーネント(file://directory?fileName=foo.txt みたいの)だとファイルの中身
    • activemqコンポーネント(activemq:queueName:QUEUE)だとQueueの中身
  • DSLで取得する場合はbody(_)で取得出来る。
  • DSLで設定する事は基本的には出来ない。(ただし応用すれば?出来る。)

サンプルコード

  • Scala:2.11.6
  • Camel:2.15.0
6
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6