PerlとJavaで異言語Webサービス連携 - SOAP/WSDLの光と影 Shibuya Perl Mongers テクニカルトーク #5 株式会社ドリーム・アーツ 広島ラボ 竹迫 良範 <[email protected]> 2004/12/16 1 Perl と Java で異言語 Web サービス連携 はじめに 1. Perl で SOAP::Lite を使う 2. Perl と Java の業務アプリケーション 3. 各種 Adapter の紹介 Apache Axis で Java と連携 2004/12/16 株式会社ドリーム・アーツでの事例紹介 DA::API フレームワーク 4. SOAP, 日本語文字コード WSDL, WSDL2Java, Type Mapping 問題 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 2 1. Perl で SOAP::Lite を使う Shibuya Perl Mongers テクニカルトーク #5 “Lite”な割には「軽く」ない… 2004/12/16 3 SOAP とは? SOAP (Simple Object Access Protocol → SOAP1.2より固有名詞) XMLを利用してRPCやメッセージングの機能を実現するための仕様 軽量で特定のプラットフォームに依存しないのが特徴 SOAPによるRPCは、Webサービスの中核技術 SOAPは、データ構造のみが定義されており、 転送手段としては既存の通信プロトコルを使用(主にHTTP) (例) SOAP メッセージ (XML) リクエスト SOAP over HTTP network クライアント Windows Java (Apache Axis) 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 レスポンス SOAP メッセージ (XML) サーバ Linux mod_perl (SOAP::Lite) Copyright © 2004 DreamArts Corporation. All Rights Reserved. 4 tcpmon で SOAPメッセージをキャプチャ TCPモニタを起動する java org.apache.axis.utils.tcpmon 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 5 Perlクライアントの例 (SOAP::Lite) #!/usr/bin/perl use SOAP::Lite(); my $soap = SOAP::Lite ->uri('urn:DA/API/Tests') ->proxy('http://localhost:8001/service/soap/') ->new; local $@; my $som = eval { $soap->add({ a => 123, b => 456, c => 789, }); }; if ($@) { die $@; } if ($som->fault) { die $som->faultstring; } my $result = $som->result; print "result='$result'\n"; exit(0); 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 6 SOAP::Lite で日本語を扱うと・・・ 日本語を扱うと・・・ なぜか文字化けしてしまうことが 文字化けの原因 Base64 でエンコードされている Devel::Peek::Dump で確認 2004/12/16 SOAP::Lite の typelookup が原因 XML Parser から取り込んだ文字列に UTF8フラグが立っている! ISO-8859-1 → UTF-8 へ自動変換(文字化け) Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 7 SOAP::Lite の typelookup Perl : 型のない言語 _typelookup => { base64 => [10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/}, 'as_base64'], 'int' => [20, sub {$_[0] =~ /^[+-]?(\d+)$/ && $1 <= 2147483648;}, 'as_int'], float => [30, sub {$_[0] =~ /^(-?(?:\d+(?:\.\d*)?|\.\d+|NaN|INF)| ([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)$/}, 'as_float'], string => [40, sub {1}, 'as_string'], 'long' => [25, sub {$_[0] =~ /^[+-]?(\d+)$/ && $1 <= 9223372036854775807;}, 'as_long'], }, 【マルチバイトでもbase64エンコードせず強制的に文字列として返す】 $self->{_typelookup}->{string} = [ 1, sub {1}, 'as_string']; 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 8 通常の回避策(UTF8フラグの除去) 文字列 $_ 中のUTF8フラグを除去する [1] unpack して pack する $_ = pack ( 'C*', unpack ( 'C*', $_ ) ); もっと 効率的 [2] pack 'C0' を使う $_ = pack 'C0A*', $_; from MT/XMLRPCServer.pm at www.movabletype.org. ## The following subroutine strips the UTF8 flag from a string, thus ## forcing it into a series of bytes. "pack 'C0'" is a magic way of ## forcing the following string to be packed as bytes, not as UTF8. 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 9 強硬な回避策(UTF8フラグの除去) XML-Parser にパッチを当てる(荒技) --- XML-Parser-2.34-orig/Expat/Expat.xs Mon Jul 28 23:41:10 2003 +++ XML-Parser-2.34/Expat/Expat.xs Fri Aug 27 08:36:39 2004 @@ -17,6 +17,8 @@ #undef convert +#undef SvUTF8_on + #include "patchlevel.h" #include "encoding.h" # patch –p1 < XML-Parser-2.34-no_utf8.patch → ややこしいことは考えなくて済む! 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 10 2. Perl と Java の業務アプリケーション Shibuya Perl Mongers テクニカルトーク #5 株式会社ドリーム・アーツでの事例紹介 http://www.dreamarts.co.jp/ 2004/12/16 11 株式会社ドリーム・アーツの主力製品 【インスイート エンタープライズ】 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 12 「INSUITE Enterprise」と「ひびき」の位置付け エンドユーザ 外部 内部 EIP : 情 報 ・ 知識ポータル(モバイル対応) (シングル・サイン・オン、 パーソナライズ、 グループ・部門・役職単位のポータル設定、アクティブ・ノーティス(通達機能)・・・etc.) 在庫管理 ニュース クリッピング ポートレット マーケット プレース 人事総務 eラーニング パートナー サイト グループウエア スケジューラ 施設予約 掲示板 ファイル共有Box ToDoリスト ホームページ作成 検索機能 アドレス帳 ワークフロー 高速全文検索エンジン(アクセス・コントロール対応) ユーザ・グループ管理 セキュリティ 【ひびき】は、INSUITE®のポータル機能はじめ全文検索、ユーザ管理、セキュリティ機能を有効利用 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 13 「INSUITE Enterprise」と「ひびき」の比較 INSUITE Enterpirse カテゴリ EIP, グループウェア 開発言語 Perl, C 開発環境 vi 開発者 oldtype 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 ひびき 業務アプリ 異言語連携 (SOAP) PROJECT SALES Java Eclipse 異文化交流 (相互理解) newtype Copyright © 2004 DreamArts Corporation. All Rights Reserved. 14 4. DA::API フレームワーク Shibuya Perl Mongers テクニカルトーク #5 各種 Adapter の紹介 2004/12/16 15 DA::API フレームワークの構成図 Web I/F layer POST-XML Adapter sudo require user & group Shibuya Perl Mongers テクニカルトーク #5 SOAP Adapter Authz layer DA::Adapter::BasicAuth スケジュール 登録・更新 削除・検索 ユーザ・グループ 情報の参照 : Authen layer DA::Adapter::CreateSession Command Adapter DA::API modules Web I/F の実装 2004/12/16 Adaptation layer DA::Adapter DA::Adapter::API HTML::Template cgi-bin Web Browser Implementation layer cmd tools SOAP Client HTTP Client 実装(メンテナンス)する部分はここだけ 各Adapterがインタフェースを自動生成 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 16 DA::API::Tests モジュールの書き方 インタフェースの実装(例) # ▼ 足し算 #-------------------------------------------------------------------------sub add { my $get = new DA::Adapter::API(@_); # my $session = $get->session(); my $a = $get->require("a" => t_("引数 a (必須項目)"), my $b = $get->require("b" => t_("引数 b (必須項目)"), my $c = $get->options("c" => t_("引数 c (省略可能)"), my $d = $get->options("d" => t_("引数 d (省略可能)"), $get->summary(t_("足し算(a+b+c+d)の結果を返す")); $get->end(); 入力パラメータの定義 (決まった書き方) "int"); "int"); "int"); "int"); if (!defined $c) { $c = 0; }; if (!defined $d) { $d = 0; }; my $result = $a + $b + $c + $d; return $result; } HTTP/POST-XML Adapter が インタフェースの入力仕様を元に サンプルHTMLフォームを自動生成 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 17 DA::Adapter 機能説明 (1) コアモジュール DA::Adapter::API DA::Adapter::Command HTTP/POST-XML の機能を提供するモジュール HTMLフォームの自動生成、APIの自動リストアップ機能を持つ DA::Adapter::SOAP 2004/12/16 api コマンドの機能を提供するモジュール 自動 sudo 機能を持つ(wwwユーザで実行) DA::Adapter::CGI DA::APIを利用するためのコアモジュール HTTP/SOAP の機能を提供する wrapper モジュール Apache::SOAP の代わりに呼び出す Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 18 DA::Adapter 機能説明 (2) 内部モジュール(カスタマイズ可能な領域) DA::Adapter::BasicAuth DA::Adapter::CreateSession フック関数の提供(pre, post, commit, rollback)→暫定 DA::Adapter::Sudo 2004/12/16 SOAP::Lite の改変版(auto encoding機能などを追加) DA::Adapter::Hook API単位で同期実行(排他実行)機能を提供する 1つのAPIが同時に(並列に)複数実行されないことを保証 DA::Adapter::MySOAP 認証されたユーザでセッションを生成する DA::Adapter::Synchronized Cookie を用いない HTTP Basic 認証を提供 実行ユーザ権限のチェックや、環境変数、umask の設定など Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 19 Webサービスの設定方法 .htaccess (httpd.conf) で設置可能に <Location /service/soap/> order deny,allow IPアドレスの制限 deny from all allow from 127.0.0.1 192.168. AuthName HTTP_Basic_Authentication ユーザ認証の設定 AuthType Basic PerlModule DA::Adapter::BasicAuth PerlAuthenHandler DA::Adapter::BasicAuth require valid-user SetHandler perl-script PerlModule DA::Adapter::SOAP SOAP Service の設定 PerlHandler DA::Adapter::SOAP PerlSetVar dispatch_to "DA::API::Tests, DA::API::Sample" PerlSetVar options "compress_threshold => 10000" Options +ExecCGI PerlSetVar SOAP_default_ie UTF-8 PerlSetVar SOAP_default_oe UTF-8 入出力エンコーディング設定 PerlSetVar SOAP_typelookup string </Location> 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 20 4. Apache Axis で Java と連携 Shibuya Perl Mongers テクニカルトーク #5 WSDLファイルとJavaスタブコード 2004/12/16 21 Apache Axis インストールするソフトウェア群 (1) J2SDK 1.4.2_05 ... j2sdk-1_4_2_05-windows-i586-p.exe (2) Jakarta Tomcat 4.1.31 ... jakarta-tomcat-4.1.31.exe (3) Apache Axis 1.2RC1 ... axis-1_2RC1-bin.zip (4) JAF 1.0.2 ... jaf-1_0_2-upd.zip (5) javamail 1.3.1 ... javamail-1_3_1.zip 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 22 Javaクライアントの例 (Apache Axis) import import import import import org.apache.soap.Constants; org.apache.soap.rpc.*; org.apache.soap.transport.http.SOAPHTTPConnection; java.net.URL; java.util.Vector; // javac SOAPClientTests.java // java SOAPClientTests public class SOAPClientTests { public static void main(String[] args) { try { // URLの指定 URL url = new URL("http://localhost:8001/service/soap/"); // Callオブジェクトを生成 Call call = new Call(); // ユーザ認証の設定 org.apache.soap.transport.http.SOAPHTTPConnection soapTransport = new org.apache.soap.transport.http.SOAPHTTPConnection(); soapTransport.setUserName(“username"); soapTransport.setPassword("password"); call.setSOAPTransport(soapTransport); // ターゲットとなるURIを指定 call.setTargetObjectURI("urn:DA/API/Tests"); // ターゲットとなるメソッドを指定 call.setMethodName("add"); // 直列化のスタイルを指定 call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); // パラメータの設定 Vector params = new Vector(); params.addElement(new Parameter("a", String.class, "123", null)); params.addElement(new Parameter("b", String.class, "456", null)); params.addElement(new Parameter("c", String.class, "789", null)); call.setParams(params); // 呼び出しを実行 String SOAPActionURI = ""; Response resp = call.invoke(url, SOAPActionURI); // 戻り値を取得 Parameter ret = resp.getReturnValue(); System.out.println(ret.getValue()); } catch (Exception e) { e.printStackTrace(); } } 2004/12/16 } Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 23 WSDL2Java WSDLファイルからJavaのスタブコードを自動作成 java org.apache.axis.wsdl.WSDL2Java ISAPI.wsdl Javaクライアント ./jp/co/dreamarts/insuite/DA/API/WSDL/FacilityInfo.java ./jp/co/dreamarts/insuite/DA/API/WSDL/FaScheduleInfo.java ./jp/co/dreamarts/insuite/DA/API/WSDL/GroupInfo.java ./jp/co/dreamarts/insuite/DA/API/WSDL/ISAPI.java ./jp/co/dreamarts/insuite/DA/API/WSDL/ISAPIBindingStub.java ./jp/co/dreamarts/insuite/DA/API/WSDL/ISAPIService.java ./jp/co/dreamarts/insuite/DA/API/WSDL/ISAPIServiceLocator.java ./jp/co/dreamarts/insuite/DA/API/WSDL/ScheduleInfo.java 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 24 WSDL とは? WSDL (Web Services Description Language) Webサービスを記述するための外部仕様(入出力仕様書) サービスのインターフェースや、提供場所、実行方法などの情報を記述 (例) SOAP メッセージ (XML) WSDL ファイル (XML) リクエスト 入出力仕様書 network クライアント Windows Java (Apache Axis) 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 レスポンス SOAP メッセージ (XML) サーバ Linux mod_perl (SOAP::Lite) Copyright © 2004 DreamArts Corporation. All Rights Reserved. 25 WSDLファイルの例 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 26 Apache Axis (Java) の Type Mapping 問題 2004/12/16 WSDL type Java Type xsd:string java.lang.String xsd:int int java.lang.Integer xsd:long long java.lang.Long xsd:short short java.lang.Short xsd:float float java.lang.Float xsd:double double java.lang.Double xsd:boolean boolean java.lang.Boolean xsd:byte byte java.lang.Byte xsd:integer java.math.BigInteger xsd:decimal java.math.BigDecimal Shibuya Perl Mongers テクニカルトーク #5 Java Type (nillable) Copyright © 2004 DreamArts Corporation. All Rights Reserved. 27 何が問題か? xsd:integer 無条件で java.math.BigInteger にマッピング 多倍長整数なのでパフォーマンス悪化 xsd:int nillable=“false” では int 宣言となる nillable=“true” では java.lang.Integer 型を使用する (nullを許可するため) int配列で nillable=false を指定する方法が不明 int配列の要素にnullを許可したい場合… xsd:int が使えないので xsd:integer を使うしかない? 2004/12/16 Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 28 SOAP/WSDLのまとめ 2004/12/16 疎結合な技術でどんなプラットフォーム同士でも連携できる (Perl, Java, Ruby, Python, C++, .NET C#…) 言語「非依存」と言いつつ、実際は言語「依存」である (Type Mapping, プロシジャコール…) 規格は「厳格」なようで、実は「曖昧」である (規格の範囲内であれば、どんな実装でもOK) WSDLを自動生成するツールの精度はまだ良くない (手作業でWSDLファイルを作成するのが安全) 構造化データ:ツールによってうまく扱えないものがある (SOAP::Lite の WSDL サポートはまだ不完全) WSDLでは、例外条件や入力文字列幅などを定義できない <!-- コメントの中に書いて人間がわかるようにする --> うまく動くようになると爽快!(バッドノウハウの塊かも?) Shibuya Perl Mongers テクニカルトーク #5 Copyright © 2004 DreamArts Corporation. All Rights Reserved. 29
© Copyright 2024 ExpyDoc