C# 调用soap接口时 No binding operation info while invoking unknown method with params unknown
2021-08-04 15:16:18
与其他部门有个常规的 WebService 接口,对方提供服务,这边调用。像往常一样,使用 cxf 生成了客户端的代码并调用,开发的过程中并没有遇到什么问题,测试也没发现问题。然而一个礼拜之后正式上线的生产环境中,客户端调用接口总是抛出异常
服务器发送了 HTTP 状态代码 302: Moved Temporarily
。
@Test
public void test() throws Exception {
URL url = new URL("https://home.winning.com/web-service/cxf/findReportEntity?wsdl");
ReportEntityService service = new ReportEntityServiceImplService(url)
.getReportEntityServiceImplPort();
ReportEntity res = service.findOne("");
System.out.println(res.getEnterpirseName());
com.sun.xml.internal.ws.client.ClientTransportException: 服务器发送了 HTTP 状态代码 302: Moved Temporarily
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:310)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:259)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:217)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:130)
at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:95)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:1121)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:1035)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:1004)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:862)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:448)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:178)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147)
at com.sun.proxy.$Proxy32.findOne(Unknown Source)
at SkytechTest.test(SkytechTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
检查了下配置的 URL 发现,实际配置的地址是HTTPS形式的。因为测试环境与生产环境的配置都是一样的,除了URL,测试环境是直接通过 IP 访问的。基本上可以确定问题就出在HTTPS上了。初步判断,应该是对方在生产环境中使用了 nginx 做了反向代理,并且开启了 SSL,导致访问接口的时候被重定向了。但是,wsdl
是可以通过 https 访问的,这就有些奇怪了。 为了排查问题,用C# 快速写了一个测试程序:
ReportEntityServiceClient client = new ReportEntityServiceClient();
reportEntity report = client.findOne("");
Console.WriteLine(report.enterpirseName);
catch (Exception ex)
Console.WriteLine(ex.Message);
同样抛出了异常,异常消息与 Java 有些不同, No binding operation info while invoking unknown method with params unknown.
, 将 app.config
文件中的 endpoint address
节点修改为 https, 运行提示:提供的 URI 方案“https”无效,应为“http”。参数名: via
问题可以确定,就是 https 导致的问题。通过 Wireshark 抓包来看,接口调用请求的为 http,虽然配置的 URL 是 https 但是实际上调用的其实是 http。
如果 WebService 调用可以设置代理,把代理地址设置成 https 应该就能解决问题。 经过一番 Google 貌似找到一个解决方法, 通过 BindingProvider
拿到请求上下文,添加 BindingProvider.ENDPOINT_ADDRESS_PROPERTY
:
@Test
public void test() throws Exception {
String wsdlLocation = "https://home.winning.com/web-service/cxf/findReportEntity?wsdl";
URL url = new URL(wsdlLocation);
ReportEntityService service = new ReportEntityServiceImplService(url)
.getReportEntityServiceImplPort();
((BindingProvider) service).getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlLocation);
ReportEntity res = service.findOne("");
System.out.println(res.getEnterpirseName());
问题就这么解决了,只需要添加一行代码就搞定了。对于 .NET 需要修改 app.config
, 在 binding
节点中添加 security
配置,并且将 endpoint address
节点修改为 https。详细配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ReportEntityServiceImplServiceSoapBinding" >
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://home.winning.com/web-service/cxf/findReportEntity"
binding="basicHttpBinding" bindingConfiguration="ReportEntityServiceImplServiceSoapBinding"
contract="ServiceReference.ReportEntityService" name="ReportEntityServiceImplPort" />
</client>
</system.serviceModel>
</configuration>
BindingProvider
定义了获取 request 与 response 上下文 (context)的方法,context 是一个 Map, 可以设置一些属性。 除了 ENDPOINT_ADDRESS_PROPERTY
以外,还有 USERNAME_PROPERTY
、PASSWORD_PROPERTY
等属性。 参考 Purpose of BindingProvider in JAX-WS web service
2021-01-08 10:43:03.718 WARN 4912 --- [nio-8080-exec-1] o.a.cxf.phase.PhaseInterceptorChain : Interceptor for {http://webservice.leftso.com/}RmsWebServiceImplService has thrown exception, unwinding now
org.a.
警告: Interceptor for {http://test.cxf.atguigu.com/}HelloWorldImplService has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: No binding operation info while invoking unknown method with params unknown.
at org...
1.1 WebService是什么
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。
Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换
本人这两天在学WebService.按照教学视频里的教程尝试做了一个最简单的Demo,但出现了一下问题。百思不得其解,在网上找了很久也没有找到答案。故此在这里发帖求各位大神指点下。
下面是问题描述:
照理说能访问到wsdl文件就说明web Service 已发布出去了,定义的接口也能调用,SOAP Request Envelope和SOAP Response Envelope应
1. Demo (转载 http://mushme.iteye.com/blog/1776078)cxf的官网文档地址:http://cxf.apache.org/docs/ 1.建立一个web project,名称为cfx-new,部署目录写成ROOT 2.下载最新的cxf包http://cxf.apache.org/download.html,我下载的是apache-cxf-2.5.2.zip...
CXF发布webservice之后访问报错:
org.apache.cxf.interceptor.Fault: No binding operation info while invoking unknown method with params unknown.
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(A...