少し前もっての情報:
SOAP サービスがあります (JAX-WS (エンドポイント クラス) を使用してホストされていますが、それは重要ではないと思います)。
クライアント (C#) を生成する Visual Studio で問題なく Web サービスに接続して使用できます。
Eclipse Web ツール (新規 --> その他 --> Web サービス --> Web サービス クライアント) を使用して Java クライアントを生成しました。
次に、クライアントをテストする JUnit テストを作成しました。テストは成功しますが、実行に非常に時間がかかります。各サービス コールには 300 秒かかります (2 ~ 3 秒かかります)。さらに、コンピューターの速度は関係ありません。非常に遅い仕事用のラップトップでこれを実行すると、高速な家庭用マシンで実行した場合と同じ時間がかかります。
org.apache.axis.encoding.DeserializationContext 内の次の関数への軸コードにデバッグしました。
public void parse() throws SAXException
{
if (inputSource != null) {
SAXParser parser = XMLUtils.getSAXParser();
try {
parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
parser.parse(inputSource, this);
try {
// cleanup - so that the parser can be reused.
parser.setProperty("http://xml.org/sax/properties/lexical-handler", nullLexicalHandler);
} catch (Exception e){
// Ignore.
}
当然のことですが、parser.parse() の呼び出しに 300 秒かかっています。Web サービスからの は非常に短いため、解析にそれほど時間はかかりません。
誰かが疑問に思っている場合に備えて、パーサーの実際のタイプはcom.sun.org.apache.xerces.internal.jaxp.SAXParserImpl
ソースを持っていないため、デバッグできません (そして、一般的に使用されるライブラリの奥深くで 50 の呼び出しをデバッグするのにうんざりしています)。
私は現在、Sun からのパッケージを含めるためにプロファイラーを実行しています。完了したら、その結果を投稿します(これらのパッケージをすべて追加すると、テストが大幅に遅くなります)
私は走っていてEclipse 3.5.1
、使っていますaxis 1.4
編集:
JUnit テストは次のとおりです。
@Test
public void testExecuter() throws IOException, InterruptedException, RemoteException, ServiceException
{
//Listener l = new Listener(3456);
//l.start();
Executer exec = new ExecuterServiceLocator().getExecuterPort();
//Executer exec = new ExecuterProxy("http://localhost:3456/Executer");
System.out.println("executer created");
_return remote = exec.execute("perl -e \"print 5\"", new EvAction[0]);
System.out.println("after call 1");
assertEquals("5", remote.getStdout());
assertEquals("", remote.getStderr());
assertEquals(0, remote.getReturnCode());
}
注: 実行者を作成する両方の方法で同じことが起こります
編集2:
サービスを開始するために使用しているコードは次のとおりです。
public static void main(String[] args) {
Endpoint.create(new Executer()).publish("http://localhost:3456/Executer");
}
現在、単一のマシンで開発しているだけなので、URL を投稿できません。ただし、http://localhost:3456/Executer?WSDLにアクセスすると生成される WSDL は次のとおりです。
<!--
Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6.
-->
−
<!--
Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6.
-->
−
<definitions targetNamespace="http://executer/" name="ExecuterService">
−
<types>
−
<xsd:schema>
<xsd:import namespace="http://executer/" schemaLocation="http://localhost:3456/Executer?xsd=1"/>
</xsd:schema>
</types>
−
<message name="Execute">
<part name="parameters" element="tns:Execute"/>
</message>
−
<message name="ExecuteResponse">
<part name="parameters" element="tns:ExecuteResponse"/>
</message>
−
<message name="IOException">
<part name="fault" element="tns:IOException"/>
</message>
−
<message name="InterruptedException">
<part name="fault" element="tns:InterruptedException"/>
</message>
−
<portType name="Executer">
−
<operation name="Execute">
<input message="tns:Execute"/>
<output message="tns:ExecuteResponse"/>
<fault message="tns:IOException" name="IOException"/>
<fault message="tns:InterruptedException" name="InterruptedException"/>
</operation>
</portType>
−
<binding name="ExecuterPortBinding" type="tns:Executer">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
−
<operation name="Execute">
<soap:operation soapAction=""/>
−
<input>
<soap:body use="literal"/>
</input>
−
<output>
<soap:body use="literal"/>
</output>
−
<fault name="IOException">
<soap:fault name="IOException" use="literal"/>
</fault>
−
<fault name="InterruptedException">
<soap:fault name="InterruptedException" use="literal"/>
</fault>
</operation>
</binding>
−
<service name="ExecuterService">
−
<port name="ExecuterPort" binding="tns:ExecuterPortBinding">
<soap:address location="http://localhost:3456/Executer"/>
</port>
</service>
</definitions>
編集:
これが問題を引き起こしている可能性があると思います:
TCPMonitor を使用して SOAP 要求を調べたところ、クライアントが HTTP/1.0 を話し、サーバーが HTTP/1.1 を話していることに気付きましたが、これが問題の原因であるかどうかはわかりません。私は現在、クライアントに HTTP/1.1 を話させる方法を見つけようとしています。
誰かが疑問に思っている場合に備えて、SOAP メッセージを次に示します。
POST /Executer HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.4
Host: USENBOONETL1C:2222
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 354
<?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><Execute xmlns="http://executer/"><arg0 xmlns="">perl -e "print 5"</arg0></Execute></soapenv:Body></soapenv:Envelope>
と応答:
HTTP/1.1 200 OK
Content-type: text/xml;
charset="utf-8"
Content-length: 266
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:ExecuteResponse xmlns:ns2="http://executer/"><return><stdout>5</stdout><stderr></stderr><returnCode>0</returnCode></return></ns2:ExecuteResponse></S:Body></S:Envelope>
編集:
ついに!HTTP クライアントを CommonsHTTPClient に変更し、HTTP/1.1 を使用すると問題が修正されることがわかりました。
これを修正したクライアントに追加したコードは次のとおりです。
BasicClientConfig basicClientConfig = new BasicClientConfig();
SimpleChain simpleChain = new SimpleChain();
simpleChain.addHandler(new CommonsHTTPSender());
basicClientConfig.deployTransport("http", simpleChain);
ExecuterServiceLocator l = new ExecuterServiceLocator(basicClientConfig);
...
注:クラスパスにcommon-httpclient.jar
とを追加する必要があります。common.codec.jar