Gleyzer両氏によって共同開発されました。2019で、同言語の発表を行いました。InfoQはPurdy氏に言語と、氏らが解決を目指した問題について聞きました。設計/アーキテクチャアジャイルマニュフェスト:ソフトウェアアーキテクトの視点ソフトウェアアーキテクトの役割と責任はアジャイルソフトウェア開発のためのマニフェストの価値と矛盾していると見えますが、優れたアーキテクトはアジャイル開発チームをサポートするテクニックを見つけています。Streamingは、ストリーミングデータのためのSQLライクなインターフェースを提供します。Streamsによって、Redisがストリーミングデータを複数のプロデューサとコンシューマの間で消費、保持、配信することができるようになります。ソフトウェア開発のマニフェストたゆまず息もつかずに市場に突進することで、会社を静かに消滅の崖っぷちへと追い込みます。それは設計してコードを書く方法を再考する時です。簡単さへの投資は、速さへの投資です。簡単さは知的財産の主鉱脈でもあります。競争上の優位性は、一度失ったら、もう一度手に入れることはほとんど不可能です。Buytaerts氏が過去10年間にわたって、企業がDevOps採用のハイプサイクルをくぐり抜け、変革に対する誤解を解消する過程を支援してきた経験について語ります。俊平はじめに.NETとJava間の相互運用には、様々なアプローチが存在します。Schemaを作り上げ、Webサービスを使用することです。あなたが期待するとおり、Webサービスはインターネットベースのアプリケーションにとってはベストな解です。一つの部門内や組織内の、LAN上で動作するイントラネットアプリケーションを書くのであれば、他のミドルウェア技術も魅力的なものとなります。メッセージ指向ミドルウェア(MOM)は、単一の企業内で様々なプラットフォームを統合するのに一般的な選択肢です。この記事では、.NETとJavaの間のコミュニケーションの基盤としてMOMを使用し、ローカルLANで動作する単純な株取引アプリケーションの中で、.NETクライアントとJavaの中間層が連携するというデモンストレーションをお見せします。実装にあたっては、アプリケーションの層をまたがって共通のプログラミングモデルを提供するため、SpringフレームワークによるJMSサポート(Javaと同様.NETでも利用可能です)を使用します。メッセージングなのか?いろいろな意味で、メッセージ指向ミドルウェアは相互運用性における長老のようなものだと考えられます。IBMやTIBCOといったベンダーは、異質なオペレーティングシステムが混在する環境で動作し、複数の言語バインディングを持つメッセージングミドルウェアを20年以上にわたり提供してきました。Service(JMS)仕様が、メッセージングの世界に登場しました。API1を提供しています。Framework、そしてC++クライアントAPIを提供している、TIBCOのJMS実装を使用します。付け加えますが、もしあなたが選んだベンダーが.NETクライアントを提供していないとしても、.NETからJMSにアクセスする方法は少ないながらも選択の余地が残されています。Codemesh3などの相互運用のための製品を使用する、というのがあります。メッセージングを使う理由が、相互運用のためにやむを得ず、というのであれば、デファクトではないにせよ、アプリケーションのアーキテクチャにあわせた魅力的な選択肢が(メッセージング以外の)他にもたくさん存在します。要するに、MOMを使う利点はプロセス間の非同期な対話、パブリッシュ/サブスクライブ型(1対多)のメッセージ配信、そして高いレベルの信頼性というところにあるのです。あなたのアプリケーションがこうした機能から恩恵を受けられるのであれば、極めて高い確率で、メッセージングソリューションを使用するのが自然かもしれません。あなたの会社が既に、こうした理由からJavaもしくはC++ベースのアプリケーションのみからなるメッセージングを使用しているのなら、すでにあるアーキテクチャを論理的に拡張して.NETクライアントを含めるようその役割を広げることができます。JMSベースのソリューション構築には、独自の学習曲線とベストプラクティスの集合を持つからです。この記事は、.NETとJavaの上でSpringフレームワークを使用し、いかに素早くJMSアプリケーションを作成できるかをお見せします。.NETとJava間の対話にメッセージングを利用するあたって生じるいくつかの問題点に対する手引きを提供したいと思います。Spring.NET4についてはあまりよく知られていません。Spring.NETはSpringフレームワークの.NETバージョンです。C#で全て構築されており、アプリケーション開発に対するSpringのデザインとアプローチを.NETに持ち込みます。Exporters、宣言的トランザクション管理、そしてADO.NETフレームワークなどを備えています。"Spring.Java"のユーザであれば、Spring.NETにもすぐ馴染むことができるでしょう。Spring.Javaが多くのサードパーティ製ライブラリを基本セットに含めているのとは違い、Spring.NETは別々にダウンロードすることができるモジュールとしてサードパーティ製ライブラリに対するサポートを分割しています。JMSのサポートを提供しています。Service)の評価版をダウンロードする必要があります。"という疑問は当然のことです。他のベンダーがサポートされていないのは、大した理由があるわけではありません。APIのデファクトが.NETに存在していない(ためAPIが統一されていない)という現実的な理由からです。APIに着想を得て、コピーしています。私がTIBCOのJMS製品を最初にSpring.NETでサポートしようと考えたのは単に、非常に慣れ親しんでいたので都合が良かったためです。SpringフレームワークによるメッセージングSpringによるJMSサポートのゴールは、JMSを使用する際の抽象度を高め、メッセージングにおけるベストプラクティスをサポートすることです。Springはこれらのゴールを達成するため、簡単に使えるクラス(複数)を提供しています。object"(POJO/POCO)プログラミングモデルによるメッセージングを可能にします。objects"の間の変換を行うことです。これは(Webサービスにおける)XML/オブジェクトマッパーと同じ考え方であり、それをJMS用に変形したものです。メッセージコンバータを使用すると、JMS関連のコードをあなたのアプリケーションの最も外層に追いやることができるため、アプリケーションの大部分がその技術的な詳細を知らずに済みます。ミドルウェアを切り替える必要が生じたとしても、JMSのMapMessageがビジネス処理内に散見する場合に比べると、リファクタリングが非常に容易です。JDBCに似て、JMSは低いレベルのAPIであり、最も基本的なJMSタスクの場合でさえ多くの仲介者的なオブジェクトを作成、管理する必要があります。JMSオペレーションを"ワンライナー(1行プログラム)"にします。受信側においては、SpringのMessageListenerContainerのおかげで、メッセージを並行、かつ非同期に処理するための基盤を簡単に作ることができます。MessageListenerContainerはどちらも、JMSとPOJO/POCOの間の変換を行うためにMessageConverterと関連付けることができます。よるJMSサポートの中核をなすものです。この記事はこれらを広く使用し、多少は詳細についても解説しますが、完全なリファレンスというわけではありません。詳しく知りたければ、Springのリファレンスドキュメンテーションか、その他のSpringに関する文献を当たってみて下さい。World"というテキストメッセージを送信する例を見てみましょう。APIを直接使用するのに比べて、JmsTemplateを使用するのがいかに単純かがすぐに見て取れるでしょう。JmsTemplateは本来コーディングが必要な、JMS接続、セッション、メッセージプロデューサなどのリソース管理に関して鋳型を提供するのが主な役目だからです。JmsTemplateは、Javaにおけるチェック例外を非チェック例外に変換したり、JMSのあて先を文字列ベースで指定できるようにしたり、オブジェクトをJMSメッセージに変換するためにMessageConverterに処理を委譲したり、などのいろいろ便利な機能も提供します。変換なしでメッセージを送信したい時のために、JmsTemplateは単純なSendメソッドも持っています。World!"をJMSのTextMessageに変換します。SimpleMessageConverterはまた、バイト配列からByteMessageへの変換、ハッシュテーブルからJMSのMapMessageへの変換もサポートしています。JMSアプリケーションを作るための中核となる作業は、カスタムのMessageConverterを実装し、提供することです。アプリケーションコード内で使われているオブジェクトに対するコンバータを作成して、単純にJMS(メッセージ)へのマーシャル/アンマーシャルを行うのが一般的なアプローチです。objects"の実装が互換性を持っているかどうかという点に集約されます。objects"のことを"ビジネスオブジェクト"と呼ぶことにしましょう。それらは実際には、完全に独立したドメインオブジェクト、データトランスファーオブジェクト、もしくはUIに表示するため最適化されたバージョンのドメインオブジェクトとなります。このアプローチにおけるビジネスオブジェクトとは、本質的に、二つの層間におけるデータ規約と成り得ます。そのフィールドとプロパティはデータ規約の一部であり、MessageConverterの実装からは独立しています。ここで注意すべきは、ある特定のデータ型については明確に共通なものがないと言うことです。片側で使用されているデータ型を、もう片方の側で互換性のある形で使用するには、それらに関連付けられたメッセージコンバータが責任を持って変換処理を行う必要があります。このアプローチは確かに、Webサービスのようにまず規約ありき、というアプローチよりも強制力が弱いです。そのため、やり取りされるデータに強い制約を課したり、ささいなミスマッチを減らすためのいくつかのテクニックが存在します。この点に関して、技術的ではない面から助けになるのは、イントラネット内もしくは部門別のアプリケーションは同じグループ(または人物)が.NETクライアントとJavaミドル層を開発していることが多いと言うことです。従って、異なる開発グループの間であらかじめ定めた規約を使用する、ということの拡張として、コミュニケーションや頻繁に行われる統合テストを捕らえなおすことができます。あなたが、層同士の連携においてあらかじめ定められた形式ばった規約を定義するのがお好みなら、JMSのアプローチは多分好きになれないのではないでしょうか。言っても、相互運用性に対するこのゆるい、確かにあまり標準的ではないアプローチは、私の知る限りいくつかのプロジェクトで成功を収めてきています。以下の節で、MessageConverterを使用して.NETをJavaの間でビジネスオブジェクトを同期しておくための、より洗練されたアプローチをお見せしたいと思います。サンプルアプリケーションは、Springにが持つSimpleMessageConverterを使用して、ハッシュテーブルのやり取りを行う所からスタートします。最終的には、ソースコードトランスレータや汎用的な"万能"MessageConverterを用いて、プラットフォームそれぞれにおいてコンバータとビジネスオブジェクトを手書きするという、重複した作業を減らすためのいくつかのテクニックをお見せします。それぞれのアプローチにおける様々な良い点と悪い点は、途中で議論します。株取引サンプルお見せするサンプルは、単純化した株式取引アプリケーションです。市場情報のリアルタイム配信、新しい取引の開始、取引におけるポートフォリオの検索です。市場情報の配信を行うにあたって、我々はJavaの中間層から.NETクライアントにメッセージを送るためのJMSインフラを作成します。Javaの中間層では、メッセージの送信のためJmsTemplateが作成され、クライアント側ではメッセージの受信のためSimpleMessageListenerContainerが作成されます。どちらのクラスも、デフォルトではSimpleMessageConverterを使用してJMSメッセージとオブジェクトの変換を行います。そのため、.NET/Java間では単純なハッシュテーブルをデータのやり取りに使い、デフォルトのコンバータを使用します。JmsTemplateとSimpleMessageListenerの双方に、JMS接続ファクトリとJMSあて先の名称、タイプに関する設定が必要です。MessageListenerコールバックの実装への参照を指定する必要があります。使用して受信したJMSメッセージをオブジェクトに変換する機能を持つ、MessageListenerAdapterクラスを提供しています。MessageListenerAdapterは、MessageConverterを使用してオブジェクトに変換した後、ユーザが提供したハンドラオブジェクト内の、シグネチャが適合するメソッドを呼び出します。前述の流れが、最もよくサンプルについて言い表しています。data)"というシグネチャのメソッドが呼び出されます。trade)というメソッドを持つ必要があります。以下のシーケンス図がイベントの流れを表しています。MessageListenerが直接メッセージングのコールバックとしては働きません。このアプローチの利点の一つは、ハンドラメソッドを直接呼び出して、アプリケーションの流れを試すような統合スタイルのテストケースを作成するのが容易になるという点です。その他の利点としては、MessageListenerAdapterがメッセージングアプリケーションに良く見られるif/elseやswitch/caseの肩代わりをしてくれると言う点です。SimpleMessageListenerContainerは、ハンドラメソッドの戻り値に応じて返答メッセージを自動的に送信したり、処理の流れをカスタマイズするためにサブクラス化されることを意図している、など他にも機能がたくさんあります。詳しくはSpringのリファレンスドキュメントを参照してください。これらのオブジェクトに対するSpringの設定を以下に示します。value="HandleObject"/></object>Spring.NETは、オブジェクトを定義する際'bean'ではなく'object'というXML要素を使用するのに注意してください。ハンドラオブジェクトは、"DelegateObject"という.NETの感覚から言うと少し気持ち悪い名前を持ちます。delegateとは何の関係もありません。クライアントへ送られる全てのデータはAPP.STOCKというJMSトピック上に送信され、クライアントから(Javaの)中間層へはAPP.STOCK.REQUESTというキューを用いて全てのデータが送信されます。JMSメッセージの送信は、市場データ自体はちょっと嘘っぽいですが、以下に示すように単純なものです。jmsTemplate.send(marketData);受信側は、StockAppHandlerクラスのメソッド内で処理が行われます。}}始めるにあたって最少量のインフラコードは全て整いました。ハッシュテーブルのやり取りは非常に簡単で、かつ設定一切なしで利用できるものの、これは最も単純な相互運用シナリオの場合にのみ適切です。私は、10個未満のキーと値のペアからなる、5個未満のデータのやり取りを以って単純と意味づけています。その理由は、より複雑なシナリオでは上手く広げていけないのは極めて明白であり、データの規約がゆるすぎて、二つの層の間でキーと値のペアにミスマッチが生じないようにするのが難しくなってきます。自然なアプローチは、データをクラスにカプセル化する事です。したクラスは、例えば、パラメータを持つコンストラクタを提供したり、サードパーティのバリデーションライブラリを用いるなどして、自身の持つデータの内容が正しいことを保証することができます。バリデーションはさておき、ハッシュテーブルを持ち込み、MessageConverterの要件に合わせていじくるよりも、業務的な処理に使用している中間層のオブジェクトを直接扱うほうが単純に楽です。して直接オブジェクトを使用して動かすためには、カスタムのメッセージコンバータを作成し、SpringのJMSインフラにプラグインする必要があります。カスタムコンバータの使用SpringのMessageConverterインターフェースは非常に単純です。以下に示すように、二つのメソッドを持ちます。message);}メッセージの変換に失敗した場合、MessageConversionExceptionが投げられます。我々は、クライアントから中間層に対し取引の開始をリクエストするメッセージを送信するため、カスタムのメッセージコンバータを作成します。TradeRequestクラスは、取引の開始に際してユーザが入力した情報を収集し、またバリデーションを行うメソッドを持ちます。タイプ、アカウント名、アクション(買い/売り)、リクエストID、ユーザ名です。JMSのMapMessageに単純に追加していくだけのものです。クライアントにおける"ToMessage"メソッドの実装を以下に示します。shown)}"FromMessage"メソッドの実装は、TradeRequestオブジェクトを作り、単純にメッセージから取り出した値を使用してそのプロパティにセットするだけです。詳細はコードを見てください。あなたがデータのマーシャル/アンマーシャルにプロパティを使用するなら、マーシャル時におけるこれらのプロパティの呼び出しが副作用を伴わないことを確認するのを忘れないでください。クライアントから中間層にデータを送信するには、前出のJMSインフラをちょうど鏡に映したようなイメージを作成する必要があります。JmsTemplateはクライアント側で、SimpleMessageListenerContainerは中間層側で使用します。handle(TradeRequest)"を持ちます。クライアント側の設定は以下のようになります。</property></object>テンプレートを利用してハードコードされたクライアントは以下のようになります。jmsTemplate.ConvertAndSend(tradeRequest);}クライアントにおける、メッセージ送信のシーケンス図を以下に示します。中間層の設定と、POJOメッセージハンドラの単純な実装は以下のようになります。}}このアプローチの利点は、クライアントと中間層が本質的にクラスを"共有"できることです。この場合はTradeRequestクラスであり、データと機能の両方を持ちます。クラスを共有することの欠点の一つは、大きなプロジェクトでは特に、ビジネスオブジェクトとコンバータを作成する手間が二重になることです。層の間でやり取りされるデータが比較的安定しているなら、こうした手間は一度きりのコストだと考えられます。開発が活発な間は一般的なことですが、もしやり取りされるデータが週ごと、日ごとに元から変わってしまう場合には、とても面倒なタスクと成り得ます。これらの問題に対処する効率のよい方法は、複数のメッセージタイプを処理できる単一の万能MessageConverterを作成すること、そしてビジネスオブジェクトをJavaで一度だけ書き、ソースコード変換ツールを使用して同等のC#コードを手に入れることです。次の節では、このアプローチについてさらに詳しく論じます。汎用的なメッセージコンバータTradeRequestConverterのコードで前に見たような実装は、手作業でコーディングすべきではありません。解決策としては、コード生成かリフレクションを代わりに使用することです。サンプルコードには、'XStream'に着想を得たリフレクションベースのコンバータであるRefrectionMessageConverterが含まれており、広範囲のオブジェクトを変換することができます。このコンバータは以下のような機能と制限を持ちます。全てのフィールドメンバは、リフレクション経由でその値がマーシャルされます。プロパティのsetter/getterが持つかもしれない副作用を避けるためにこうした選択がなされました。(WCFのDataContract/DataMemberアトリビュートと同様の、どのフィールドが包含/除外されるかを制御するための外部設定、もしくはアトリビュート/アノテーションのサポートを追加することは、優れた拡張と言えるでしょう。)サポートされているフィールド型は、プリミティブ型(int、stringなど)、Date、Timestamp、プリミティブ型で構成されたオブジェクト、ハッシュマップ、オブジェクトの(総称でない)コレクションです。循環参照は検出されます。MapMessageとして表現されます。これにより、このコンバータを使用していない他のプロセスがJMSメッセージのやり取りに参加することが容易になります。JMSプロバイダは、コレクションクラスの変換のため、入れ子のマップメッセージをサポートしている必要があります。任意のオブジェクト型に対する追加のコンバータを登録することができます。コンバータが、コンバートされる先の型を知る必要がないため、.NET/Java間の結合度が疎になります。型の識別子はメッセージ内に保持されており、何という型のオブジェクトを生成すべきかを表しています。どちらの側でも、型の識別子は特定のデータ型からは独立しています。全てのビジネスオブジェクトが、名前空間/パッケージの違い以外全て同じ名前であるという場合に、最小限の設定で済むため便利です。そのコンバータは現在も作成が進行中だとみなされており、Spring.NETウェブサイトから利用できるようになるべく改善が行われています。その他の、単一の万能MessageConverterというアプローチで代わりになるものとしては、既存のマーシャリング技術に面倒ごとを委譲するなどがあります。XML/オブジェクトコンバータに委譲し、XML文字列をJMSメッセージに載せて送信する事ができます。Format(POF)を(同社の製品である)Coherenceの一部として提供しており、同じ目的に利用できます。TradeRequestのレスポンスとしてTradeオブジェクトをクライアントに送る際RefrectionMessageConverterを使用しています。Portfolioオブジェクトをレスポンスとして受信するというものもあります。コンバータに関する設定は以下の通りです。--></object>上で使用されている、TypeMapperの単純なスタイルのほうの設定は、マーシャリングの際メッセージ内に含められた、完全修飾型名の最後の部分を型の識別子として使用します。DefaultNamespaceとDefaultAssemblyNameプロパティは、アンマーシャリングの際に完全修飾型名を構築するのに使用されます。Javaの側において型マッパーの定義に相当する部分は以下に示すとおりです。--></bean>(コメントアウトされている)IdTypeMapping/IdClassMappingプロパティは、完全なクラス名の使用を避けるためにはどうしたらよいか、型を指定するために任意の識別子を使用するにはどうしたらよいか、を表しています。Converter(JLCA)を使用してJavaクラスをC#7のものに自動的に変換する、というものがあります。一度きりの"翻訳を意図しており、自動化されたビルドプロセスに取込、Javaと.NET間でビジネスオブジェクトを同期するのに使用できます。実際ビジネスオブジェクトは、データアクセスやWebプログラミングなど手作業による修正なしには正しく変換するのが困難なテクノロジ固有のAPIを含まないため、この変換ツールにとって非常に良い候補者です。JLCAには短所もあります。手作業による介入なしにJavaへと変換できる複雑なC#クラスを書くことができるにもかかわらず、様々な制限や奇妙な動作が存在します。目だっておかしいのは、JavaBeanのget/setメソッドが.NETプロパティに変換されるのは良いとして、メソッド名が小文字のままになってしまう点です。他の制限としてはアノテーションはアトリビュートに変換されない、ジェネリクスについてのサポートがない、などです。名前空間がJavaのパッケージ名のまま残ってしまうのは、単純な正規表現を用いて後処理を行えば簡単に修正できます。C#実装を作成します。java.util.SetのC#版などです。あなたが自身のプロジェクトでこのテクノロジーをどこまで使用できるかは、少し検証作業を行ってみてください。Sethのブログ8に、このコンバータの機能をまとめた"カンニングペーパー"があります。最後に、JLCAに関するちょっとした情報を一つ。Companionという翻訳ルール9を変更、または追加できる製品も販売しています。この例では、Javaクラスに対してJLCAを動作させるのは非常にうまく行きます。.NETソリューション内で"Bo"ディレクトリと"Jlca"ディレクトリをインクルード/エクスクルードすることにより、手作業で記述したC#のビジネスオブジェクトと、JLCAが生成したそれは相互に切り替えることができます。TradeRequestクラス内のバリデーションメソッドは見て/いじってみてください。単純な条件分岐のロジックとコレクションクラスの操作を使用しています。Javaビジネスオブジェクトに対してJLCAを走らせ、パッケージ名を正しく.NET名前空間に変更する、antスクリプトもサンプルコードに含まれています。以下に示すのは、いくつか市場データを受信し、TradeRequestとPortfolioRequestを送信した直後の、クライアントのスクリーンショットです。結論もしあなたが既にメッセージングを行っているか、非同期のコミュニケーションやパブリッシュ/サブスクライブ型配信などのメッセージング機能を必要としているなら、SpringのJMSサポートをJavaと.NETの双方で利用することは、相互運用ソリューションへの非常にパワフルな第一歩と成り得ます。Spring(を使用したメッセージング)は、JMSのプロデューサとコンシューマの間の互換性を維持するための規約という点からはあまりがっちりしたものではありませんが、あなたが考え出した規約を取り入れるためのシンプルな拡張ポイントであるMessageConverterを提供します。コンバータとそれに関連したオブジェクトの洗練度が、あなたのアプリケーションの複雑さを左右します。RefrectionMessageConverterは、あなた自身が簡単に実験を行うための土台として使用できます。possible)"。私はこの言葉が、.NET/Javaが混在した環境におけるSpringのJMSサポートについても当てはまると良いと思っています。二つの世界で同じプログラミングモデルとベストプラクティスを簡単に共有できるからです。この記事で使用したソースコードはこちら(zip)からダウンロードできます。