Title: Message
Doug and all, I'm trying to debug some client side code which is generating incorrect SOAP with rpc/literal WSDL.  Here's how the code is being called:
 
 
    String endpoint = "http://localhost:8080/axis/services/Math";
    URL wsdl = MathClient.class.getResource("Math.wsdl");
    ServiceFactory sf = (ServiceFactory) ServiceFactory.newInstance();
    Service svc = (Service) sf.createService(wsdl, new QName("urn:mike:types", "MathServiceService"));
    Math math = (Math) svc.getPort(endpoint, perham.test.Math.class);
    int ret = math.add(4, 5);
    System.out.println("4 + 5 = " + ret);
 
When I call it that way, I get this SOAP:
<add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <arg0 xsi:type="xsd:int">4</arg0>
  <arg1 xsi:type="xsd:int">5</arg1>
</add>
When I change the getPort() line to this:
 
    Math math = (Math) svc.getPort(perham.test.Math.class); // no endpoint
 
I get this SOAP instead which looks more correct but is still wrong (specifically I believe it is incorrect to specify type when using literal?):
<ns1:add xmlns:ns1="urn:mike:types">
  <a xsi:type="xsd:int" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">4</a>
  <b xsi:type="xsd:int" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">5</b>
</ns1:add>
Now my understanding of what is happening here is that inside the getPort(String, Class) call, the portName is null so the Call essentially "loses" the WSDL that the service knows about and so must fall back to defaults when generating the message (apparently rpc/encoded).  I also noticed there is a private method Service.getPort(String, QName, Class) that takes the portName so that it could potentially be specified by a caller. 
 
So my questions:
 
1. Why is the private method hidden?  Should it be exposed and my client code changed? 
2. Should getPort(String, null, Class) try to see if there is only one Port defined in the WSDL and if so, use it?
3. Why can't we specify both the portName and the target endpoint address so we can do dynamic endpoints (i.e. for load balancing, etc)?
 
I wrote the code for (2):
 
            Call call = null;
            if (portName == null) {
                // if the wsdl service only has a single port, use it
                if (wsdlService != null && wsdlService.getPorts().size() == 1) {
                    String pname = (String) wsdlService.getPorts().keySet().iterator().next();
                    String ns = wsdlService.getQName().getNamespaceURI();
                    call = (org.apache.axis.client.Call) createCall(new QName(ns, pname));
                } else {
                    call = (org.apache.axis.client.Call) createCall();
                    if (endpoint != null) {
                        call.setTargetEndpointAddress(new URL(endpoint));
                    }
                }
            } else {
                call = (org.apache.axis.client.Call) createCall(portName);
            }
 
It now generates this:
<add xmlns="urn:mike:types">
  <a xmlns="">4</a>
  <b xmlns="">5</b>
</add>
which is closer to the SOAP that I believe should be generated:
<ns0:add xmlns:ns0="urn:mike:types">
  <ns0:a>4</ns0:a>
  <ns0:b>5</ns0:b>
</ns1:add>
Thoughts?

Attachment: Math.wsdl
Description: Math.wsdl

Reply via email to