关于jdk8升级jdk21 cxf报错的踩坑记录

 更新时间:2024年10月09日 09:14:46   作者:照猫画狐  
在升级Java项目时,从JDK1.8和Spring2迁移到JDK21和Spring3后,遇到了JAXBException错误,原因是从JDK11开始移除了jaxb模块,而cxf在编译动态客户端时默认classpath不包含必要的类,解决方法是在jar包同级目录创建libs并添加jakarta.xml.bind-api

项目场景

听说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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot中Mockito单元测试入门

    SpringBoot中Mockito单元测试入门

    单元测试在很多地方都用的到,本文主要介绍了SpringBoot中Mockito单元测试入门,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • 教你怎么用Java完成人民币大写转化

    教你怎么用Java完成人民币大写转化

    这篇文章主要介绍了教你怎么用Java完成人民币大写转化,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-04-04
  • Java8深入学习之熟透Optional

    Java8深入学习之熟透Optional

    这篇文章主要给大家介绍了关于Java8深入学习之熟透Optional的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java8具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Java8新特性stream和parallelStream区别

    Java8新特性stream和parallelStream区别

    这篇文章主要介绍了Java8新特性stream和parallelStream区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 二叉树递归迭代及morris层序前中后序遍历详解

    二叉树递归迭代及morris层序前中后序遍历详解

    这篇文章主要为大家介绍了二叉树递归迭代详解及二叉树的morris遍历、层序遍历、前序遍历、中序遍历、后序遍历示例分析,有需要的朋友可以借鉴参考下
    2021-11-11
  • Java包装类之自动装箱与拆箱

    Java包装类之自动装箱与拆箱

    这篇文章主要介绍了Java包装类之自动装箱与拆箱,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Spring boot Rabbitmq消息防丢失实践

    Spring boot Rabbitmq消息防丢失实践

    这篇文章主要介绍了Spring boot Rabbitmq消息防丢失实践,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Java实现根据模板自动生成新的PPT

    Java实现根据模板自动生成新的PPT

    这篇文章主要介绍了如何利用Java代码自动生成PPT,具体就是查询数据库数据,然后根据模板文件(PPT),将数据库数据与模板文件(PPT),进行组合一下,生成新的PPT文件。感兴趣的可以了解一下
    2022-02-02
  • 详细总结Java基础类和包装类

    详细总结Java基础类和包装类

    近几天一直在复习Java基础知识,今天就带大家总结一下Java基础类和包装类,下文中有非常详细的代码示例,对正在学习Java基础的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • java isInterrupted()判断线程的实例讲解

    java isInterrupted()判断线程的实例讲解

    在本篇内容里小编给大家分享的是一篇关于java isInterrupted()判断线程的实例讲解内容,有兴趣的朋友们可以学习下。
    2021-05-05

最新评论