You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by Mike Perham <Mi...@webifyinc.com> on 2003/08/11 20:33:54 UTC

Axis service bug?

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?