‘SOAP’ カテゴリーのアーカイブ

SOAP 結合テスト

このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをFC2ブックマークに追加このエントリをNifty Clipに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをChoixに追加このエントリをnewsingに追加

php-soapを使った、SoapClientと、javaでのSoapServerでの結合テストが行われた。こちらは仕様書通りのSOAPメッセージを出しているから、バッチリだろう。そう思っていた。

すると、まずSOAPのバージョンから違った…。俺が実装してたのは、仕様書に載っていたSOAP1.2で、SoapServerが実装してたのはSOAP1.1だった。いきなり仕様書通りじゃないとは!

しかしこちらはクライアントなので、サーバに合わせなければならない。あれをこうして、それをああして、という話を聞いている間に、仕様書には書かれてないSOAPメッセージになった…。

とりあえず、修正したSOAPメッセージを使ったところ、通信できた。まあ一応よかった〜という話にはなったが、じゃああの仕様書は一体なんだったんだろう…。お客さんから届いた仕様書の通りに作ったのに、違いますって言われても…。違うのは仕様書ってことになるやん。その仕様書はお客さんからもらってるんだけど…。

まずは通信ができることを最優先するみたいだが、SOAP1.2を使う予定だったのに1.1で実装しているSoapServerが他のWebAPIで問題になるんじゃないかとヒヤヒヤしている。まあそれもテストをしていればわかることだが。

ちなみにスタブで使ってたphpのSoapServerでは、オプションでsoap_version => SOAP_1_1にして、クライアントはsoap_version => SOAP_1_2にしても、なぜか通信できてたみたい。柔軟に対応してくれるってことか?


php-soapでわかったこと

このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをFC2ブックマークに追加このエントリをNifty Clipに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをChoixに追加このエントリをnewsingに追加

色々とあって、php-soapやってますが、わかったことがあるので載せときます。
たしか、こんな感じにしたと思う。

◆SOAPメッセージの要素を入れ子にする方法(wsdlなし)

$options = array(
'soap_version' => SOAP_1_2,
'location' => 'http://example.net', // SoapServerのURL
'uri' => 'http://example.net/namespace/', // 名前空間のURL
'trace' => true, // トレースOKにするか否か
'exceptions' => false // SoapFault型の例外をスローするか否か
);
$obj_soap_client = new SoapClient(null, $options);  // wsdlなし、オプションは各自適当にしてネ

$ar_children = array(
new SoapVar($obj_a, SOAP_ENC_OBJECT, null, null, 'child'),
new SoapVar($obj_b, SOAP_ENC_OBJECT, null, null, 'child'),
new SoapVar($obj_c, SOAP_ENC_OBJECT, null, null, 'child'),
);
$obj_parent = new SoapVar($ar_children, SOAP_ENC_OBJECT, null, null, 'parent');
$response = $obj_soap_client->something($obj_parent); // somethingメソッドはSoapServerで定義されてること

◆もっともっと、入れ子にする方法

$ar_children = array(
new SoapVar(3, XSD_INTEGER, null, null, 'number'),
new SoapVar(array(
new SoapVar(170, XSD_INTEGER, null, null, 'height'),
new SoapVar(65, XSD_INTEGER, null, null, 'weight'),
new SoapVar('Aさん', XSD_STRING, null, null, 'name'),
), SOAP_ENC_OBJECT, null, null, 'child'),
new SoapVar(array(
new SoapVar(190, XSD_INTEGER, null, null, 'height'),
new SoapVar(100, XSD_INTEGER, null, null, 'weight'),
new SoapVar('Bさん', XSD_STRING, null, null, 'name'),
), SOAP_ENC_OBJECT, null, null, 'child'),
new SoapVar(array(
new SoapVar(175, XSD_INTEGER, null, null, 'height'),
new SoapVar(80, XSD_INTEGER, null, null, 'weight'),
new SoapVar('Cさん', XSD_STRING, null, null, 'name'),
), SOAP_ENC_OBJECT, null, null, 'child'),
);
$obj_parent = new SoapVar($ar_children, SOAP_ENC_OBJECT, null, null, 'parent');
$response = $obj_soap_client->something($obj_parent); // somethingメソッドはSoapServerで定義されてること

◆SoapServerからの戻り値について
なんと、stdClassで戻ってきやがる!
こちらは完全に連想配列のつもりでいたんで(まあこれは俺の完全な思い込みからだけど)、俺が準備したスタブの値(連想配列)で動いていたほかの人のプログラムにもろに支障が出た。うーん、戻り値を配列にするフラグくらいあるだろうと思ってネットで検索したが、めぼしいものは見つからなかった。一応、SoapClientのコンストラクタのオプションで

$options = array(
'features' => SOAP_SINGLE_ELEMENT_ARRAYS
);

というのがあったが、これはどうやら戻り値が1つの場合でも配列っぽくするよという意味っぽい(あくまでstdClassのメンバ変数でだろうけど)。

仕方がないので、stdClassを配列にキャストした。
その際、戻り値のみを

$response = (array)$response;  // stdClassオブジェクトを配列にキャスト

とした場合、1次元しか配列にキャストされないので、戻り値が多次元の場合、再帰で処理しないといけないことに注意!(再帰のプログラムは先輩が作ってくださった。ありがとうございます!)

php-soapの情報はあんまりなかったので(見つけられなかったので?)、こういうメモが多くの人の役に立つことを祈ります。


Get Adobe Flash playerPlugin by wpburn.com wordpress themes