【Delphi Sample】Delphi と Google App Engine と Thrift と Java その1

【Delphi Sample】Delphi と Google App Engine と Thrift と Java その1

皆さんはサーバーとクライアントの通信にどのような方法を利用していますか?

この記事では、クライアントアプリケーションをDelphi、サーバーアプリケーションをGoogle App Engine (GAE/J)にて実装し、その間の通信には Apache Thriftを利用するサンプルを紹介します。

キーワード

実際のサンプルに入る前に主要なテクノロジーやソフトウエアについて少し触れてみます。

  • Google App Engine
    Google が運営するPaaSです。サーバーのことをほとんど意識することなく、アプリケーション開発に集中できます。制限もありますが、特性を理解して適切に使うことができれば、ほかの環境では簡単に作成することができないアプリケーションを作ることができます。
  • Delphi
    デルファイと読みます。Pascal言語を利用してアプリケーションを作ることができる開発環境です。フレームワークがとても強力で、多様なプラットフォームをサポートしています。GUIアプリケーションを作るうえで、これだけ安定している環境は得難いのではないでしょうか?
  • Thrift
    スリフトと読みます。アプリケーション間で処理の呼び出しをサポートしてくれるフレームワークです。これを利用するとクライアントアプリケーションからサーバーアプリケーションの関数を呼び出すことができます。この類のテクノロジーはいくつも出ていましたが、使い勝手や保守性に優れており、特別な技術が使われているわけでもなくとてもシンプルに作られています。
    そのシンプルさゆえ、いろいろな言語で利用することができます。同じ言語間の通信はもちろん、今回のようにJavaDelphiなど異なる言語間でも通信を行うことができます。

インターフェイスを決める

サーバーとクライアントの間で何かやり取りをするということは、やり取りの方法を決める必要があります。具体的には、データと処理の呼出し口を決めます。

インターフェイスをしっかりと決めておくことで、以下のような利点があります。

  • サーバーとクライアントで分業できる。
  • インターフェイスを見るだけで、アプリケーションの全体像がつかめる。

JSONやXMLを使ってデータのやり取りを行うのがよく使われる方法ですが、インターフェイスを決める主導権はどちらか一方に偏りがちです。サーバー側での変更がクライアント側に伝わらず、いつの間にかデータ構造が変わっていたということもあるのではないでしょうか?

この問題をThriftはインターフェイス記述言語(IDL)というもので解決しています。つまり、インターフェイスそのものをコーディングするという考え方です。コーディングできるということはソースコード管理を行うことができますから、いつの間にか変わってしまったという現象を防ぐことができるのです。

インターフェイス設計

今回は四則演算のサービスを作成します。インターフェイスのコーディングにはIDLを利用します。Thrift専用の言語ですが、覚えることも少ないのでドキュメントを眺めながら進めていけばすぐに慣れると思います。

クラスにメソッドを宣言していくようなつもりで進めていくのがいいでしょう。JSONやXMLでのやり取りではデータが中心となってきますから、アプローチの方法が異なりますね。

ここで行うのはあくまでもインターフェイスの設計・宣言です。実装については誰が行ってくれるかというと、そこはThriftが担ってくれます。つまり、ソースコードはThriftが自動生成してくれるわけです。

calculator.thrift

計算サービスを定義していきます。コメントをつけたので、理解しやすいのではないでしょうか?namespaceを宣言するとグルーピングが行えます。ここではJavaとDelphiでグルーピング方法を変えています。細かく分割するのか、一つにまとめてしまうかは言語の作法に従うのがいいと思います。
また、includeを使って、ほかのIDLファイルを読み込むこともできます。
もう一つ注目してもらいたいのは、exceptionで例外を定義しているということです。今回の四則演算のサービスでは、割り算でゼロ除算を行ったときに例外を送出するよう考えています。言語間で例外をやり取りできるのは表現の幅が広がりますね。

namespace java com.example.thrift
namespace delphi ThriftInterface.Calculator

include "common.thrift"

/** 計算サービス */
service CalculatorService {
    /** 加算 */
    i32 add(1:i32 param1, 2:i32 param2),
    /** 減算 */
    i32 sub(1:i32 param1, 2:i32 param2),
    /** 乗算 */
    i32 mul(1:i32 param1, 2:i32 param2),
    /** 除算 */
    i32 div(1:i32 param1, 2:i32 param2) throws (1: common.TInvalidParameterException error)
}

common.thrift

calculator.thriftで利用した例外はこちらで宣言しています。後でサービスを追加することを想定して、ファイルを分けています。

namespace java com.example.thrift
namespace delphi ThriftInterface.Common

/** パラメータに誤りがあったときの例外 */
exception TInvalidParameterException {
    1: string message
}

ファイルの自動生成

Windowsを利用している人はここから実行ファイルをダウンロードしてください。コマンドラインプログラムなので、適当な場所に配置し、その場所をPathに追加すると使いやすいです。

Macを利用している人はBrewを使って実行ファイルをセットアップしてください。

今回は2つのthriftファイルを作成したので、次のようにコマンドを実行します。common.thriftは参照されているので、初めに実行します。

rmdir /s /q gen-java
rmdir /s /q gen-delphi

thrift --gen java --gen delphi IDL/common.thrift
thrift --gen java --gen delphi IDL/calculator.thrift

コード生成の前にgen-java gen-delphiのフォルダを削除するコマンドを入れておくと、間違いが少なくなりますね。

フォルダ構成

gen-javagen-delphiという二つのフォルダができています。中にはそれぞれJavaのソースファイルとDelphiUnitが生成されているのが分かるでしょうか?
namespaceの宣言によってフォルダ構成やファイルの分かれ方も変わってきます。いろいろと試してみてください。

スポンサーリンク

コメント

このブログの人気の投稿

【KotlinとJava】分解宣言

wxPythonでのモーダルダイアログ作成

【Delphi Sample】並列プログラミング1