使用不正确的 wsdl 访问 SOAP Web 服务
背景:
我需要使用现有的 Web 服务(基于 http 的 SOAP),该服务有几个问题:
1)服务器上的 wsdl 甚至与文档中描述的 Web 服务不同,其中包含完全不同的 wsdl 文件
2)他们的文档提供的wsdl文件似乎很接近描述服务器上的Web服务,但是当我使用cxf生成java客户端代码并用它来访问Web服务时,cxf抛出如下异常
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://us-labs.companyxyz.com/", local:"searchResponse"). Expected elements are <{http://companyxyz.com/xyz-xml/2.0/}searchResponse>
... 33 more
我不SOAP 专家,但假设这意味着他们响应中的名称空间与 wsdl 中定义的名称空间不匹配。
由于我的应用程序是用 java 编写的,因此我能够使用 commons http 客户端和手工制作的 SOAP 请求进行连接并获取响应,因此最坏的情况我可以回退到该状态并解析响应以获得我需要的内容。
我的问题:
- 我是否正确解释了异常?
- 如果没有:关于如何调试这个问题有什么建议吗?
- 如果是的话:有人可以建议更好的替代方案来手工制作 http 请求并手工解析 xml 吗? (不幸的是,无法获得正确的 wsdl)
提前致谢。
Background:
I need to consume an existing web service (SOAP over http) that has a couple of issues:
1) The wsdl on the server doesn't even resemble the web service as described in their documentation, which includes a completely different wsdl file
2) The wsdl file provided with their documentation seems to come close to describing the web service on the server, but when I generated java client code using cxf and used it to access the web service, cxf throws exceptions like the following
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://us-labs.companyxyz.com/", local:"searchResponse"). Expected elements are <{http://companyxyz.com/xyz-xml/2.0/}searchResponse>
... 33 more
I'm no SOAP expert, but assuming this means the namespaces in their response don't match those defined in the wsdl.
Since my application is written in java, I was able to connect and get a response using commons http client and a handcrafted SOAP request, so worst case I can fall back to that and parse the response to get what I need.
My questions:
- Did I interpret the exception correctly?
- If no: any suggestions on how I can debug this?
- If yes: can anyone suggest better alternatives to handcrafting http requests and parsing xml by hand? (Getting correct wsdl is, unfortunately, not an option)
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
很有可能。响应使用名称空间“http://us-labs.companyxyz.com/”,但在 WSDL 中,使用名称空间“http://companyxyz.com/xyz-xml/2.0/”声明相同的元素。
我不熟悉 CXF,但其他 SOAP 框架通常提供某种日志记录功能。如果将 SOAP 请求和响应记录在某处以进行更具体的分析,这可能会对您有所帮助。
为什么不能选择获取正确的 WSDL?如果您确实能够“手工制作”正确的 SOAP 请求并期望能够“手工解析”响应,那么您也应该能够自己编写 WSDL。当然,WSDL 应该由服务运营商提供给您,但如果您的意思是没有人能够为您提供正确的 WSDL,我会考虑自己编写它,而不是手动创建和解析 SOAP 消息。
Most likely. The response is using the namespace "http://us-labs.companyxyz.com/", but in the WSDL, the same element is declared with namespace "http://companyxyz.com/xyz-xml/2.0/".
I'm not familiar with CXF, but other SOAP frameworks usually offer some kind of logging capabilities. It would probably help you if the SOAP requests and responses are logged somewhere for more specific analysis.
Why is it not an option to get a correct WSDL? If you really are able to "handcraft" correct SOAP requests and expect to be able to "handparse" the responses, you should be able to write the WSDL yourself as well. Of course, the WSDL should be provided to you by the service operator, but if you mean that noone is able to provide you with a correct WSDL, I would consider writing it myself instead of creating and parsing the SOAP messages manually.
我认为您正确解释了异常 - 命名空间与预期不同。
这也并不出人意料。供应商提供的 wsdls 并不总是正确的,这是不争的事实。实际上,出于这个原因,我们为供应商应用程序编写了自己的 WSDL 和 XSD。
您甚至可以在运行时使用自己的 WSDL。有一些关于此的问题,这里和此处。
您还可以看看 此处。我没试过,但它可以工作。
我们实际上扩展了生成的服务,并使用 JaxWS 服务构造函数。这对我们来说效果很好。
我们通过转储传入和传出消息来调试 CXF。似乎有很多方法可以做到这一点。我们在 Web 服务和客户端之间使用代理,或者最近在某处使用 cxf.xml 文件。使用 -D 标志我们临时配置它。
并且 cxf-debug.xml 包含一些类似:
http://cxf.apache.org/docs/debugging-and-logging.html
I think you interpreted the exception correctly - the namespace is different than expected.
It is also not really unexpected. it is a fact of life that vendor supplied wsdls are not always correct. We actually write our own WSDLs and XSDs for vendor applications for just that reason.
You can use your own WSDL even run-time. There are some SO questions on that, here and here.
You could also have a look here. I haven't tried it, but it could work.
We actually extend the generated service and create a port supplying a WSDL located on the classpath using the JaxWS Service constructor. That works fine for us.
We debug CXF by dumping the incoming and outgoing messages. There seem to be quite a lot of methods to do just that. We use either a proxy between de web service and our client, or recently a cxf.xml file somewhere. Using a -D flag we temprarily configure this.
and cxf-debug.xml contains something like:
http://cxf.apache.org/docs/debugging-and-logging.html
两种回应都提出了相同的基本方法,事实证明这是正确的。
我修复了提供的 wsdl 以使其与 Web 服务匹配,并且我能够使用 cxf,这节省了我大量的手动编码工作。
他们的 wsdl 的主要问题实际上是名称空间问题。问题的本质如下:他们的 wsdl 定义了两个名称空间,两个名称空间都有一个“searchResponse”元素。
在 wsdl 中定义为包含 0 个或多个
但在其响应中,嵌套的 searchResponse 未由
{http://companyxyz.com/xyz-xml/2.0/}
限定,因此 cxf 将其解释为a{http://us-labs.companyxyz.com/}searchResponse
我通过引入一种新类型来修复它。
感谢两位回复者。
Both responses suggested the same basic approach, which turned out to be the correct one.
I fixed the provided wsdl to make it match the web service, and I was able to use cxf, which saved me a lot of hand coding.
The main problem with their wsdl was in fact a namespace issue. The essence of the problem was as follows: their wsdl defined two namespaces, both of which have a "searchResponse" element.
was defined in the wsdl to contain 0 or more
But in their response the nested searchResponse wasn't qualified by
{http://companyxyz.com/xyz-xml/2.0/}
so cxf interpreted it as a{http://us-labs.companyxyz.com/}searchResponse
I fixed it by introducing a new type.
Thanks to both responders.