I'm having this problem. I created a Web Service that runs on top of JBoss 5, using the Seam Framework. The web service has a single method called "login". When I consume the service from a Java client, it works fine, but when I try to consume from a Visual FoxPro client (my real need), I get an error message:
Error 1429 - OLE IDispatch exception code 0 from ?: Cannot find child element: username
The error stacktrace from JBoss:
12:02:32,396 ERROR [SOAPFaultHelperJAXWS] SOAP request exception
org.jboss.ws.WSException: Cannot find child element: username
at org.jboss.ws.core.CommonSOAPBinding.getParameterFromMessage(CommonSOAPBinding.java:917)
at org.jboss.ws.core.CommonSOAPBinding.unbindRequestMessage(CommonSOAPBinding.java:361)
at org.jboss.ws.core.server.ServiceEndpointInvoker.invoke(ServiceEndpointInvoker.java:197)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:474)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:295)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:205)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:131)
at org.jboss.wsf.common.servlet.AbstractEndpointServlet.service(AbstractEndpointServlet.java:85)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source)
My web service class:
@Name("ServiceName")
@WebService(name = "ServiceName", serviceName = "ServiceName")
@SOAPBinding(style = SOAPBinding.Style.RPC)
@Stateless
public class ServiceName implements ServiceNameRemote {
@WebMethod
@Override
public boolean login(@WebParam(name = "username") String username, @WebParam(name = "password") String password) {
// logic..
return result;
}
}
The WSDL from localhost:8080/app-app/ServiceName?wsdl
<definitions name="ServiceName"
targetNamespace="http://service.namespace/"
xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://service.namespace/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types />
<message name="ServiceName_login">
<part name="username" type="xsd:string" />
<part name="password" type="xsd:string" />
</message>
<portType name="ServiceName">
<operation name="login" parameterOrder="username password">
<input message="tns:ServiceName_login" />
<output message="tns:ServiceName_loginResponse" />
</operation>
</portType>
<binding name="ServiceNameBinding" type="tns:ServiceName">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="login">
<soap:operation soapAction="" />
<input>
<soap:body namespace="http://service.namespace/"
use="literal" />
</input>
<output>
<soap:body namespace="http://service.namespace/"
use="literal" />
</output>
</operation>
</binding>
<service name="ServiceName">
<port binding="tns:ServiceNameBinding" name="ServiceNamePort">
<soap:address
location="http://localhost:8080/app-app/ServiceName" />
</port>
</service>
</definitions>
Client code (Using MS Soap Toolkit 3.0):
LOCAL loServiceNamePort AS "XML Web Service"
* LOCAL loServiceNamePort AS "MSSOAP.SoapClient30"
* Do not remove or alter following line. It is used to support IntelliSense for your XML Web service.
*__VFPWSDef__: loServiceNamePort = http://localhost:8080/app-app/ServiceName?wsdl , ServiceName , ServiceNamePort
LOCAL loException, lcErrorMsg, loWSHandler
TRY
loWSHandler = NEWOBJECT("WSHandler",IIF(VERSION(2)=0,"",HOME()+"FFC\")+"_ws3client.vcx")
loServiceNamePort = loWSHandler.SetupClient("http://localhost:8080/app-app/ServiceName?wsdl", "ServiceName", "ServiceNamePort")
* Call your XML Web service here. ex: leResult = loServiceNamePort.SomeMethod()
MESSAGEBOX(loServiceNamePort.login("username", "password"))
CATCH TO loException
lcErrorMsg = "Error: "+TRANSFORM(loException.Errorno)+" - "+loException.Message
DO CASE
CASE VARTYPE(loServiceNamePort)#"O"
* Handle SOAP error connecting to web service
WAIT WINDOW "Error connecting to web service" NOWAIT
CASE !EMPTY(loServiceNamePort.FaultCode)
* Handle SOAP error calling method
lcErrorMsg = lcErrorMsg + CHR(13) + loServiceNamePort.Detail
WAIT WINDOW "SOAP error calling method" NOWAIT
OTHERWISE
* Handle other error
ENDCASE
* Use for debugging purposes
MESSAGEBOX(lcErrorMsg)
FINALLY
ENDTRY
Client code (using PocketSOAP):
LOCAL loException, lcErrorMsg, loFactory, loProxy
TRY
loFactory = createObject("pocketsoap.Factory")
loProxy = loFactory.CreateProxy("http://localhost:8080/app-app/ServiceName?wsdl", "http://service.namespace/")
MESSAGEBOX(loProxy.login("username", "password"))
CATCH TO loException
lcErrorMsg = "Error: "+TRANSFORM(loException.Errorno)+" - "+loException.Message
DO CASE
CASE VARTYPE(loServiceNamePort)#"O"
* Handle SOAP error connecting to web service
WAIT WINDOW "Error connecting to web service" NOWAIT
CASE !EMPTY(loServiceNamePort.FaultCode)
* Handle SOAP error calling method
lcErrorMsg = lcErrorMsg + CHR(13) + loServiceNamePort.Detail
WAIT WINDOW "SOAP error calling method" NOWAIT
OTHERWISE
* Handle other error
ENDCASE
* Use for debugging purposes
MESSAGEBOX(lcErrorMsg)
FINALLY
ENDTRY
I've been looking for an explanation as to why this happens, but haven't found it. I tried several things I found when googling: I added the namespace attribute with the corresponding value to the @WebParam annotations, added the @WebResult annotation with name and namespace, changed the SOAP binding from RPC to Document, all to no avail. Any help you can give me here is really appreciated.
EDIT: We ditched the SOAP services and now are using REST services, which we found easier to consume from Visual Fox, without the need for any bridge application.
Nevermind. Forwarded the Java WS through an ASP.NET WS, and made the VFP client consume it. It works.