Java调用SOAP Web服务报Could not send Message及404异常咨询
使用Java基于Apache CXF框架调用SOAP Web服务时抛出异常,顶层异常信息如下:
javax.xml.ws.WebServiceException: Could not send Message. at
org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:183)
at
org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145)
at com.sun.proxy.$Proxy83.hastaHizmetVerileriGetir(Unknown Source)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.inte at
org.junit.vintage.engine.VintageTestEngine$$Lambda$361/0000000000000000.accept(Unknown
Source) at
java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:497)
at java.base/ja at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
异常核心根因为HTTP 404错误:
根因:org.apache.cxf.transport.http.HTTPException: 与url.example.com通信时返回HTTP响应'404: Not Found'
对应根因异常栈:
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1619) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1626) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1571) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1371) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:671) at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:63) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314) at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140) ... 53 more
获取服务代理端口的代码如下:
private IESHIstanbul getPort(CortexEvdeSaglikClientContext context, String methodName) { JaxWsProxyFactoryBean serviceProxyFactoryBean = WsUtils.getServiceProxyFactoryBean(IESHIstanbul.class, context.getUrl()); SoapLogInfo soapLogInfo = new SoapLogInfo(); soapLogInfo.setUrl(context.getUrl()); soapLogInfo.setMethodName(methodName); soapHandlerService.getLoggingHandler(soapLogInfo); Object port = serviceProxyFactoryBean.create(); WsUtils.setServiceEndPoint(port, context.getUrl()); return (IESHIstanbul) port; }
404错误本质是客户端发起请求的目标路径在服务端不存在,按以下优先级排查即可:
- 校验服务端点URL准确性
- 禁止直接把带
?wsdl后缀的元数据地址当成服务调用地址,?wsdl仅用于获取服务描述元数据,实际调用端点要以WSDL文件内<soap:address location="xxx">标签配置的地址为准 - 逐字符核对配置的URL,确认端口、上下文路径、服务路径没有拼写错误,和服务提供方给出的正式地址完全一致
- 直接用SOAP UI、Postman等工具填入配置的URL,发送格式正确的SOAP请求,先确认地址本身可正常访问,排除服务端路径下线、网关路由配置错误的问题
- 禁止直接把带
- 检查CXF代理配置逻辑
- 排查
WsUtils.getServiceProxyFactoryBean和WsUtils.setServiceEndPoint两个工具方法的内部实现,确认不存在重复拼接路径、自动追加错误后缀的问题——比如创建代理时已经根据服务类注解拼接了一层服务路径,后续设置端点时又重复追加路径,会导致最终请求路径变成类似http://domain/service/service的错误格式,触发404 - 开启CXF的DEBUG级别日志,直接查看框架实际发出的HTTP请求完整路径,和预期地址做对比,快速定位路径拼接错误
- 排查
- 检查网络与网关配置
- 如果服务通过反向代理、API网关暴露,确认网关已正确放行SOAP POST请求,部分网关配置错误时会将不匹配路由规则的POST请求直接返回404
- 检查HTTP Conduit配置,确认没有错误配置重定向规则、全局路径前缀,避免请求被转发到错误地址
- 校验服务端运行状态
- 确认服务端对应SOAP服务已正常启动、接口路径成功注册,部分应用启动时如果SOAP服务初始化失败,会出现端口可连通但对应接口路径返回404的情况
内容的提问来源于stack exchange,提问作者hsynuls

