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?):
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();
} else {
call = (org.apache.axis.client.Call) createCall(portName);
}
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));
}
}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?
Math.wsdl
Description: Math.wsdl
