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

总结

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

相关文章

  • SpringSecurity框架下实现CSRF跨站攻击防御的方法

    SpringSecurity框架下实现CSRF跨站攻击防御的方法

    CSRF是一种网络攻击方式,也可以说是一种安全漏洞,这种安全漏洞在web开发中广泛存在。这篇文章主要介绍了SpringSecurity框架下实现CSRF跨站攻击防御,需要的朋友可以参考下
    2019-12-12
  • 浅谈java安全编码指南之堆污染

    浅谈java安全编码指南之堆污染

    什么是堆污染呢?是指当参数化类型变量引用的对象不是该参数化类型的对象时而发生的。我们知道在JDK5中,引入了泛型的概念,在创建集合类的时候,指定该集合类中应该存储的对象类型。如果在指定类型的集合中,引用了不同的类型,那么这种情况就叫做堆污染。
    2021-06-06
  • Mybatis日期格式自动转换需要用到的两个注解说明

    Mybatis日期格式自动转换需要用到的两个注解说明

    这篇文章主要介绍了Mybatis日期格式自动转换需要用到的两个注解说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 解决Java提示正在尝试分配更低的访问权限问题

    解决Java提示正在尝试分配更低的访问权限问题

    在本篇文章里小编给大家整理的是关于解决Java提示正在尝试分配更低的访问权限问题的相关方法内容,有需要的朋友们跟着参考学习下。
    2019-07-07
  • RabbitMQ中Confirm消息确认机制保障生产端消息的可靠性详解

    RabbitMQ中Confirm消息确认机制保障生产端消息的可靠性详解

    这篇文章主要介绍了RabbitMQ中Confirm消息确认机制保障生产端消息的可靠性详解,生产者将数据发送到 RabbitMQ 的时候,可能数据就在半路给搞丢了,因为网络问题啥的,都有可能,需要的朋友可以参考下
    2023-12-12
  • Java 内省(Introspector)深入理解

    Java 内省(Introspector)深入理解

    这篇文章主要介绍了Java 内省(Introspector)深入理解的相关资料,需要的朋友可以参考下
    2017-03-03
  • 一文让你彻底明白Java中的值传递和引用传递

    一文让你彻底明白Java中的值传递和引用传递

    这篇文章主要给大家介绍了关于Java中值传递和引用传递的相关资料,值传递是指在调用函数时将实际参数复制一份传递到函数中,引用传递是指在调用函数时将实际参数的引用直接传递到函数中,需要的朋友可以参考下
    2023-10-10
  • 用SpringBoot框架来接收multipart/form-data文件方式

    用SpringBoot框架来接收multipart/form-data文件方式

    这篇文章主要介绍了用SpringBoot框架来接收multipart/form-data文件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 排序算法图解之Java插入排序

    排序算法图解之Java插入排序

    插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。本文通过图片合示例讲解了插入排序的实现,需要的可以了解一下
    2022-11-11
  • IDEA取消SVN关联,再重新分享项目的操作

    IDEA取消SVN关联,再重新分享项目的操作

    这篇文章主要介绍了IDEA取消SVN关联,再重新分享项目的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论