2019年7月2日火曜日

クラウドネイティブなアプリケーション環境向けアーキテクチャー

原文: Introduction to cloud-native application environment architecture By Christina Lin July 2, 2019


クラウドネイティブ環境のアーキテクチャーを理解するのはとても大変だったりします。アプリケーション開発者や ソフトウェア/システムアーキテクトの理解を助ける為、これからクラウドネイティブ環境のアーキテクチャーを構成する個々の要素とそれらがどのように連携するかについて説明します。
より理解しやすくするには、アーキテクチャーを4階層に分けて考えるのが有効である事に気がつきました。4階層は、「アプリケーションソフトウェア開発」、「サービスのスケール」、「アプリケーションネットワーク」、「コンテナオーケストレーションプラットフォーム」から構成されます。

この記事では、最初の階層である「アプリケーションソフトウェア開発」について説明します。4階層の概念を視覚化しやすくする為、下記の図を描きました。







































コンテナネイティブまたはクラウドネイティブなアプリケーション開発は一般的なグリーン・フィールドシステムと呼ばれ、アプリケーションはマイクロサービスに分割されます。各マイクロサービスの傾向として独自のデータソースがあり、他のマイクロサービスから独立しており、分散して配置されます。

このような実装の利点は、アプリケーションをよりアジャイルかつポリグロットにし、問題を切り分け、コードベースを小さくし、保守を容易にできることです。仮にこのような実装を選択することで今すぐあなたの人生が良くなると伝えたならば、私のメッセージはウソになります。

アジャイルで真にスケーラブルで自動化されたコンテナ/クラウドネイティブシステムのメリットを実現するには、アプリケーション、プラットフォーム、ペルソナといった要素を考慮する必要があります。以下の要素も含まれます:
  • シナリオに適したテクノロジを使用する
    • 複雑な解決策は過剰である場合があります
    • 間違った解決策を間違った場所で使用すると、責務を見失う可能性があります
  • 継続的インテグレーションをあわせたドメイン駆動設計
    • 非同期のイベントか API
    • 既存のブラウンフィールドアプリケーションといかにインテグレートするか
上の図は、コンテナ/クラウドネイティブ システムのさまざまな構成要素がどのように連携して機能するかの大まかな概要を示します。また、特定のテクノロジをいつ導入するか、または導入するかどうかを決めるのにも役立てばと願います。

アプリケーションソフトウェア開発レイヤー

アプリケーションソフトウェア開発レイヤーは、システムに適用されるソフトウェアパターンに関するレイヤーです。ドメインのモデリング、マイクロサービスの定義方法、デプロイ方法、疎結合で継続的に改善するシステムの開発に役立ちます。また、通信技術とアプリケーション間のパターンも含まれます。

サービス スケール - Knative

アプリケーションが使用されていないときにゼロへスケールインできると、リソースの最適化が可能になります。 このレイヤーは、クラウドコンピューティングの特性を最大限に活用しますが、すべてのサービスが必要とするわけではありません。

アプリケーションネットワーク - Service mesh

これは、分散マイクロサービス環境でとても一般的なアーキテクチャ機能です。 このレイヤーを使用すると、マイクロサービス間の通信をより良く、より均一に制御でき、観測性も向上します。 DevOps はこのレイヤーを使用して、一般的なセキュリティ、障害回復、ロールアウトポリシーなどを適用したり、カスタマイズされたポリシーを設定したりできます。 このレイヤーは、開発者の多くの冗長な作業を取り除きます。

コンテナ オーケストレーション プラットフォーム レイヤー - Red Hat OpenShift

クラウドネイティブ環境におけるアーキテクチャの基盤です。 コンテナオーケストレーション、サービスディスカバリ、CI/CD自動化、ロギングなどの基本的かつ不可欠な機能を提供します。

ドメイン駆動設計 と アジャイル インテグレーション 

ドメイン駆動設計(domain-driven design: DDD)の原則は、ビジネスユーザーと開発者間のコミュニケーションを改善し、ドメインに従ってオブジェクトをモデル化し、境界を設定して複雑なビジネス要件をセグメント化することにより、クラウドネイティブの世界でアプリケーションを開発する方法に適用されます。 DDDの重要な側面は、継続的インテグレーションです。

アジャイル インテグレーションは、マイクロサービスとDDDの基本概念から発展しました。 ビジネスロジックのモデリングをのぞくソフトウェア開発では、他の多くの要素も考慮する必要があります。 DDDをベースとしたアジャイル インテグレーションにより、モデルと境界だけでなく、異なる機能に関する懸念に基きそれらをどのように分離すべきか、およびそれらを物理的にデプロイする方法を定義するのに役立ちます。 アジャイル インテグレーションには3つの主な責任があります。
  • コア - ビジネスロジックまたはドメイン機能を実装するマイクロサービスの大部分は、このカテゴリに属します。 これらは、実行形態およびサービス間の連携方法の両方で軽量であり、典型的に小さくシンプルなマイクロサービスの良い例です
  • コンポジット - ここでは、サービスの適切な粒度の設定、トランザクションの処理、さまざまな種類のイベントに対するオーケストレーション、データ変換がすべて処理されます。 このカテゴリでは、データとイベントの集約と分離が行われます。 これは、あるポイントから別のポイントにイベントを適切な形式で伝搬するシンプルでステートレスなパイプとして機能し、場合によっては外部のSaaS、ブラウンフィールドアプリケーション、または境界コンテキスト外のサービスへのゲートウェイである必要があります
  • コントロール と ディスパッチ - システムが少数の外部システムとのみ連携する場合、このカテゴリは不要かもしれません。このカテゴリを使用すると、システムが提供するサービスについて、より多くの洞察と意味のあるビジネスコントロールが可能になります。これは、迅速でアドホックな変更を必要とする外部クライアントのリクエストから、常に面倒なカスタマイズを隠すカテゴリです。 ファサードパターンはこのカテゴリに適用されます
上記の原則を適用すると、次のことが可能になります:
  • ビジネス要件からモデルとエンティティを抽出します
  • ビジネスドメイン間の境界を設定します
  • コードの性質を分類し、独立した個別のデプロイ可能なマイクロサービスインスタンスに分けます
別の重要で基本的な問題は、これらのマイクロサービス間の通信です。 これらのマイクロサービスの通信バックボーンには、主にイベント駆動型かつ非同期である必要があるはずです。データの配信を疎結合にでき、システムはリアクティブになります。 欠点は、このタイプの設計ではトランザクションがかなり複雑になる可能性があることですが、これはイベントソーシングなどの手法を実装することで克服できます。 境界または外部クライアント/パートナー間の通信には、以下の理由で APIを使用することを強くお勧めします:
  • プロセスのほとんどはリクエスト/レスポンス形式を使用しており、 REST APIの生来の基本動作と合致します
  • コントラクトの定義とリポジトリを管理する為の技術は、API分野でより成熟しています
次回は、イベント内に存在するさまざまなタイプのデータとその処理方法、およびクラウドネイティブなアプリケーション環境でデータの一貫性を実現する方法について説明します。 また、今回紹介していない他のレイヤー(サービススケーリング、アプリケーションネットワーク、コンテナーオーケストレーションプラットフォーム)についても説明します。

原文: Introduction to cloud-native application environment architecture By Christina Lin July 2, 2019

2019年6月25日火曜日

Apache Camel 3 - camel-core vs camel-core-engine (小さくなった core)

原文: Apache Camel 3 - camel-core vs camel-core-engine (smaller core) By Claus lbsen(@davsclaus) June 25, 2019

Camelチームは、現在 Apache Camel 3 のリリースに向け多忙です。すでに多くのタスクが実装済みであり、これまでに 3つの マイルストーン リリースを公開しました。次のマイルストーンのリリース番号 4 には、革新的な新機能が同梱されます。今後数カ月にわたり、この素晴らしい新機能についてブログで紹介していきます。

このブログでは、camel-core をより小さなモジュールに分割した作業について紹介します。小さなモジュールに分割されたことで、必要なものだけを簡単に選択できるようになりました。

camel-core の JAR 依存関係ツリーを見ると、以下のように多くのモジュールに分割されていることがわかります。

[INFO] +- org.apache.camel:camel-core:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-base:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-jaxp:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-management-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-support:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-util:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-util-json:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-bean:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-browse:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-caffeine-lrucache:jar:3.0.0-SNAPSHOT:compile
[INFO] |  |  \- com.github.ben-manes.caffeine:caffeine:jar:2.7.0:compile
[INFO] |  |     +- org.checkerframework:checker-qual:jar:2.6.0:compile
[INFO] |  |     \- com.google.errorprone:error_prone_annotations:jar:2.3.3:compile
[INFO] |  +- org.apache.camel:camel-controlbus:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-dataformat:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-dataset:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-direct:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-directvm:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-file:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-language:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-log:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-mock:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-properties:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-ref:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-rest:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-saga:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-scheduler:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-seda:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-stub:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-timer:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-validator:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-vm:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-xpath:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-xslt:jar:3.0.0-SNAPSHOT:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.25:compile

Camel 2.xでは、前述したすべてのモジュールが同じ camel-core JAR に含まれていました。

Camel 2.x から 3.0 へのマイグレーション作業内容と今後の使いやすさを考慮し、camel-core は Camel 2.x と同じ JAR 依存関係を保持します。つまり上記の出力は、camel-coreへの依存関係を宣言しただけの Maven  pom.xml もしくは gradle build ファイルから生成されたものです。

しかし Camel 3 マイルストーン 4 では、更に必要なものだけを簡単に選択できるようになります。たとえば以下の依存関係ツリーを確認することで、必要最低限の依存関係で camel-core が構成されていることがわかります。(新規に提供される下記 camel-core-engine JAR を dependency に設定します)

+- org.apache.camel:camel-core-engine:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  |  \- org.apache.camel:camel-util:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-management-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-support:jar:3.0.0-SNAPSHOT:compile
[INFO] |  \- org.apache.camel:camel-core:jar:3.0.0-SNAPSHOT:compile
[INFO] |     +- org.apache.camel:camel-base:jar:3.0.0-SNAPSHOT:compile
[INFO] |     \- org.apache.camel:camel-properties:jar:3.0.0-SNAPSHOT:compile

この構成を説明する為に 2つのサンプルを提供しています。


前者はすべての core コンポーネントなどを含む camel-core に依存します。後者は必要最低限の依存関係を使います。この例では bean と quartz2 コンポーネントのみを使用しているので、それらを別途 依存関係として追加する必要があります。

camel-example-main-tiny の依存関係ツリーは以下のとおりです。(JAXB はテストスコープとして除外されます)

[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ camel-example-main-tiny ---
[INFO] org.apache.camel.example:camel-example-main-tiny:jar:3.0.0-SNAPSHOT
[INFO] +- org.apache.camel:camel-core-engine:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  |  \- org.apache.camel:camel-util:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-management-api:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.apache.camel:camel-support:jar:3.0.0-SNAPSHOT:compile
[INFO] |  \- org.apache.camel:camel-core:jar:3.0.0-SNAPSHOT:compile
[INFO] |     +- org.apache.camel:camel-base:jar:3.0.0-SNAPSHOT:compile
[INFO] |     \- org.apache.camel:camel-properties:jar:3.0.0-SNAPSHOT:compile
[INFO] +- org.apache.camel:camel-main:jar:3.0.0-SNAPSHOT:compile
[INFO] +- org.apache.camel:camel-bean:jar:3.0.0-SNAPSHOT:compile
[INFO] +- org.apache.camel:camel-quartz2:jar:3.0.0-SNAPSHOT:compile
[INFO] |  +- org.quartz-scheduler:quartz:jar:2.3.1:compile
[INFO] |  |  +- com.mchange:mchange-commons-java:jar:0.2.15:compile
[INFO] |  |  \- com.zaxxer:HikariCP-java7:jar:2.4.13:compile
[INFO] |  \- com.mchange:c3p0:jar:0.9.5.4:compile
[INFO] +- com.sun.xml.bind:jaxb-core:jar:2.3.0:test
[INFO] +- com.sun.xml.bind:jaxb-impl:jar:2.3.0:test
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.11.2:runtime
[INFO] +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] \- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO]    \- org.slf4j:slf4j-api:jar:1.7.25:compile

2つのサンプルそれぞれに含まれる JARの容量を比較してみました:
  • camel-example-main (camel-core): 48 JAR files with total of 9.3 MB
  • camel-example-main-tiny (camel-core-engine): 21 JAR files with total of 7.4 MB
2つのサンプルをそれぞれ実行すると、camel-core-engineを使用した方が、JVMにロードされるクラス数が若干少なくなることもわかります。
  • camel-example-main (camel-core): 3666 classes loaded
  • camel-example-main-tiny (camel-core-engine): 3430 classes loaded
目立った減少ではなかったかもしれませんが、Camel はコンポーネントを遅延ロード(lazy load)しますし、今回のサンプルは bean と quartz コンポーネントのみ使用している為、想定された結果となります。しかし、ディスクサイズが 約25% 減少し、JAR ファイルが 50% 削減されたことにより、クラスパスのスキャンスピードも多少向上するはずです。

この他にもたくさんの素晴らしい機能が Apache Camel 3 には含まれます。リリース前(2019年の 9月/10月 を予定)となる今夏、これら新機能についてブログを執筆する予定です。


2019年2月1日金曜日

[English] Check this data mapping tool! Atlasmap.io

Have you ever tried "Red Hat Fuse Online" before? It's an "integration Platform-as-a-Service (iPaaS) solution that makes it easy for business users to collaborate with integration experts and application developers".  If you've never tried it yet, please check this free trial.

https://www.redhat.com/en/technologies/jboss-middleware/fuse-online

If you know about "Red Hat Fuse Online", probably also you know that https://syndesis.io/ is the main upstream community for "Red Hat Fuse Online". How about https://www.atlasmap.io/ ?
"AtlasMap is a data mapping solution with interactive web based user interface, that simplifies configuring integrations between Java, XML, and JSON data sources." Please note that the ease of integration development is brought by AtlasMap too.

The good news is even if you are not ready for OpenShift world yet, you can still launch a standalone jar archive on your laptop to start AtlasMap web tooling. Yes, you can experience the data mapping solution within a few seconds. (Community members are still on the way to release standalone Atlasmap(issues/560), but we can try it in advance)
Of course, you can use the mapping file in your Java application. I recommend to use camel-atlasmap component because it's super easy to use.

Let me explain step by step about

  1. Download and launch Atlasmap web tooling
  2. Create data mapping
  3. Run the mapping by using Apache Camel

1: Download and launch AtlasMap web tooling

From version 1.39.0, atlasmap-standalone jar is available in maven central repository.
http://central.maven.org/maven2/io/atlasmap/atlasmap-standalone/1.39.0/atlasmap-standalone-1.39.0.jar
You can run AtlasMap standalone by `java -jar atlasmap-standalone-1.39.0.jar` which is springboot uber jar and UI is available at localhost:8585.

If you want to try latest AtlasMap source code, clone the repository and build it by yourself.
$ git clone https://github.com/atlasmap/atlasmap.git
$ cd ${ATLASMAP}
$ ./mvnw clean install -DskipTests

After booting up the web UI, you will see the console log something like this
2019-02-01 13:39:37.762  INFO 16127 --- [           main] b.c.e.u.UndertowEmbeddedServletContainer : Undertow started on port(s) 8585 (http)
2019-02-01 13:39:37.766  INFO 16127 --- [           main] io.atlasmap.standalone.Application       : Started Application in 4.816 seconds (JVM running for 5.427)
2019-02-01 13:39:37.766  INFO 16127 --- [           main] io.atlasmap.standalone.Application       : ### AtlasMap Data Mapper UI started at port: 8585 ###

2: Create data mapping

After accessing to localhost:8585, please take a look at the UI for about 5 minutes. I guess you will see what/how you can use  this tool.

On the left side panel named "Source", you can import and display the source data structure to convert.
On the right side pane named "Target", you can import and display the target data structure.

Java, XML, and JSON format is currently supported.

By moving the cursor to the arrow icon next with "Source" or "Target", you will see the pop up message "import instance or schema file".
As pop up message says, you can import xml file.(not schema file) AtlasMap will automatically analyze it for you.
Also you can import jar archive which contains multiple class files. After importing a jar archive, you can specify specific class name with package name.

By clicking each data entries from "Source" and "Target", you can do mapping.
On the right side panel named "Action", you can choose how you map data entries. (map/combine/separate)

By clicking gear icon on the right top right side corner, you can enable "Show Mapping Preview". With this feature, you can simulate the mapping using dummy data.

When you finish mapping, click export icon on the top right side to get the mapping archive.

3: Run the mapping by using Apache Camel

Using "Red Hat Developer Studio"(Eclipse) new project wizard, you can create a new sample Camel project. Please select spring boot for the run time. I select 2.21.0.fuse-720050-redhat-00001 for Red Hat Fuse version. If you love karaf container, please watch
https://github.com/atlasmap/atlasmap/issues/68.

Add camel-atlasmap dependency in the pom.xml

<dependency>
  <groupId>io.atlasmap</groupId>
  <artifactId>camel-atlasmap</artifactId>
  <version>1.40.0-SNAPSHOT</version>
</dependency>

Since 1.40.0-SNAPSHOT is not hosted on maven central repository, you need to use the one in the local maven repository.(I did mvn install with latest atlasmap git repo, so I can use 1.40.0-SNAPSHOT)

This is a sample camel route to test data mapping.
Timer consumer endpoint will fire one time. Put a sample pojo object using "sebBody", and do mapping(pojo to xml) by using camel-atlasmap. we can check the result by comparing the output log.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd  http://camel.apache.org/schema/spring  http://camel.apache.org/schema/spring/camel-spring.xsd">
    <bean class="sample.Product" id="sampleProduct">
        <property name="id">
            <value>1</value>
        </property>
        <property name="price">
            <value>1000</value>
        </property>
    </bean>
    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
        <route id="simple-route">
            <from id="route-timer" uri="timer:timerName?repeatCount=1"/>
            <log id="route-log1" message="hello world"/>
            <setBody id="route-setBody">
                <simple>${ref:sampleProduct}</simple>
            </setBody>
            <log id="route-log2" message="Before Mapping >>> ${body}"/>
            <to id="_to1" uri="atlas:atlasmap-mapping.adm"/>
            <log id="route-log3" message="After Mapping >>> ${body}"/>
        </route>
    </camelContext>
</beans>

This part of camel route is camel-atlasmap. atlasmap-mapping.adm file is placed under $PROJECT/src/main/resources.

<to id="_to1" uri="atlas:atlasmap-mapping.adm"/>

This is the part of output log. We can confirm that the data was converted from pojo to xml.
14:08:33.813 [main] INFO  org.mycompany.Application - Started Application in 4.41 seconds (JVM running for 4.691)
14:08:34.763 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - hello world
14:08:34.768 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - Before Mapping >>> sample.Product@5ed4bc
14:08:35.036 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='JSONInstanceSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='JSONInstanceSource': docId='JSONInstanceSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='JSONSchemaSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='JSONSchemaSource': docId='JSONSchemaSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='XMLSchemaSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='XMLSchemaSource': docId='XMLSchemaSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='sample.Product', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='XMLInstanceSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='XMLInstanceSource': docId='XMLInstanceSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - No target document created for DataSource:[id=JSONInstanceTarget, uri=atlas:json:JSONInstanceTarget]: docId='JSONInstanceTarget', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - No target document created for DataSource:[id=JSONSchemaTarget, uri=atlas:json:JSONSchemaTarget]: docId='JSONSchemaTarget', path='null'
14:08:35.039 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - After Mapping >>> {JSONInstanceTarget=null, JSONSchemaTarget=null, XMLInstanceTarget=<?xml version="1.0" encoding="UTF-8" standalone="no"?>, sample=<?xml version="1.0" encoding="UTF-8" standalone="no"?><request><id>1</id><price>1000</price></request>, XMLSchemaTarget=<?xml version="1.0" encoding="UTF-8" standalone="no"?>}

For more details/instruction/latest information about AtlasMap, please visit https://www.atlasmap.io/.
I hope this post helps a bit.

Regards,
Hisao

2019年1月31日木曜日

atlasmap.io に注目! (後編)

2018年12月21日に data mapperを使いマッピングをデザインしてから1ヵ月以上が経過していました。。
大変遅れてしまいましたが、やっとマッピングしたものを動かす記事を書きます。

日進月歩の勢いで開発が進んでいるプロジェクトなので、現時点での改善点をいくつかご紹介します。
 1: 1.39.0 から、maven repositoryで atlasmap-standalone jar が公開されました。
   http://central.maven.org/maven2/io/atlasmap/atlasmap-standalone/1.39.0/atlasmap-standalone-1.39.0.jar
   java -jar atlasmap-standalone-1.39.0.jar で web ui が起動します。ポート番号は前回と同様に 8585 です。

 2: camel-atlasmap コンポーネントを動かす為の修正や改善が複数入りました。コミュニティメンバーが親切に対応してくださったおかげで、使い易くなっています。
    https://github.com/atlasmap/atlasmap/issues/712
    https://github.com/atlasmap/atlasmap/issues/713
    https://github.com/atlasmap/atlasmap/issues/729

今回の動作検証を通し、不具合についてコミュニティメンバーへインプットしました。メンバーはどなたも親切で、何かインプットしてから製品に反映されるまでの速さにはとても驚きました。ディスカッションを通して内部構造を知るきっかけにもなり 良い事尽くしだったので、ぜひ皆さんもコミュニティーへ活発に参加されてみてはいかがでしょうか。

話がそれましたが、いよいよ本題です。今回は camel-atlasmap を使い、データ変換を試してみます。ランタイムは springbootを使います。
(捕捉: karaf愛好家の方は、こちらのチケットを watchしてください。 https://github.com/atlasmap/atlasmap/issues/68)

atlasmap git repository を最新の状態にし、ビルドしてください。

$ cd ${ATLASMAP}
$ git pull
$ ./mvnw clean install -DskipTests

お手数ですが、再度前回の投稿で実施したマッピング作業をし、設定ファイルをエクスポートしてください。 issues/713 の修正を使った設定ファイルが必要だからです。

Red Hat Developer Studio(Eclipse) のウィザードで、新規 Camel プロジェクトを作成します。ランタイムに springboot を選択し、Fuseのバージョンには 2.21.0.fuse-720050-redhat-00001 を指定しました。
pom.xml に camel-atlasmap の dependency を追記します。

<dependency>
  <groupId>io.atlasmap</groupId>
  <artifactId>camel-atlasmap</artifactId>
  <version>1.40.0-SNAPSHOT</version>
</dependency>

オンライン リポジトリーには 1.40.0-SNAPSHOT が公開されていないので、ローカルリポジトリを参照する必要があります。

データ変換を試す為に、簡単な camel routeを作成しました。タイマーを使い1回メッセージを生成し、サンプル用の pojoを挿入後、camel-atlasmap で xmlに変換しています。変換前/変換後のデータはログから確認できます。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd  http://camel.apache.org/schema/spring  http://camel.apache.org/schema/spring/camel-spring.xsd">
    <bean class="sample.Product" id="sampleProduct">
        <property name="id">
            <value>1</value>
        </property>
        <property name="price">
            <value>1000</value>
        </property>
    </bean>
    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
        <route id="simple-route">
            <from id="route-timer" uri="timer:timerName?repeatCount=1"/>
            <log id="route-log1" message="hello world"/>
            <setBody id="route-setBody">
                <simple>${ref:sampleProduct}</simple>
            </setBody>
            <log id="route-log2" message="Before Mapping >>> ${body}"/>
            <to id="_to1" uri="atlas:atlasmap-mapping.adm"/>
            <log id="route-log3" message="After Mapping >>> ${body}"/>
        </route>
    </camelContext>
</beans>

camel-atlasmap の定義はこの箇所です。

<to id="_to1" uri="atlas:atlasmap-mapping.adm"/>

出力した atlasmap-mapping.adm を指定しています。atlasmap-mapping.adm は、$PROJECT/src/main/resources 配下に設置しています。

プロジェクトを実行すると、このようなログが出力されるはずです。(ログは一部を抜粋しています) XMLに変換されている事が確認できます。

14:08:33.813 [main] INFO  org.mycompany.Application - Started Application in 4.41 seconds (JVM running for 4.691)
14:08:34.763 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - hello world
14:08:34.768 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - Before Mapping >>> sample.Product@5ed4bc
14:08:35.036 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='JSONInstanceSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='JSONInstanceSource': docId='JSONInstanceSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='JSONSchemaSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='JSONSchemaSource': docId='JSONSchemaSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='XMLSchemaSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='XMLSchemaSource': docId='XMLSchemaSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='sample.Product', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - There's no source document with docId='XMLInstanceSource', returning default: docId='null', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - Null or non-String source document: docId='XMLInstanceSource': docId='XMLInstanceSource', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - No target document created for DataSource:[id=JSONInstanceTarget, uri=atlas:json:JSONInstanceTarget]: docId='JSONInstanceTarget', path='null'
14:08:35.037 [Camel (MyCamel) thread #1 - timer://timerName] WARN  o.a.c.c.atlasmap.AtlasEndpoint - No target document created for DataSource:[id=JSONSchemaTarget, uri=atlas:json:JSONSchemaTarget]: docId='JSONSchemaTarget', path='null'
14:08:35.039 [Camel (MyCamel) thread #1 - timer://timerName] INFO  simple-route - After Mapping >>> {JSONInstanceTarget=null, JSONSchemaTarget=null, XMLInstanceTarget=<?xml version="1.0" encoding="UTF-8" standalone="no"?>, sample=<?xml version="1.0" encoding="UTF-8" standalone="no"?><request><id>1</id><price>1000</price></request>, XMLSchemaTarget=<?xml version="1.0" encoding="UTF-8" standalone="no"?>}

ぜひお試しいただき、コミュニティーへフィードバックしていただければと思います。こちらへコメントしていただければ、自分が代理でコミュニティーへインプットすることもできます。お気軽にお知らせください。
引き続きよろしくお願い致します。