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 + ";");
下面提供一个示例程序,仅供参考。大佬们如果有更好的解决方案,欢迎提出交流。
参考链接:
[CXF-7932] JaxWsDynamicClientFactory in Spring Boot fat JAR with JDK11 leads to JAXBException ... doesnt contain ObjectFactory.class or jaxb.index - ASF JIRA
[CXF-7925] Dynamic WSDL Client creation fails on JDK 11 because it cannot compile generated classes - ASF JIRA
转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34680736/article/details/137404102