IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  SOA and Web services  >

連載「作る!SOAアプリケーション」:第3回 インターフェースと記述言語

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません


レベル: 初級

米持 幸寿, テクノロジー・エバンジェリスト, IBM

2005年 9月 30日

今回はインターフェースと記述言語について詳しく解説し、SOA的ソフトウェア構造で言う「インターフェース」がどういうものか、しっかりと理解していただきます。プログラムコードは主にJavaを使って記述しますが、別の言語でも同じと考えてください。

さまざまなインターフェース

インターフェースという言葉は、SOAよりもさらに曖昧(あいまい)な単語です。
インターフェース(interface)という英単語は「境界面」というような意味です。たとえば、宇宙船が大気圏の再突入する際の境界面というのがあります。(地上から400000フィートのところだそうです)これを再突入インターフェースと言うそうです。また、どこかの会社の担当者が、顧客との窓口になるとき、「インターフェースを勤める」という言い方をします。

コンピューター用語でもインターフェースは「境界面」という意味でさまざまな場面で使われます。たとえば「ユーザー・インターフェース」。コンピューターとユーザー(通常は人類)がデータ交換を行うための境界面のことをさしていて、キーボード、マウス、マイクなどの入力、パソコン画面に表示される図形、記号、文字、パソコンから発せられる音はパソコン側から人類に対する出力がユーザー・インターフェースです。EAIやEDIシステム上で、データ交換を行う部分のことをインターフェースと呼ぶこともあります。

SOAでのインターフェースは、基本的にソフトウェア対ソフトウェアの境界面です。二つのソフトウェアを結合するときの結合面です。そして、SOA的ソフトウェア構造のインターフェースはさらに少し制限がかかります。一般的に「標準に則ったインターフェース」という言い方をします。標準に則ったインターフェースとはなんでしょうか?

では、ソフトウェアの結合にまつわる境界面の例をいくつか挙げ、どのへんからがSOA的ソフトウェア構造のインターフェースに合致するものか考えて見ましょう。

モデリング言語における「インターフェース」

モデリング言語UMLには、インターフェースの記述方法が決められています。たとえば、クラス図などには、丸と線を組み合わせた記号でインターフェースを示します。

UMLでは、インターフェースを記述する場合、クラス図上でステレオタイプ <<interface>> を使います。たとえば、書籍検索インターフェースは、図1のように記述することができます。


図1.書籍検索のインターフェース定義
図1.書籍検索のインターフェース定義

UMLでは、インターフェース定義に詳細な戻り値や引数の情報をあまり定義しません。また、内部で使われるデータの型などは、別途クラス図などで準備することになります。

UML 2.0では、コンポーネント図においてある定義のインターフェースへアクセスすることを「要求インターフェース」として定義することができます。

プログラミング言語における「interface」

Javaには「interface」というそのものを示す機能があります。interfaceは、Javaのオブジェクトが持つメソッドの型定義を行うものです。

Javaのinterfaceの使い方は大まかに二つあります。ひとつは、多態性(ポリモーフィズム)を使う場合です。様々なクラスに同じメソッドのセットを準備することで、ひとつのコードで扱うことができるようにします。もうひとつは多重インターフェースです。ひとつのクラスに複数の機能を同時に持たせることにより、コードの整理をします。

上記の書籍検索インターフェースをJavaのinterfaceで記述すると、ソースコード1のようになります。ただし、こちらはデータの型までを定義しています。(本来は、BookInfoクラスにはアクセサを準備するべきですが、割愛)


ソースコード1.Javaによるインターフェース記述
                
public class BookInfo {
public String isbn;
public String title;
public String author;
public String company;
public String abstraction;
public String price;
}

public interface BookSearcher {
public BookInfo[] searchBooksByKeyword(
String keyword,
boolean title,
boolean author);
public BookInfo getBookByISBN(
String isbn);
}

分散プログラミングにおけるインターフェース

CORBAなどの分散オブジェクト技術では、「Interface Definition Language(IDL)」というのを使ってインターフェースを定義します。ちょっと古い情報なので、例は割愛しますが、Javaのinterfaceと似たような記述方法で記述することができます。

Webサービスにおけるインターフェース

Webサービスには現状ではinterfaceという単語は出てきません。しかし、新しい仕様には登場します。WSDL 1.1で「portType」と呼ばれていたものがWSDL 2.0において「interface」と改名されました。

WSDL 1.1で、上記のインターフェースを記述すると、ソースコード2の様になります。(インターフェース部分のみ抜粋)


ソースコード2.WSDLによるインターフェース記述
                
<wsdl:types>
<schema targetNamespace="http://yone.com" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:impl=
"http://yone.com" xmlns:intf="http://yone.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<element name="searchBooksByKeywordResponse">
<complexType>
<sequence>
<element name="searchBooksByKeywordReturn" nillable="true" type="impl:ArrayOfBookInfo"/>
</sequence>
</complexType>
</element>
<element name="getBookByISBN">
<complexType>
<sequence>
<element name="isbn" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getBookByISBNResponse">
<complexType>
<sequence>
<element name="getBookByISBNReturn" nillable="true" type="impl:BookInfo"/>
</sequence>
</complexType>
</element>
<element name="searchBooksByKeyword">
<complexType>
<sequence>
<element name="keyword" nillable="true" type="xsd:string"/>
<element name="title" nillable="true" type="xsd:string"/>
<element name="author" type="xsd:boolean"/>
</sequence>
</complexType>
</element>
<complexType name="BookInfo">
<sequence>
<element name="abstraction" nillable="true" type="xsd:string"/>
<element name="author" nillable="true" type="xsd:string"/>
<element name="company" nillable="true" type="xsd:string"/>
<element name="isbn" nillable="true" type="xsd:string"/>
<element name="price" nillable="true" type="xsd:string"/>
<element name="title" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="ArrayOfBookInfo">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="BookInfo" nillable="true" type="impl:BookInfo"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getBookByISBNResponse">
<wsdl:part element="impl:getBookByISBNResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="searchBooksByKeywordRequest">
<wsdl:part element="impl:searchBooksByKeyword" name="parameters"/>
</wsdl:message>
<wsdl:message name="getBookByISBNRequest">
<wsdl:part element="impl:getBookByISBN" name="parameters"/>
</wsdl:message>
<wsdl:message name="searchBooksByKeywordResponse">
<wsdl:part element="impl:searchBooksByKeywordResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="BookSearcher">
<wsdl:operation name="searchBooksByKeyword">
<wsdl:input message="impl:searchBooksByKeywordRequest" name="searchBooksByKeywordRequest"/>
<wsdl:output message="impl:searchBooksByKeywordResponse" name="searchBooksByKeywordResponse"/>
</wsdl:operation>
<wsdl:operation name="getBookByISBN">
<wsdl:input message="impl:getBookByISBNRequest" name="getBookByISBNRequest"/>
<wsdl:output message="impl:getBookByISBNResponse" name="getBookByISBNResponse"/>
</wsdl:operation>
</wsdl:portType>




上に戻る


プログラム結合に対するプログラミング

EDIなどの業界標準

EDIFACT、RosettaNet、ebXMLといったEDIの業界標準、あるいは、OASISを初めとする世界中に数多くある標準化団体が、XMLなどを使った企業間取引のデータフォーマットを策定しています。これは、ある種のインターフェースと呼ぶことができます。
業界標準なので、「標準に則ったインターフェース」と呼ぶ人もいます。
SOAではこれの解釈は様々ですが、ソフトウェア結合の観点から行くと筆者は違うと思います。なぜなら、これらのフォーマットの多くは、結合技術に使えません。こういった団体で作られるXML標準は、データ型、引数、戻り値、名前などで構成されているわけではなく、交換フォーマットを決めているのです。インターフェースよりもプロトコルに近いものです。EDI業界標準は「インターフェースを取り決めている」のではなく、「プロトコルを決めている」のです。
決められているのは、データ交換のためのフォーマットで、しかも多くの場合記述言語を使いません。このため、EDI標準を利用するためには、そのフォーマットにデータを整形してネットワークに送出するためのプログラムコードをプログラマが記述する必要があります。
これは、旧来のメッセージ基盤を利用するEAIシステムでも同じことが起こりえます。

原始的なソフトウェア境界面「サブルーチン」

最も原始的なソフトウェア境界面はサブルーチンでしょう。しかし、サブルーチンは、命令のジャンプが起こるだけで境界面がはっきりしません。受け渡しするデータは、メモリー上にあらかじめ準備してレジスターなどを使ってポインターを渡すのが一般的でしょう。
このような場合、受け渡しするデータの型は、アセンブラーやコンパイラーはまったくといっていいほど処理しません。プログラムロジックそのものがこの準備をする必要があります。これはある意味マーシャリング処理であり、インターフェースへのプログラミングができないわけです。
その証拠にサブルーチンには、UML、Java、WSDLに見られるような「インターフェース記述」の機能がありません。サブルーチンは、インターフェースを明確に記述することができません。このため、サブルーチンをコールするためには、そのためのデータをサブルーチンが利用する形態で、メモリー上に準備するコードを記述する必要があります。

データの整形、送受信、分解処理

SOAのシステムは、一般的に分散されることを想定しています。分散システムを作る場合に、ソフトウェアがやらなければならないことは、主に以下のことです。

  1. 相手に渡すためのデータを準備する
    例:呼び出し機能を示すデータ、処理データ、コンテキストデータなど
  2. 相手に渡すためのデータを、決められた形式に整形する
    例:単なるテキスト、全銀フォーマット、特殊なバイナリー、CSV型、XMLなど
  3. 整形したデータを、決められた方法で呼び出し先へ渡し、受け取る
    例:メモリーポインター、ネットワークパイプ、IPソケット、FTP、HTTPなど
  4. 受け取ったデータを、決められた形式に基づいて分解する
  5. 分解したデータを処理する

ここで、2~3の処理は、プロトコルごとに違う処理を行うことになります。

ユーザーが持っているデータを、決められた形式に整形し、並べることをマーシャリング、あるいはシリアライズといいます。逆の分解処理をアンマーシャリングあるいはデ・シリアライズといいます。マーシャリング(シリアライズ)、アンマーシャリング(デ・シリアライズ)は、プロトコル処理の一部です。これらはSOAでいう「インターフェース」に含みません。なぜなら、マーシャリングをアクセスコードの一部に入れてしまうと、SOAが目指す「プロトコル非依存」という性質を達成できないからです。

MQ、TCPIP、ネットワークパイプへのアクセスはエンドポイント処理となります。「インターフェースに対して」ではなく、「プロトコルに対して」プログラミングしていることになります。

SOAの「インターフェースを介してアクセスする」というのは、操作名、引数、戻り値、データ型に対してのプログラミングをすることにあります。決して、それらをマーシャリングし、プロトコルAPIを使って送出したり受信したりする部分のことは含みません。

これらを整理すると、先ほどの1から5までの処理は、次のように言い換えることができます。

  1. インターフェース呼び出し処理
  2. リクエストのマーシャリング
  3. エンドポイント呼び出し
  4. レスポンスのアンマーシャリング
  5. インターフェースのレスポンス処理

WSDLの中身をご存知の方ですと、ここまでの話で「portType要素」がインターフェースで、bindingおよびserivce要素はプロトコルにあたるのだということがお分かりになると思います。




上に戻る


SOAに都合のよい「インターフェース」とは

SOAでは「インターフェースを介してアクセスする」のがサービスです。そして、プロトコルに依存しないことは重要な要件です。SOAにとって、プログラムが(アン)マーシャリングやエンドポイント処理を行うことは望ましくないわけで、2から4の処理をいかにプログラムに行わせないか、は重要な要点となるわけです。

たとえば、BookSearcherサービスのsearchBooksByKeywordを、引数keywordとして「米持幸寿」、タイトルでの検索はなし、著者名での検索はあり、として呼び出すために、バイナリーフォーマットを使うとして、データを作ってみましょう。

渡すためのデータは、次のようなフォーマットとします。

  • 最初の4バイトがサービスを識別するIDで、BookSearcherは「0000035A」である。
  • 次の1バイトが操作を表し、「01」がsearchBooksByKeywordである。
  • それ以降は、種類1バイト、長さ4バイト、データの順で並ぶ。数値の場合は、長さバイトはなく、Javaの数値バイトと同じ長さである。00=String, 01=boolean, 02=byte, 03=int, 04=long, .....

どのようなデータになるでしょうか。(4バイトおきに区切り、漢字部分はバイナリーだとわかりにくいのでそのまま漢字で表現しています)

0000035A 010008米 持幸寿01 000101

こういったバイナリー形式のデータ構造を「構造化フィールド」と呼びます。

このデータを組み立てるコードをJavaで書くとしたら、こんなコードかもしれません。


ソースコード3.マーシャリングするJavaコード
                
int bytecount = 4+1+1+1+keyword.length()+1+1+1+1;
byte[] buffer = new byte[bytecount];

buffer[0]=0;    // BookSearcher 0000035a
buffer[1]=0;
buffer[2]=0x03;
buffer[3]=0x5a;
buffer[4]=0x01; // searchBookByKeyword
buffer[5]=0x00; // String
buffer[6]=(byte)keyword.length();

byte[] keywordbytes = keyword.getBytes();
for(int i=0; i<keywordbytes.length; i++){
buffer[7+i]=keywordbytes[i];
}

buffer[7+keywordbytes.length]=01;       // boolean
buffer[8+keywordbytes.length]=(byte)(titleflag ? 0x00 : 0x01);

buffer[9+keywordbytes.length]=01;       // boolean
buffer[10+keywordbytes.length]=(byte)(authorflag ? 0x00 : 0x01);

このようなデータを組み立てて送り、分解して処理し、またBookInfo(これもフォーマットを決めておかなければなりません)を作って送り返し、分解すればサービスを呼び出すことは可能でしょう。しかし、これは非常にややこしいプログラミングが必要で、開発コストもメインテナンスコストもかかり、品質にも影響し、あまり良いことがありません。

このような処理をプログラマにプログラミングさせず、自動プログラミングの技術を利用することができます。それは、結合技術を利用することです。SOAでサービスを呼び出す際に、結合技術を使う、と前回の記事に書きました。SOAでは、インターフェースを結合技術にとって都合がよいように作る必要があります。それは、「記述言語で記述可能なインターフェース」です。そして、標準的な(たとえばWSDLのような)記述言語で記述可能なインターフェースが「標準に則ったインターフェース」です。

では、UML、IDL、Java、WSDLなどで定義できるようなインターフェースにアクセスする場合のJavaコードはどうなるでしょうか。記述言語では、インターフェースそのものがプログラムに「見える」ようになります。このことは、マーシャリング処理をプログラムに記述せずにソフトウェアの統合が可能なことを示しています。たとえば、ソースコード4.のようなJavaコードでサービスを呼び出すことができます。


ソースコード4.サービスの呼び出し
                
BookInfo[] results = searchBooksByKeyword(keyword, titleflag, authorflag);

いかがですか?ソースコード3と4はどちらが簡単なコードでしょうか?

SOAの「インターフェースを介してアクセスする」というのはこういうことを示しています。ソフトウェア結合技術を駆使すればソースコード4を実現できます。このようなコンセプトでコンシューマーを作るには結合技術が必要であり、今日のように混在環境が進んだ時代には、Webサービスは大きな武器になることは間違いありません。

マーシャリング方法は、採用する結合技術とプロトコルによって決まります。それらは、インターフェースに対して汎用的に設計されているので、インターフェースを「記述」してあげればソフトウェア結合が可能です。(どのような結合技術があるか、は前回を参照のこと)

IBMでは、SOAのインターフェースをさまざまなプロトコルに対応できるように拡張したWSDLで記述します。WSDLで記述するからといって、SOAP-HTTPで結合するとは限らない、という意味です。Javaバインディング、JMSバインディング、EJBバインディング、SOAP-JMSバインディング、SOAP-HTTPバインディングなどがサポートされています。

IBMでは、さまざまな分散ソフトウェアをSOAに結合するために、多くの製品を提供します。これらの中心となるコンセプトは、すべてのインターフェースに「記述言語で記述可能な」ものに変換し、WSDLを提供することにあります。WSDLが存在するようになることで、分散ソフトウェアがSOAのシステムに結合しやすくなり、柔軟性が増すのです。



著者について

1987年に日本アイ・ビー・エム入社。メインフレームOS、ミドルウェアの障害対応、障害解析ソフトウェアの開発、ワークフローシステム開発、オブジェクト指向開発、Web開発など経験。2000年より、ソフトウェアのテクノロジーエバンジェリストとして活動中。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



はいいいえわからない
 


 


12345
不充分・不完全である大変素晴らしい
 


この記事を共有する

はてなブックマーク はてなブックマーク livedoorクリップ livedoorクリップ del.icio.us del.icio.us Buzzurl(バザール) Buzzurl(バザール) Choix! Choix!
Saafブックマーク Saafブックマーク FC2ブックマーク FC2ブックマーク MM/memo MM/memo ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
CZブックマーク CZブックマーク newsing newsing




上に戻る


    日本IBMについて プライバシー お問い合わせ