关于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

总结

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

相关文章

  • java8 stream多字段排序的实现

    java8 stream多字段排序的实现

    这篇文章主要介绍了java8 stream多字段排序的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 浅谈SpringBoot项目打成war和jar的区别

    浅谈SpringBoot项目打成war和jar的区别

    这篇文章主要介绍了浅谈SpringBoot项目打成war和jar的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 浅析JavaWeb项目架构之Redis分布式日志队列

    浅析JavaWeb项目架构之Redis分布式日志队列

    架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Redis做消息队列罢了。下面通过本文给大家分享JavaWeb项目架构之Redis分布式日志队列,感兴趣的朋友一起看看吧
    2018-01-01
  • javaweb图书商城设计之购物车模块(3)

    javaweb图书商城设计之购物车模块(3)

    这篇文章主要为大家详细介绍了javaweb图书商城设计之购物车模块的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Java利用位运算实现比较两个数的大小

    Java利用位运算实现比较两个数的大小

    这篇文章主要为大家介绍了,在Java中如何不用任何比较判断符(>,==,<),返回两个数( 32 位整数)中较大的数,感兴趣的可以了解一下
    2022-08-08
  • 如何在Java中调用python文件执行详解

    如何在Java中调用python文件执行详解

    丰富的第三方库使得python非常适合用于进行数据分析,最近在项目中就涉及到java调用python实现的算法,下面这篇文章主要给大家介绍了关于如何在Java中调用python文件执行的相关资料,需要的朋友可以参考下
    2022-05-05
  • Spring内部bean和级联属性用法详解

    Spring内部bean和级联属性用法详解

    这篇文章主要介绍了Java内部bean和级联属性用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • MyBatis-plus中的模糊查询解读

    MyBatis-plus中的模糊查询解读

    这篇文章主要介绍了MyBatis-plus中的模糊查询解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • java.lang.OutOfMemoryError: Metaspace异常解决的方法

    java.lang.OutOfMemoryError: Metaspace异常解决的方法

    这篇文章主要介绍了java.lang.OutOfMemoryError: Metaspace异常解决的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java中String类getBytes()方法详解与完整实例

    Java中String类getBytes()方法详解与完整实例

    这篇文章主要给大家介绍了关于Java中String类getBytes()方法详解与完整实例的相关资料,getBytes()是Java编程语言中将一个字符串转化为一个字节数组byte[]的方法,需要的朋友可以参考下
    2023-10-10

最新评论