"Cannot find child element" error when calling JBoss Web Service from Visual FoxPro
我遇到了这个问题。我使用 Seam 框架创建了一个在 JBoss 5 之上运行的 Web 服务。 Web 服务有一个称为"登录"的方法。当我从 Java 客户端使用服务时,它工作正常,但是当我尝试从 Visual FoxPro 客户端(我真正需要)使用时,我收到一条错误消息:
1 |
来自 JBoss 的错误堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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) |
我的网络服务类:
1 2 3 4 5 6 7 8 9 10 11 12 | @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; } } |
来自
的 WSDL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <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> |
客户端代码(使用 MS Soap Toolkit 3.0):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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 |
客户端代码(使用 PocketSOAP):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 |
我一直在寻找关于为什么会发生这种情况的解释,但没有找到。我尝试了在谷歌搜索时发现的几件事:我将具有相应值的命名空间属性添加到 @WebParam 注释中,添加了带有名称和命名空间的 @WebResult 注释,将 SOAP 绑定从 RPC 更改为 Document,但都无济于事。非常感谢您在这里给我的任何帮助。
编辑:我们放弃了 SOAP 服务,现在使用 REST 服务,我们发现它更易于从 Visual Fox 中使用,无需任何桥接应用程序。
没关系。通过 ASP.NET WS 转发 Java WS,并让 VFP 客户端使用它。它有效。