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

在使用Java开发WebService时遇到一个错误,表现为com.sun.xml.bind.v2.runtime.JAXBContextImpl无法被转换为com.sun.xml.internal.bind.api.JAXBContext。尝试删除冲突的JAR文件、升级JDK或修改POM配置均未解决问题。最终发现,通过在客户端调用时设定QNAME的namespace可以避免该错误。解决方案包括在handler-chain.xml配置文件中进行设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

java.lang.ExceptionInInitializerError
	at 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.JAXBRIContext
	at 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 more
17: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> {

	@Override
	public 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;
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void close(MessageContext context) {
		// TODO Auto-generated method stub
	}

	@Override
	public Set<QName> getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}

}

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值