Java でいくつかの WS を開発する必要があります。これについてはこれまで経験がないため、簡単な例から始めました。ここでWS:
@WebService
public interface DataExchangeWebService {
public int doubleIt(int numberToDouble);
}
@WebService(targetNamespace = "http://www.example.com/ws/DataExchange",
portName = "DataExchangePort",
serviceName = "DataExchangeService",
endpointInterface = "xyz.DataExchangeWebService")
public class DataExchangeWebServiceImpl implements DataExchangeWebService {
@Override
public int doubleIt(int numberToDouble) {
return numberToDouble * 2;
}
}
ここで、このサービスを JUnit 経由でのみテストしたいと思います。テスト ケースの出発点となるこのブログ エントリを見つけました。シンプルにするために、Java Endpoint クラスを使用しました。
protected static URL wsdlURL;
protected static QName serviceName;
protected static QName portName;
protected static Endpoint endpoint;
protected static String address;
static {
serviceName = new QName("http://www.example.com/ws/DataExchange", "DataExchangeService");
portName = new QName("http://www.example.com/ws/DataExchange", "DataExchangePort");
}
@BeforeClass
public static void setUp() throws MalformedURLException {
address = "http://localhost:9000/ws/DataExchange";
wsdlURL = new URL(address + "?wsdl");
endpoint = Endpoint.publish(address, new DataExchangeWebServiceImpl());
}
@AfterClass
public static void tearDown() {
endpoint.stop();
}
これにより、WS が発行され、次の 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 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.example.com/ws/DataExchange" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.example.com/ws/DataExchange"
name="DataExchangeService">
<import namespace="http://dataexchange.sys.cs.iface.service.appserver.xyz/"
location="http://localhost:9000/ws/DataExchange?wsdl=1" />
<binding xmlns:ns1="http://dataexchange.sys.cs.iface.service.appserver.xyz/"
name="DataExchangePortBinding" type="ns1:DataExchangeWebService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="doubleIt">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="DataExchangeService">
<port name="DataExchangePort" binding="tns:DataExchangePortBinding">
<soap:address location="http://localhost:9000/ws/DataExchange" />
</port>
</service>
</definitions>
これで、2 つのテスト ケースができました。最初のものは、プレーン サービスを使用してリクエストを行います。
public void raw_service() {
Service service = Service.create(wsdlURL, serviceName);
DataExchangeWebService dataExchangeWebService = service.getPort(portName, DataExchangeWebService.class);
int resp = dataExchangeWebService.doubleIt(10);
assertEquals(20, resp);
}
これはうまく機能しています。問題は2つ目です。SOAP メッセージを使用してリクエストを行います。
public void raw_service_with_full_soap_message() throws DOMException, SOAPException, IOException {
Service service = Service.create(wsdlURL, serviceName);
Dispatch<SOAPMessage> disp = service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
InputStream is = getClass().getClassLoader().getResourceAsStream("fullSOAPMessage.xml");
SOAPMessage reqMsg = MessageFactory.newInstance().createMessage(null, is);
assertNotNull(reqMsg);
SOAPMessage response = disp.invoke(reqMsg);
assertEquals("Double-It not doubling zero correctly", "0", response.getSOAPBody().getTextContent().trim());
}
fullSOAPMessage.xml は次のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:doubleIt xmlns:ns2="http://www.example.com/ws/DataExchange">
<numberToDouble>0</numberToDouble>
</ns2:doubleIt>
</soap:Body>
</soap:Envelope>
JUnit は次のエラーで失敗します。
javax.xml.ws.soap.SOAPFaultException: Cannot find dispatch method for {http://www.example.com/ws/DataExchange}doubleIt
私がこれまでに行った調査では、これが WS のターゲット名前空間と SOAP メッセージの間の競合と関係があることだけが明らかになりました。しかし、私の目にはそうではありません。これを解決する方法や何が起こっているのかについてのアイデアはありますか?