webservice:com.sun.xml.bind.v2.runtime.JAXBContextImpl cannot be cast to com.sun.xml.internal.bind.a

来源:互联网 发布:新余学院网络公选课 编辑:程序博客网 时间:2024/06/05 06:47

用原生jdk开发好webservice服务端接口后,和客户端联调的过程中调不通,服务端报错:

java.lang.ExceptionInInitializerErrorat com.sun.xml.internal.ws.wsdl.PayloadQNameBasedOperationFinder.getWSDLOperationQName(PayloadQNameBasedOperationFinder.java:140)at com.sun.xml.internal.ws.wsdl.OperationDispatcher.getWSDLOperationQName(OperationDispatcher.java:76)at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:84)at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:626)at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:585)at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:570)at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:467)at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:299)at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:593)at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:244)at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95)at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80)at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:649)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)at java.lang.Thread.run(Thread.java:745)Caused by: java.lang.ClassCastException: com.sun.xml.bind.v2.runtime.JAXBContextImpl cannot be cast to com.sun.xml.internal.bind.api.JAXBRIContextat com.sun.xml.internal.ws.fault.SOAPFaultBuilder$1.run(SOAPFaultBuilder.java:570)at com.sun.xml.internal.ws.fault.SOAPFaultBuilder$1.run(SOAPFaultBuilder.java:566)at java.security.AccessController.doPrivileged(Native Method)at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createJAXBContext(SOAPFaultBuilder.java:565)at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.<clinit>(SOAPFaultBuilder.java:555)... 21 more17:44:05.222 [schedulerFactoryBean_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 0 triggers

网上查了好久,大部分都说是因为jaxb-api.jar和Jaxb-impl,jar冲突导致的,大致有以下几种解决方式:

1.删掉lib目录下的jaxb-api.jar和Jaxb-impl.jar;

2.把jdk升级到1.6以上版本;

3.在工程(我用的maven建的工程)的pom.xml中增加

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><systemPropertyVariables><com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize>true</com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize></systemPropertyVariables></configuration></plugin>
以上方式我都尝试了但都无效,我用的maven搭建的工程,为此还折腾了各种版本的引用包均无效。

最后,尝试直接在webservice发布时就设置:

System.setProperty("javax.xml.bind.JAXBContext", "com.sun.xml.internal.bind.v2.ContextFactory");
webservice服务器端倒是不报错了,但是客户端依然调不通,报错说找不到匹配的方法。




然后,又是一番折腾,基本上都说是webservice内部jar版本与现在所用的jdk的jar有冲突,问题依然没有解决。

后来发现如果客户端调用的时候设置了QNAME的namespace就可以绕过此错误,附上客户端调用的关键代码:

Call call = null;try {call = (Call)service.createCall();call.setTargetEndpointAddress(new URL("http://localhost:8081/UserService?wsdl"));call.setProperty("axis.connection.timeout", new Integer(3600000));call.setTimeout(new Integer(3600000));call.setOperationName(new javax.xml.namespace.QName("http://webservice.web.demo.com/", "queryUsers")); //用这句可以正常调用//call.setOperationName("queryUsers");//用这句就报错说找不到匹配的方法Object res=call.invoke(new Object[]{});PrintWriter out = response.getWriter();out.println(res);}catch (Exception e) {e.printStackTrace();}

如果不想改客户端的调用代码,也可添加拦截器拦截webservice请求,拦截后判断namespace是否存在不存在则加上,方法如下:

在classpath下建handler-chain.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>  <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"      xmlns:xsd="http://www.w3.org/2001/XMLSchema">      <javaee:handler-chain>          <javaee:handler>          <!-- 拦截器类的包名和类名路径 -->            <javaee:handler-class>com.xxx.xxx.web.service.WebservicePhaseInterceptor</javaee:handler-class>          </javaee:handler>      </javaee:handler-chain>  </javaee:handler-chains>  

在webservice的实现类上加HandlerChain配置:

@HandlerChain(file="handler-chain.xml")public class UserWebServiceImpl implements UserWebService {/**代码省略**/}

SOAPHandler实现拦截请求并加namespace的类:

package com.xxx.xxx.web.service;import java.util.Iterator;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPElement;import javax.xml.soap.SOAPMessage;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;import org.apache.commons.lang3.StringUtils;public class WebservicePhaseInterceptor implements SOAPHandler<SOAPMessageContext> {@Overridepublic boolean handleMessage(SOAPMessageContext context) {try {SOAPMessage msg = context.getMessage();SOAPBody body = msg.getSOAPBody();Iterator<?> iter = body.getChildElements();while (iter.hasNext()) {Object next = iter.next();if (next instanceof SOAPElement) {SOAPElement se = (SOAPElement) next;String uri = se.getNamespaceURI();if (StringUtils.isBlank(uri)) {QName name = se.getElementQName();QName qName = new QName("你的namespaceURI,在wsdl文件中可以看到", name.getLocalPart());se.setElementQName(qName);}}}} catch (Exception ex) {ex.printStackTrace();}return true;}@Overridepublic boolean handleFault(SOAPMessageContext context) {// TODO Auto-generated method stubreturn false;}@Overridepublic void close(MessageContext context) {// TODO Auto-generated method stub}@Overridepublic Set<QName> getHeaders() {// TODO Auto-generated method stubreturn null;}}

拦截器的实现,参考了http://blog.csdn.net/accountwcx/article/details/46986943,感谢。

目的虽然达到了,问题也绕过去了,客户端调用成功,但是问题依然没有从根本上解决。我实在想不到好的解决方式了,如果有解决方法还请不吝留言告知哦,感激不尽。

0 0