我得到了这个 WSDL,我必须为它开发一个客户端(我一直在这里提出问题,哈哈)。
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:ManterFornecedor" xmlns:s0="urn:ManterFornecedor" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="urn:ManterFornecedor">
<xsd:element name="Novo" type="s0:InputMapping1"/>
<xsd:complexType name="InputMapping1">
<xsd:sequence>
<xsd:element name="NO_FORNECEDOR" type="xsd:string"/>
<xsd:element name="DE_CONTRATO" type="xsd:string"/>
<xsd:element name="DH_INICIO" nillable="true" type="xsd:dateTime"/>
<xsd:element name="DH_FIM" nillable="true" type="xsd:dateTime"/>
<xsd:element name="NO_PRODUTO" type="xsd:string"/>
<xsd:element name="IC_STATUS" type="s0:IC_STATUSType" nillable="true"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="IC_STATUSType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Ativo"/>
<xsd:enumeration value="Inativo"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="NovoResponse" type="s0:OutputMapping1"/>
<xsd:complexType name="OutputMapping1">
<xsd:sequence>
<xsd:element name="Id" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="AuthenticationInfo" type="s0:AuthenticationInfo"/>
<xsd:complexType name="AuthenticationInfo">
<xsd:sequence>
<xsd:element name="userName" type="xsd:string"/>
<xsd:element name="password" type="xsd:string"/>
<xsd:element minOccurs="0" name="authentication" type="xsd:string"/>
<xsd:element minOccurs="0" name="locale" type="xsd:string"/>
<xsd:element minOccurs="0" name="timeZone" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="NovoSoapOut">
<wsdl:part element="s0:NovoResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="ARAuthenticate">
<wsdl:part element="s0:AuthenticationInfo" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="NovoSoapIn">
<wsdl:part element="s0:Novo" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="PortPortType">
<wsdl:operation name="Novo">
<wsdl:input message="s0:NovoSoapIn"></wsdl:input>
<wsdl:output message="s0:NovoSoapOut"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="PortSoapBinding" type="s0:PortPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Novo">
<soap:operation soapAction="urn:ManterFornecedor/Novo" style="document"/>
<wsdl:input>
<soap:header message="s0:ARAuthenticate" part="parameters" use="literal"></soap:header>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ManterFornecedorService">
<wsdl:documentation>Fornecedor</wsdl:documentation>
<wsdl:port binding="s0:PortSoapBinding" name="PortSoap">
<soap:address location="http://somewhere&webService=ManterFornecedor"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
我提供了完整的 WSDL,但问题的重要部分是
<soap:operation soapAction="urn:ManterFornecedor/Novo" style="document"/>
<wsdl:input>
<soap:header message="s0:ARAuthenticate" part="parameters" use="literal"></soap:header>
<soap:body use="literal"/>
</wsdl:input>
如您所见,输入在其标头中有一条 ARAuthenticate 消息,即
<wsdl:message name="ARAuthenticate">
<wsdl:part element="s0:AuthenticationInfo" name="parameters"></wsdl:part>
</wsdl:message>
<xsd:element name="AuthenticationInfo" type="s0:AuthenticationInfo"/>
<xsd:complexType name="AuthenticationInfo">
<xsd:sequence>
<xsd:element name="userName" type="xsd:string"/>
<xsd:element name="password" type="xsd:string"/>
<xsd:element minOccurs="0" name="authentication" type="xsd:string"/>
<xsd:element minOccurs="0" name="locale" type="xsd:string"/>
<xsd:element minOccurs="0" name="timeZone" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
我使用 Eclipse 的 Web 服务资源管理器创建了一个 WS 客户端来测试这个 Web 服务,它成功了!此客户端具有要设置的用户名和密码字段。
好的,现在我需要使用这个客户端示例代码,并实现一个独立的(不是 Web UI)解决方案来收集信息并使用客户端将其发送到服务器。但它失败了,我相信这是因为身份验证。
我看到设置的用户名和密码的唯一地方是 PortSoapBindingStub.createCall():
org.apache.axis.client.Call _call = super._createCall();
if (super.maintainSessionSet) {
_call.setMaintainSession(super.maintainSession);
}
if (super.cachedUsername != null) {
_call.setUsername(super.cachedUsername);
}
if (super.cachedPassword != null) {
_call.setPassword(super.cachedPassword);
}
if (super.cachedEndpoint != null) {
_call.setTargetEndpointAddress(super.cachedEndpoint);
}
if (super.cachedTimeout != null) {
_call.setTimeout(super.cachedTimeout);
}
if (super.cachedPortName != null) {
_call.setPortName(super.cachedPortName);
}
但是,这些缓存的东西是从哪里来的?我尝试编辑此代码并手动设置它们,但不断收到错误:
Exception in thread "main" AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: java.lang.ArrayIndexOutOfBoundsException: -1
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}hostname:myhost
java.lang.ArrayIndexOutOfBoundsException: -1
at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(Unknown Source)
at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:796)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
at org.apache.axis.client.Call.invoke(Call.java:2767)
at org.apache.axis.client.Call.invoke(Call.java:2443)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
at ManterFornecedor.PortSoapBindingStub.novo(PortSoapBindingStub.java:174)
at ManterFornecedor.PortPortTypeProxy.novo(PortPortTypeProxy.java:50)
at caixa.pedes.br.ManterFornecedor.main(ManterFornecedor.java:43)
这是我的代码:
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import org.apache.axis.AxisFault;
import org.apache.axis.client.Call;
import ManterFornecedor.*;
public class ManterFornecedor {
public static void main(String[] args) throws RemoteException, ServiceException, MalformedURLException {
InputMapping1 parameters = new InputMapping1(
"fornecedor","contrato",java.util.Calendar.getInstance(), java.util.Calendar.getInstance(),
"produto",IC_STATUSType.Ativo
);
java.net.URL endpoint = new java.net.URL("http://somewhere&webService=ManterFornecedor");
PortPortTypeProxy proxy = new PortPortTypeProxy();
ManterFornecedorServiceLocator locator = new ManterFornecedorServiceLocator();
ManterFornecedor.PortPortType port = locator.getPortSoap();
PortSoapBindingStub client = new PortSoapBindingStub(endpoint,locator);
ManterFornecedor.OutputMapping1 response = proxy.novo(parameters);
System.out.println(response);
}
}
编辑:如您所见,我是 Web 服务的新手,我有点迷路了。我不知道确切的原因,但是在 Proxy、Locator 和 Stub 中都可以使用 novo() 方法。我将阅读更多关于这些设计模式的信息,因为我对它们也很陌生,而同时使用这三种设计模式更加麻烦。
用于调用 WSDL 生成的运算符的最佳对象是什么?不幸的是,在 Eclipse 中创建的客户端代码使用 JSP 来接收参数,并且我无法将示例代码正确地隔离到真实客户端,以便我可以开发我的代码并调用客户端的操作员。
如果客户端被封装在一个唯一的类中,我只需要提供它的配置(端点、身份验证等)然后调用操作员就会容易得多。