0

I was provided this WSDL, and I have to develop a client for it (I've been making questions here about it lol).

<?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&amp;webService=ManterFornecedor"/>
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

I provided the full WSDL, but the important part for the question is

    <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>

As you can see, input has a ARAuthenticate message in its header, which is

<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>

I used Eclipse's Web Services Explorer to create a WS client to test this webservice, and it worked! This client has username and password fields to be set.

Ok, now I need to take this client exemple code, and implement a standalone (not web UI) solution that gathers info and uses the client to send it to the server. But it's failing, and I believe it's because authentication.

Only place I see username and password being set is in 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);
    }

But, where are these cached stuff coming from? I tried to edit this code and manually set them, but keep receiving error:

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)

Here's my code:

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&amp;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);

    }

}

Edit: as you can see, I'm new to Web Service and I'm kinda lost. I don't know exactally why, but the novo() method is available in Proxy, Locator and Stub. I'll read more about these design patterns because I'm new to them too, and using all 3 together is even more troublesome.

What's the best object to use to call WSDL generated operators? Unfortuntely, client code created in Eclipse uses JSP to receive parameters, and I'm not being able to properly isolate exemple code to real client so that I can develop my code and call client's operator.

It would be much easier if client was encapsulated in a unique class where I just had to provide its configs (endpoint, authentication, etc) and then call the operator.

Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28
Hikari
  • 3,797
  • 12
  • 47
  • 77

2 Answers2

0

You must put this code before to setRequestHeaders(_call); in the PortTypeSoapBindingStub class

    try {
        SOAPHeaderElement sopElement = new SOAPHeaderElement("urn:AuthenticationInfo","AuthenticationInfo") ;
        sopElement.addChildElement("userName").addTextNode("XXXXX") ;
        sopElement.addChildElement("password").addTextNode("XXXX");
        sopElement.addChildElement("authentication").addTextNode("");
        sopElement.addChildElement("locale").addTextNode("");
        sopElement.addChildElement("timeZone").addTextNode("");

        _call.addHeader(sopElement);

    } catch (Exception e) {
        e.printStackTrace();
    }
Garf365
  • 3,619
  • 5
  • 29
  • 41
Marcos
  • 1
0

I also struggled to achieve the same, later I found the NTLM Authentication wasn't enabled in the mac machine used at server The following code worked for me

public static void testNavisionMicrosoft() {
    static String baseURL = "file:C://locapath//customer.wsdl";
    URL url = null;
    try {
        url = new URL(baseURL);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    URL url2 = null;
    try {
        url2 = new URL("http://localhost:8080/customer?wsdl");
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    try {
        final String username = "user";
        final String password = "paswd";
        Authenticator.setDefault(new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password
                        .toCharArray());
            }
        });

        QName qname = new QName("search for soapActionin your wsdl file",
                "search for service name in wsdl file");

        Service service = Service.create(url, qname);
        CRMCustomerPort proxy = service.getPort(CRMCustomerPort.class);
        Map<String, Object> requestContext = ((BindingProvider) proxy)
                .getRequestContext();
        requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
        requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);

        Map<String, List<String>> headers = new HashMap<String, List<String>>();
        headers.put("Timeout", Collections.singletonList("10000"));
        requestContext.put(MessageContext.HTTP_REQUEST_HEADERS, headers);

        CRMCustomer data = proxy.read("AIL0003190");
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(
                "Error occurred in operations web service client initialization",
                e);
    }
}
PaulG
  • 13,871
  • 9
  • 56
  • 78