top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
うそSOAPサーバ版が技術的に実現可能かどうか簡単に検証しました。
Apache Axis 1.2.1 ベースで うそSOAPの可能性を探ってみました。Tomcat 4.1も利用しています。
とりあえず jwsベースで Webサービスを作成して Axisに食わしてみます。 WsTest01.jws
public class WsTest01 {
public String method01(String arg1, int arg2) {
return "戻り値:[" + arg1 + ", " + arg2 + "]";
}
}
WsTest01.jwsをベースに Axisが生成する WSDLは 下記になります。 http://localhost:8080/axis/WsTest01.jws?wsdl
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions targetNamespace="http://localhost:8080/axis/WsTest01.jws"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://localhost:8080/axis/WsTest01.jws"
xmlns:intf="http://localhost:8080/axis/WsTest01.jws"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><!--WSDLはApache Axis version: 1.2.1
Built on Jun 14, 2005 (09:15:57 EDT)によって生成されました / [en]-(WSDL created by Apache Axis version: 1.2.1
Built on Jun 14, 2005 (09:15:57 EDT))-->
<wsdl:message name="method01Request">
<wsdl:part name="arg1" type="xsd:string"/>
<wsdl:part name="arg2" type="xsd:int"/>
</wsdl:message>
<wsdl:message name="method01Response">
<wsdl:part name="method01Return" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="WsTest01">
<wsdl:operation name="method01" parameterOrder="arg1 arg2">
<wsdl:input message="impl:method01Request" name="method01Request"/>
<wsdl:output message="impl:method01Response" name="method01Response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="WsTest01SoapBinding" type="impl:WsTest01">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="method01">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="method01Request">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://DefaultNamespace" use="encoded"/>
</wsdl:input>
<wsdl:output name="method01Response">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/axis/WsTest01.jws" use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="WsTest01Service">
<wsdl:port binding="impl:WsTest01SoapBinding" name="WsTest01">
<wsdlsoap:address location="http://localhost:8080/axis/WsTest01.jws"/>
</wsdl:port>
</wsdl:service></wsdl:definitions>
※不要な改行を除去するなど、多少デフォルメしています。※WsTest01.jws.wsdl としてファイルを保存します。 WSDL2Javaを実行して Javaソースコードを生成します。 コマンドライン java -classpath axis.jar;commons-logging-1.0.4.jar;commons-discovery-0.2.jar;jaxrpc.jar;saaj.jar;wsdl4j-1.5.1.jar org.apache.axis.wsdl.WSDL2Java -t -s WsTest01.jws.wsdl
呼び出し側の SOAPを利用するクライアントは下記のようになります。 TestCaller.java
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import localhost.axis.WsTest01_jws.WsTest01;
import localhost.axis.WsTest01_jws.WsTest01ServiceLocator;
public class TestCaller {
public static void main(String[] args) {
try {
WsTest01 test = new WsTest01ServiceLocator().getWsTest01();
String result = test.method01("こんにちは", 123);
System.out.println(result);
} catch (RemoteException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
}
}
ここで、SOAPを うそSOAP (USOAP)サーバ・サーブレットに取り替えます。 UsoapServlet.java
/*
* うそSOAPサーブレット構築計画
* Copyright (C) 2005 いがぴょん
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* うそSOAPサーブレット ソースコード
*
* @author iga
* @version 2005.08.02
*/
public class UsoapServlet extends HttpServlet {
/**
* <code>ENCODING</code> 文字コードを与えます。
*/
public static final String ENCODING = "UTF-8";
/**
* Java Servletのエントリポイントです。
*
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public final void service(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
BufferedReader reader = null;
PrintWriter writer = null;
setResponseDefault(response);
try {
reader = request.getReader();
writer = response.getWriter();
for (Enumeration enum = request.getHeaderNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
System.out.println("H:" + key + "=" + request.getHeader(key)
+ "");
}
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println("REQ:" + line);
}
String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ " <soapenv:Body>"
+ " <ns1:method01Response"
+ " soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""
+ " xmlns:ns1=\"http://DefaultNamespace\">"
+ " <method01Return xsi:type=\"xsd:string\">"
+ "戻り値:[こんにちは, 123]"
+ "</method01Return>"
+ " </ns1:method01Response>" + " </soapenv:Body>"
+ "</soapenv:Envelope>";
writer.write(result);
} finally {
// ReaderもWriterもクローズしません。flushも呼び出してはなりません。(2005.03.13に判明)
}
}
/**
* デフォルトとなるレスポンスヘッダーの付与
*
* @param response
* レスポンスオブジェクトを与えます。
*/
private void setResponseDefault(final HttpServletResponse response) {
response.setContentType("text/html; charset=" + ENCODING);
response.addHeader("Content-Type", "text/xml");
response.addHeader("charset", ENCODING);
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
}
}
電文をシュミレートするために、うそSOAPクライアントの活用は有益です。 HttpCaller.java
/*
* うそSOAPサーブレット構築計画
* Copyright (C) 2005 いがぴょん
*/
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
public class HttpCaller {
private static final int COUNT = 100;
private static void callMethod(boolean isSysout) {
HttpClient client = new HttpClient();
client.getHostConfiguration().setHost("localhost", 8080, "http");
//PostMethod method = new PostMethod("/examples/KantanHelloServlet");
PostMethod method = new PostMethod("/axis/WsTest01.jws");
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ " <soapenv:Body>"
+ " <ns1:method01 soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""
+ " xmlns:ns1=\"http://DefaultNamespace\">"
+ " <arg1 xsi:type=\"xsd:string\">こんにちは</arg1>"
+ " <arg2 href=\"#id0\"/>"
+ " </ns1:method01>"
+ " <multiRef id=\"id0\" soapenc:root=\"0\""
+ " soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""
+ " xsi:type=\"xsd:int\""
+ " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">123</multiRef>"
+ " </soapenv:Body>" + "</soapenv:Envelope>";
byte[] requestBytes = null;
try {
requestBytes = request.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
method.addRequestHeader("content-type", "text/xml; charset=utf-8");
method
.addRequestHeader("accept",
"application/soap+xml, application/dime, multipart/related, text/*");
method.addRequestHeader("user-agent", "Usoap/1.2.1");
method.addRequestHeader("host", "localhost:8080");
method.addRequestHeader("cache-control", "no-cache");
method.addRequestHeader("pragma", "no-cache");
method.addRequestHeader("soapaction", "");
method.addRequestHeader("content-length", String
.valueOf(requestBytes.length));
method.setRequestBody(new ByteArrayInputStream(requestBytes));
try {
client.executeMethod(method);
BufferedReader reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream()));
for (;;) {
String readLine = reader.readLine();
if (readLine == null) {
break;
}
System.out.println(readLine);
}
reader.close();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
method.releaseConnection();
}
public static void main(String[] args) {
callMethod(true);
}
}
※Jakarta Commons HttpClient 2.0.2で動作確認を取りました。 とりあえず文字列エンコードがもっとも くせがありそうです。
関連する日記
文字列エンコードが納得いかないので、WSDLを少し変更してみつつあります。
参考リソース: Web Services Description Language (WSDL) Version 2.0 Part 1: Core Language http://www.w3.org/TR/2005/WD-wsdl20-20050510/ WsTest01.jws.wsdl 改造版
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions targetNamespace="http://localhost:8080/axis/WsTest01.jws"
xmlns:impl="http://localhost:8080/axis/WsTest01.jws"
xmlns:intf="http://localhost:8080/axis/WsTest01.jws"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><!--WSDLはApache Axis version: 1.2.1 が生成したものを少し改良しました。-->
<wsdl:message name="method01Request">
<wsdl:part name="arg1" type="xsd:string"/>
<wsdl:part name="arg2" type="xsd:int"/>
</wsdl:message>
<wsdl:message name="method01Response">
<wsdl:part name="method01Return" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="WsTest01">
<wsdl:operation name="method01" parameterOrder="arg1 arg2">
<wsdl:input message="impl:method01Request" name="method01Request"/>
<wsdl:output message="impl:method01Response" name="method01Response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="WsTest01SoapBinding" type="impl:WsTest01">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="method01">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="method01Request">
<wsdlsoap:body namespace="http://DefaultNamespace"/>
</wsdl:input>
<wsdl:output name="method01Response">
<wsdlsoap:body namespace="http://localhost:8080/axis/WsTest01.jws"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="WsTest01Service">
<wsdl:port binding="impl:WsTest01SoapBinding" name="WsTest01">
<wsdlsoap:address location="http://localhost:8080/axis/WsTest01.jws"/>
</wsdl:port>
</wsdl:service></wsdl:definitions>
登り電文の例 登り電文の例
H:content-type=text/xml; charset=utf-8
H:accept=application/soap+xml, application/dime, multipart/related, text/*
H:user-agent=Axis/1.2.1
H:host=localhost:8080
H:cache-control=no-cache
H:pragma=no-cache
H:soapaction=""
H:content-length=401<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<method01 xmlns="http://DefaultNamespace">
<arg1 xmlns="">こんにちは</arg1>
<arg2 xmlns="">123</arg2>
</method01>
</soapenv:Body></soapenv:Envelope>
うそSOAPサーバ・サーブレットも改良します。 UsoapServlet.java v2
/*
* うそSOAPサーブレット構築計画
* Copyright (C) 2005 いがぴょん
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* うそSOAPサーブレット ソースコード
*
* @author iga
* @version 2005.08.02
*/
public class UsoapServlet extends HttpServlet {
/**
* <code>ENCODING</code> HTMLで扱う文字コードを与えます。
*/
public static final String ENCODING = "UTF-8";
/**
* Java Servletのエントリポイントです。
*
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public final void service(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
BufferedReader reader = null;
PrintWriter writer = null;
setResponseDefault(response);
try {
reader = request.getReader();
writer = response.getWriter();
for (Enumeration enum = request.getHeaderNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
System.out.println("H:" + key + "=" + request.getHeader(key)
+ "");
}
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println("REQ:" + line);
}
String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ " <soapenv:Body>"
+ " <ns1:method01Response"
+ " xmlns:ns1=\"http://DefaultNamespace\">"
+ " <method01Return xsi:type=\"xsd:string\">こんにちはSOAP</method01Return>"
+ " </ns1:method01Response>" + " </soapenv:Body>"
+ "</soapenv:Envelope>";
writer.write(result);
} finally {
// ReaderもWriterもクローズしません。flushも呼び出してはなりません。(2005.03.13に判明)
}
}
/**
* デフォルトとなるレスポンスヘッダーの付与
*
* @param response
* レスポンスオブジェクトを与えます。
*/
private void setResponseDefault(final HttpServletResponse response) {
response.setContentType("text/html; charset=" + ENCODING);
response.addHeader("Content-Type", "text/xml");
response.addHeader("charset", ENCODING);
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
}
}
これに呼応する形で、うそSOAPクライアントも変更します。 HttpCaller.java 改造版
/*
* うそSOAPサーブレット構築計画
* Copyright (C) 2005 いがぴょん
*/
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
public class HttpCaller {
private static final int COUNT = 100;
private static void callMethod(boolean isSysout) {
HttpClient client = new HttpClient();
client.getHostConfiguration().setHost("localhost", 8080, "http");
//PostMethod method = new PostMethod("/examples/KantanHelloServlet");
PostMethod method = new PostMethod("/axis/WsTest01.jws");
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<soapenv:Envelope"
+ " xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ " <soapenv:Body>"
+ " <method01 xmlns=\"http://DefaultNamespace\">"
+ " <arg1 xmlns=\"\">こんにちは</arg1>"
+ " <arg2 xmlns=\"\">123</arg2>" + " </method01>"
+ " </soapenv:Body>" + "</soapenv:Envelope>";
byte[] requestBytes = null;
try {
requestBytes = request.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
method.addRequestHeader("content-type", "text/xml; charset=utf-8");
method
.addRequestHeader("accept",
"application/soap+xml, application/dime, multipart/related, text/*");
method.addRequestHeader("user-agent", "Usoap/1.2.1");
method.addRequestHeader("host", "localhost:8080");
method.addRequestHeader("cache-control", "no-cache");
method.addRequestHeader("pragma", "no-cache");
method.addRequestHeader("soapaction", "");
method.addRequestHeader("content-length", String
.valueOf(requestBytes.length));
method.setRequestBody(new ByteArrayInputStream(requestBytes));
try {
client.executeMethod(method);
BufferedReader reader = new BufferedReader(new InputStreamReader(
method.getResponseBodyAsStream()));
for (;;) {
String readLine = reader.readLine();
if (readLine == null) {
break;
}
System.out.println(readLine);
}
reader.close();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
method.releaseConnection();
}
public static void main(String[] args) {
callMethod(true);
}
}
とりあえず、文字列エンコーディングは 利用しないように変更することができました。
関連する日記
Visual Studio .NETでOracle DB開発 - オラクルがツールを無償提供 (MYCOM PC WEB) http://pcweb.mycom.co.jp/news/2005/08/01/003.html このリリースは .NET上でのOracle開発に大きなインパクトを与えるように感じました。「自動コード生成」、「PL/SQLエディタ」あたりが特に印象に残ります。
MYCOM: 住商情報システムと住商エレクトロニクスが合併 http://pcweb.mycom.co.jp/news/2005/08/01/005.html 業務的に私にとってインパクトのあるニュースであるように感じられました。