Perl から JAX-WS な Web サービスへマルチバイト文字列を送信
Perl の SOAP::Lite を使用して、JAX-WS な Web サービスに対して日本語の文字列を送信した所、Web サービス側で正しく受信できなかった。
Java
Web サービス側はこんな感じ。
package me.org.echo; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; @WebService() public class EchoWS { @WebMethod(operationName = "echo") public String echo(@WebParam(name = "params")String params) { Logger logger = Logger.getLogger(CalculatorWS.class.getName()); logger.log(Level.INFO, params); return params; } @WebMethod(operationName = "echoList") public List<String> echoList(@WebParam(name = "params")List<String> params) { Logger logger = Logger.getLogger(CalculatorWS.class.getName()); for (String param : params) { logger.log(Level.INFO, param); } return params; } }
マルチバイトを含まない文字列を送信した場合、正しくログに表示される。
#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use SOAP::Lite; my $client = SOAP::Lite->service('http://localhost:8084/EchoWSApplication/EchoWS?wsdl'); $client->readable(1); $client->ns('http://schemas.xmlsoap.org/soap/envelope/', 'ns'); my $str = SOAP::Data->name('params')->value('Hello'); my $result = $client->echo($str);
2010/08/05 15:12:24 me.org.echo.EchoWS echo 情報: Hello!
日本語(マルチバイト文字)を送信した場合。
#!/usr/bin/env perl use strict; use warnings; use utf8; use Data::Dumper; use SOAP::Lite; my $client = SOAP::Lite->service('http://localhost:8084/EchoWSApplication/EchoWS?wsdl'); $client->readable(1); $client->ns('http://schemas.xmlsoap.org/soap/envelope/', 'ns'); my $str = SOAP::Data->name('params')->value('こんにちはこんにちは'); my $result = $client->echo($str);
2010/08/05 15:21:18 me.org.echo.EchoWS echo 情報: 44GT44KT44Gr44Gh44Gv44GT44KT44Gr44Gh44Gv
バイナリっぽい文字列になっとる…。
送信したリクエストをデバッグモードで表示してみたら、以下のように送信されている。
<?xml version="1.0" encoding="UTF-8"?> <ns:Envelope xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/" ns:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://org.me.echo/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ns:Body> <tns:echo> <params xsi:type="xsd:base64Binary">44GT44KT44Gr44Gh44Gv44GT44KT44Gr44Gh44Gv</params> </tns:echo> </ns:Body> </ns:Envelope>
base64Binary…だと…?
Base64 エンコードとか色々試したけど、どうやってもダメだった。
色々調べた結果、ヒントが見つかったので試した。
XMLRPC::Lite (SOAP::Lite) で base64 エンコーディングさせない: blog.bulknews.net
#!/usr/bin/env perl use strict; use warnings; use utf8; use Data::Dumper; use SOAP::Lite +trace => [qw(debug)]; my $client = SOAP::Lite->service('http://localhost:8084/CalculatorWSApplication/CalculatorWS?wsdl'); $client->readable(1); $client->ns('http://schemas.xmlsoap.org/soap/envelope/', 'ns'); my $data = SOAP::Data->name('params')->type(string => 'こんにちはこんにちは'); my $result = $client->echo($data); warn Dumper $result;
2010/08/05 15:29:36 me.org.echo.EchoWS echo 情報: こんにちはこんにちは
リクエストの中身。
<?xml version="1.0" encoding="UTF-8"?> <ns:Envelope xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/" ns:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://org.me.echo/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ns:Body> <tns:echo> <params xsi:type="xsd:string">こんにちはこんにちは</params> </tns:echo> </ns:Body> </ns:Envelope>
引数の型が List の場合は、
$data = SOAP::Data->name('params')->value( 'hello!', SOAP::Data->type(string => 'こんにちは'), SOAP::Data->type(string => 'こんにちはこんにちは'), ); $result = $client->echoList($data);
とすれば正しく送信できた。