“JAX-WS版本不一致导致Webservice异常”与《共享达成共赢》


好吧,我承认这个标题有点不伦不类,只是不想总按常理出牌。

其实在这篇文章中主要描述了jdk与jboss中jax-ws等版本不一致引发的webservice调用异常的解决方案,同时反思自己解决问题的过程,并发出一点点点点“共享达成共赢”的感慨而已。

真的只是一点点。

不啰嗦,先来看问题:

由于项目需要,要使用ESB对一些Webservice进行整合,其中一些Webservice是由ejb发布而成的,部署在jboss中,而另一些是由CXF发布的,部署在tomcat中。


环境:
Mule ESB 3.4
Jboss 5.1.0GA
Tomcat 7.0.39
JDK1.7
CXF 2.7


当在ESB中整合jboss中的Webservice时,ESB端发生如下异常:

Exception in thread "main" org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
 at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:238)
 at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:60)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
 at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1679)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1517)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1425)
 at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
 at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:650)
 at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
 at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:462)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:365)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:318)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:338)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
 at com.jialin.ejb.MyClient.main(MyClient.java:40)
Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
 at [row,col {unknown-source}]: [1,0]
 at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:677)
 at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2116)
 at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2022)
 at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1114)
 at com.ctc.wstx.sr.BasicStreamReader.nextTag(BasicStreamReader.java:1137)
 at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:139)
 ... 17 more


分析异常中的两个关键信息:Error reading XMLStreamReader.和[row,col {unknown-source}]: [1,0]
 
可知,客户端在读取xml时出错了,而且是在第一行第一列出的错误。

所以我猜测,服务端根本没有返回信息。

为了验证自己猜测,我用HTTPLOOK跟踪HTTP请求,结果如下:

request:

POST /test_server_webservice/UserManagerBean HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
SOAPAction: ""
User-Agent: Apache CXF 2.5.9
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:8080
Connection: keep-alive
Content-Length: 200
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:saySomething xmlns:ns1="http://ejb.jialin.com/"><arg0>jialin</arg0></ns1:saySomething></soap:Body></soap:Envelope>

response:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Length: 0
Date: Wed, 11 Dec 2013 11:15:01 GMT


果然返回信息除了报头,什么都没有。所以客户端读xml必然出错。

从request请求的信息来看,客户端编写并没有错误,但是服务端wsdl我也分析过了,没有错误,究竟什么原因呢?
会不会是esb的问题?我又用cxf和axis分别编写了一个客户端,去调用webservice,发现依然报相同的错误。
而我又用esb调用部署在tomcat上由cxf发布的webservice时,调用成功。所以初步断定,是服务端的问题。

打开jboss所在的服务器,发现服务端果然报错,错误信息如下:

ERROR [org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS] (http-127.0.0.1-8080-1) SOAP request exception
java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
 at javax.xml.soap.SOAPMessage.setProperty(SOAPMessage.java:441)
 at org.jboss.ws.core.soap.SOAPMessageImpl.<init>(SOAPMessageImpl.java:87)
 at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:215)
 at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:193)
 at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:455)
 at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:295)
 at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:205)


想到jboss在其他方面运行正常,唯独webservice出现问题,所以将问题锁定在与webservice有关的JAX-WS等包上, 发现
JBoss 5的 Web Service 实现所使用的 JAX-WS 和 JAXB 版本是 2.1,但 JDK6 中带的JAX-WS 与 JAXB 版本却是 2.0,终于发现问题的根源。

版本为jboss-5.1.0.GA-jdk6中的

快捷的办法是将 JDK6 的 JAX-WS 和 JAXB 支持升级到 2.1。其实,这并不需要我们手动去做,jboss5已经为我们做好了。
看下面jboss官网截下来的图,
“JAX-WS版本不一致导致Webservice异常”与《共享达成共赢》_第1张图片

发现jboss-5.1.0.GA和jboss-5.1.0.GA-jdk6两个版本,而带有jdk6的版本中,JBOSS_HOME\lib\endorsed下比另一个版本多了这么几个包:

jbossws-native-jaxrpc.jar
jbossws-native-jaxws.jar
jbossws-native-jaxws-ext.jar
jbossws-native-saaj.jar

这个目录里面放置的jar文件,将有覆盖系统API的功能。可以牵强的理解为,将自己修改后的API打入到虚拟机指定的启动API中,取而代之。


在jboss-5.1.0.GA-jdk6中重新发布webservice后,使用ESB调用,成功。


问题就这么完了吗?没有,独立启动jboss没有问题。

但从eclipse中启动jboss后,在eclipse中部署项目,依然报上述问题。所以我猜测,eclipse中的某种机制,导致JBOSS_HOME\lib\endorsed下的包并没有覆盖jdk中相关包。所以,手动将该文件夹拷贝到java_home/jre/lib下。在eclipse重启jboss,用esb调webservice成功。


问题是解决了,还想多说一点,我在解决这个问题的过程中,走了很多弯路。不得不进行反思 (这也是这个诡异题目的精神所在),同时发点感慨:

当异常发生时,我错以为是客户端的错误,就一个劲的抓住客户端爆出的异常在网上死查,发现了一个很有意思的现象,查到的结果五花八门,有说防火墙问题的,有说编码问题的,有说WebService和Cas的冲突的,有说VMware虚拟网络导致的,有说WSDL命名空间错误的,还有说WSDL地址错误的……等等,我在想,人们为什么会得出这么多种不同的答案,而且还会为正确答案吵来吵去。

其实,这些答案,都有可能导致客户端爆出Unexpected EOF in prolog at [row,col {unknown-source}]: [1,0]的异常,关键并不在这里, 网上很多文章标题就是这个异常,然后跟上“解决方案”四个字,实际上各位都只是看到了引发这一问题的其中一个原因,包括我自己,我们总是站在自己的角度说出自己的观点,而我们的观点并不是错误的,只是不全面而已。

正是因为我们不断地共享自己的观点,分享别人的观点,才能不断接近事物的真实面貌,其实写博客也好,与别人讨论也好,在论坛技术贴灌水也好,都是共享的过程,只有不断地共享,我们大家才能不断地进步,转过来想,这也是博客,论坛,开源等等存在的意义,共享达成共赢。



你可能感兴趣的:(“JAX-WS版本不一致导致Webservice异常”与《共享达成共赢》)