DelphiでSOAPサービスを作成する


SOAP というのは、 Simple Object Access Protocol という新しい通信規約みたいなものですが、今まで分散型のオブジェクトを扱う場合は、DCOMやCOM+、或いはCORBAなどが使用されていました。SOAP はそれらに相当する、そしてプラットフォームに依存しない新しい技術だと思えば良いでしょう。ただ、ここでは SOAP そのものについて詳しくは説明しません。他のさらに詳細なサイトや書籍を参考にしてください。

で、そのサイトや書籍になかなか書かれていない、Delphi で SOAP を使う方法、というのを、流れだけざっとここに書いてみます。これは私自身のメモのような意味も含んでますので(笑)

ここでは、Delphi 6 Enterprise 版 で SOAP を利用する方法を説明します。その他(それ以下?)のバージョンを使用する場合のやり方も、後ほど触れます。

Delphi 6 Enterprise(以降、単に Delphi と呼びます)では、標準で SOAP をサポートしていますので、開発者が特に難しいコードを書く必要はありません。ウィザード形式で、ほんの数ステップで SOAP サーバ、及び SOAP クライアントが作成できてしまいます。その手順を紹介します。

SOAPサーバの作成

メインメニューから [ファイル] → [新規作成] → [その他] で新規作成ダイアログを開いて [WebServices]タブから「SOAPサーバアプリケーション」を選択します。



次に 「SOAPサーバの新規作成」ダイアログが表示されたら、任意の形式を選択して[OK]で完了します。通常は「ISAPI/NSAPI DLL」を選択します。これは、ISAPI、NSAPI DLLであれば、後でデバッグしやすいから、という理由もあります。CGI実行形式、Win-CGI実行形式などにすると、デバッグが多少面倒になります。もし、後で実行形式などにする場合でも、ISAPI DLLで作成しておいて、それをリポジトリに追加するなり、新規プロジェクトに追加するなどして他の形式に変換することは可能です。このあたりは Delphi ヘルプにも記述がありますので、参考にしてください。



この後、インタフェイスも作成するかたずねてきますので、既にインタフェイスが作成してある場合を除いて、普通は「はい」を選択します。すると「Webサービスの新規追加」ダイアログが表示されますので、適当なサービス名を入力して「OK」を押します。「コード生成」の設定は、通常はそのままで良いです。この詳細についても Delphi ヘルプで確認してください。

これで、メインのWebモジュール(フォーム)と「〜Impl.pas」と「〜Intf.pas」という3つのユニットができます。Webモジュールには、HTTPSoapDispatcherコンポーネント、HTTPSoapPascalInvokerコンポーネント、及び WSDLHTMLPublishコンポーネントの3つが最初から貼り付いています。基本的にこれらはそのままいじる必要はありません。それぞれの役割については、VCLのヘルプを見てください(Delphi のヘルプは、結構詳しく書かれているので、ヘルプを読むだけでも勉強になります。たまにヘンな誤記もありますが)。



では、それぞれのユニットを記述していきます。

「何とかIntf.pas」というユニットは、クラスのインタフェイス部分のみの定義を書くユニットです。ここに、定義したいメソッドを書きます。メソッドは全て stdcall 属性にしておくと良いでしょう。それ以外の書き方は、普通のクラスを定義するのと同様に記述できます。

引数や戻り値の型ですが、本来、インタフェイスでは、SOAP の場合はXML準拠(WSDL?)の型にあわせた宣言をする必要があります。が、ここは、Webモジュールに貼り付いている HTTPSoapPascalInvoker コンポーネントが、自動的にXMLとPascalの相互変換を行ってくれるので、ここで定義するメソッドの引数や戻り値も、そのまま Pascal の型が使用できちゃいます。便利ですね。

あと、自動生成されたユニットには記述されていませんが、必要に応じてコンストラクタとデストラクタも記述できます。SOAP のメソッドが呼ばれる前と呼ばれた後に何か処理をかけたい場合は、これらをオーバーライドして処理が書けます。

type

  { TSoapSample }

 
TSoapSample = class(TInvokableClass, ISoapSample)
  public
        constructor Create; override;
    destructor Destroy; override;
  end;

 

オーバーライドするときは、中に inherited を入れておきましょう。

次に、「何とかImpl.pas」ですが、これは、メソッドの実装を書くユニットです。上で書いたインタフェイスを持つクラスとして、ここも普通のクラスを記述するように記述できます。


ここまでで、コンパイル(Ctrl + F9)すると、プロジェクト名.dll (CGI実行形式などにした場合は .exe )ができるので、これを Webサーバ(IIS)の実行権のあるディレクトリに配置します。IISでは、デフォルトで、C:\Inetpub\Scripts フォルダは実行権が割り当ててあるので、ここに置いても良いし、新たに仮想ディレクトリを作成して、そこに実行権を割り当てても良いです。

早速、Webブラウザで、新しく作成、配置したモジュールにアクセスしてみます。Webサーバの仮想ディレクトリ名が「Scripts」で、作成したモジュールが「sample.dll」とすると、次のような指定でアクセスできます。

  http://localhost/scripts/sample.dll

これで「(モジュール名) - サービス情報」というページが表示されて、先ほど作成したメソッドの一覧が表示されたら、OKです。これで、このモジュールはSOAPサーバとして機能するようになりました。

Delphi 以外の環境でこのモジュールを利用するには、WSDLファイルというものが必要になりますが、これは上記モジュールが自動生成します。上記で表示されたページに [WSDL] というリンクがあります。これで移動すると、そのモジュールで提供されるサービスのWSDLのコードが表示されるようになっています。このURLを、そのままWSDLのアドレスとして利用することができるのです。これがファイルとして必要なら、表示されたページをソース表示してファイル保存(拡張子は .WSDL)して使用します。

【 参考 】 Delphi ヘルプ → インターネットアプリケーションの開発

 

SOAP クライアントの作成

Delphi では、任意のアプリケーションやモジュールをSOAPクライアントにすることができます。既存のプロジェクトで作成されたものを、SOAPクライアントとして機能させたい場合は、まずそのプロジェクトを立ち上げてください。新しく作成する場合は、適当な形式を選んで新規プロジェクトを作成します。テストをするのであれば、普通のアプリケーションを作成するのが早いです。

プロジェクトが立ち上がったら、メインメニューから [ファイル] → [新規作成] → [その他] で新規作成ダイアログを開き [WebServices] タブから「WSDLインポート」を選択します。

「WSDLインポートウィザード」で、利用したい WSDLファイルのアドレス(URL)を指定して、ウィザードの指示に従って完了します。このWSDLのアドレスは、サーバモジュールが Delphi で作成されている場合、モジュール名の後に /wsdl/(インタフェイス名) と指定することもできます。

例えば、上で作成したモジュールのインタフェイス名が「ISample」としたら、次のような指定が出来ます。

  http://localhost/scripts/sample.dll/wsdl/ISample

実は、こうしてできるインタフェイスのユニットは、サーバを作成するときにつくった「何とかIntf.pas」と同様の内容が書かれています。ですので、動かしたいSOAPサーバが Delphi で作成されている場合は、WSDLからインポートするまでもなく、上で作成した「何とかIntf.pas」をプロジェクトに加えて、そのまま利用できます。ただ、クライアントには HTTPRIO コンポーネントを使用して、そのインタフェイスを得る処理を書く必要があるので、その作業を簡略したい場合は、あえてWSDLインポートを行って、その関数を自動生成するというのも手です。

インポートが完了すると、新しくWSDLから読み込んだインタフェイスが書かれたユニットができるので、それを、実際に利用したい既存のユニットの uses 節に加えてください。

WSDLインポートによって作成されたユニットには、 Get(何とか) というグローバルな関数が宣言されています(インタフェイス名が「ISample」の場合は「GetISample」)。これが、SOAPのクラスのインタフェイスを返す関数なので、SOAPを使用したい場所で、この関数を呼んでインタフェイスを取得します。以下は、その例です。

var
  SIF: ISample;
begin

  // 変数 SIF に ISample を割り当てる
  SIF:= GetISample;

  // ISample に宣言されているメソッドが呼び出せる
  SIF.SoapMethod;

     :
     :

end;


これで、普通のクラスをインスタンス化したのと同じ状態となり、そのメソッドが利用できるようになります。


【 参考 】 Delphi ヘルプ → インターネットアプリケーションの開発


Delphi 6 Professional 、Delphi 5 などで SOAP サービスを作る

Delphi 6 Enterprise なら、上記のように、非常に簡単にSOAPサービスが構築できます。ただ、他のバージョンの Delphi でも、SOAP を作って作れないことはありません。 Delphi 6 Enterprise は非常に高価ですから(定価36万円くらい)、経済的にやろうという場合は、Professional でゴリゴリ作ってみるのも手です。ただ、実開発にかかる工数とメンテの手間を考慮した場合にどちらがお得か、ということは、計算しておいても良いでしょうね。

では、簡単にその手順を。

Delphi 6 Pro や Delphi 5 などでは、SOAP は基本的にサポートしていません。そこで、Microsoft から提供されている 「SOAP Toolkit」を利用します。これは、COMオブジェクト(ActiveXなど)を、そのままSOAPとして利用できるようにするツールです。COMならば、Delphi 6 Pro などでも作れますね。

とりあえず、 [ ここ ] から、SOAP Tool kit をダウンロードします。もちろん無料。あと、XMLをサポートするための XMLパーサも必要ですので、それは [ ここ ] からダウンロードします。ダウンロードしたら、それぞれマシンにインストールしてください。

では、SOAPサーバとしての COM オブジェクトを作成します。Delphi でCOM を作るやり方はいろいろあります。 [新規作成] で普通のアプリケーションやActiveXライブラリなどを作成して、後から「オートメーションオブジェクト」などを追加しても良いし、[新規作成]→[その他]→「ActiveX」→「トランザクションオブジェクト」を選択すると、最初から COM+ 対応のモジュールが作成できるので、これを作成しても良いです。このあたりもヘルプに詳しく書かれています( COM オブジェクトに関する記載を参照 )。

できた COM は、レジストリに登録します。 Delphi の場合は、メインメニューの [実行] → [ActiveXサーバの登録] から登録することもできます。そうでない場合は、コマンドプロンプト(DOS窓)を開いて、

モジュールがDLL形式なら、

  regsvr32 (モジュール名).dll

と打ちます。

EXE形式の場合は、

  (モジュール名).exe /RegServer

とすることで登録できます。

Windows2000 の場合は、[コントロールパネル]→[管理ツール]→[コンポーネントサービス]に新規アプリケーションを作成して、そこに登録することもできます。この方法で登録された COM オブジェクトは COM+ として機能するようになります。

登録が済んだら、SOAP Toolkit の「WSDL Generator」で、COMオブジェクトからWSDLファイルを生成します。Windowsのメイン画面から [スタート] → [プログラム] → [Microsoft Soap Toolkit] → [WSDL Generator] を起動して、ウィザードの指示に従ってWSDLファイルの作成を完了します。WSDLファイルの作成先は、Webサーバの仮想ディレクトリのどこかにすると良いでしょう。これによって、そのWSDLファイルのアドレスを指定することで、COMオブジェクトをSOAPとしてリモートで利用できるようになります。

 

次に、SOAPクライアントを作成します。

SOAPクライアントも、既存のプロジェクトを開くか、新しくプロジェクトを作成するかのいずれでも良いです。立ち上がったら、「Microsoft XML v3.0」と「Microsoft Soap Type Library」のタイプライブラリを取り込みます。 [プロジェクト] → [タイプライブラリの取り込み] → (上記のオブジェクトを選択)→ 「ユニットの作成」で、タイプライブラリのユニットが作成され、プロジェクトに追加されます。

2つの「何とか_TLB.pas」ファイルができるので、これをSOAPメソッドを呼び出したいユニットの uses 節に加えます。これで、SOAPクライアントとしての実装ができるようになります。

ところが、Delphi 6 の場合、何故かこのままだとコンパイルが通りません。なので、何とか_TLB.pas の内容でエラーとなっている部分を全て除去して使用するか、もしくは、このユニットをプロジェクトから除外して、Co〜.Create を使用しないで、CrealeOleObject でこのインタフェイスを作成するなどの手段をとる必要があります。その場合でも、TLB の中に宣言されているメソッドは全て利用できるはずですので、何とかTLB.pas を参考にしつつコーディングすれば良いです。だた、これは少々面倒くさいですね。

SOAPのメソッドの呼び出し方は、次の例のようにします。

var
  SC: Variant;
begin

  // オブジェクトの生成
  SC:= CoSoapClient.Create;

  // SOAPインタフェイスの取得
  SC.MsSoapInit('http://localhost/scripts/sample.wsdl', // WSDLファイルのアドレス
                'Sample',                               // SOAPオブジェクト名
                'SampleSoapPort');                      // SOAP Port名

  // sample.wsdl に宣言されているメソッドが呼び出せる
  SC.SoapMethod;

end;

MsSoapInit の第一引数は、WSDLファイルのアドレスです。SOAP Toolkit で作成したWSDLファイルの場所をURLで指定します。第二引数は、SOAPのオブジェクト名(サービス名)です。SOAP Toolkit で作成する際に、一番最初に設定する名前になります。第三引数は、SOAPのポート名です。これは、普通は “(SOAPオブジェクト名)SoapPort” となっています。

上記のようにオブジェクトを割り当てることで、Variant型の変数を、SOAPのインタフェイスとして利用できるようになります。

ただ、この方法だと、Delphi の様々なサポート機能が利用できません(オブジェクトの後に"."を打ってもメンバが表示されないとか、メソッドの引数リストが表示されないなど)ので、コーディングにはいろいろと気を使う必要が出てきます。

 

やはり、Delphi で SOAP サービスを本格的に作成するなら、私は Delphi 6 Enterprise の利用をお勧めします。SOAP のサポートは Delphi 6 の目玉機能の一つでもありますからね。


[ Delphi へ戻る ]