关于jdk8升级jdk21 cxf报错的踩坑记录
作者:照猫画狐
项目场景
听说jdk21有很多实用新特性,就想弄个玩玩,闲来无事把公司项目从spring2+jdk1.8直升到spring3+jdk21,折腾两天升级完了,本以为就这么简单结束了。
直到把项目发布到服务器测试调用第三方接口,一直报错:
jakarta.xml.bind.JAXBException: "com.xx.xx" 不包含 ObjectFactory.class 或 jaxb.index
各种百度,翻看源码,折腾两个星期也未能解决问题,一度想要放弃。
经过这么长时间折腾,我发现在IDEA中调用接口就不会报错,一旦打成jar使用java -jar执行就一定会报错,这一定是jvm环境问题!
我用jconsole连接两种不同场景下的jvm,经过自己反复对比调试,终于发现了问题所在。
问题描述
使用cxf创建动态客户端时报错:
jakarta.xml.bind.JAXBException: "com.xx.xx" 不包含 ObjectFactory.class 或 jaxb.index
// 创建动态客户端 JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient(addr); client.invoke(methodName, param);
原因分析
从jdk11起移除了jaxb模块,cxf编译动态客户端代码时,默认的classpath为java.class.path
当打包成jar后,java.class.path指定的目录就是当前运行的jar
由于jdk11也移除了rt.jar、tool.jar,cxf编译动态客户端java文件时,会因为找不到依赖的jar包报错
解决方案
1. 在jar包同级目录下新建一个libs目录,放入jakarta.xml.bind-api-4.0.2.jar
2. 项目启动时,把cxf编译动态客户端所依赖的jar包添加到java.class.path中。
// 获取当前jar所在目录 String jarPath = (System.getProperty("user.dir")).replaceAll("\\\\", "/").replace("file:/", "/"); String classPath = jarPath + "/libs/jakarta.xml.bind-api-4.0.2.jar"; // 因为从jdk11起移除了jaxb模块,cxf编译动态客户端代码时,默认的classpath为java.class.path,由于jdk11也移除了rt.jar、tool.jar,会导致编译异常,报错: // jakarta.xml.bind.JAXBException: "com.xx.xx" 不包含 ObjectFactory.class 或 jaxb.index System.setProperty("java.class.path", System.getProperty("java.class.path") + ";" + classPath + ";");
上面提供的示例程序,仅供参考
参考链接
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。