soap-20041217

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