Java 8迁移至Java17后Apache CXF报javax.xml.bind类未找到错误
问题:Java 17迁移后Apache CXF加载javax.xml.bind库失败
我已将应用从Java 8迁移至Java 17,同步升级了对应依赖库(完成javax到jakarta命名空间重构),但Apache CXF尝试加载javax.xml.bind库时抛出ClassNotFoundException。已知Java 11后该库已被移除,且不想引入javax.xml.bind:jaxb-api避免运行时冲突。尝试移除旧ehcache和jaxb-runtime库后,问题仍未解决。
错误堆栈
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBElement at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1353) ~[catalina.jar:?] at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165) ~[catalina.jar:?] at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?] at java.lang.Class.privateGetDeclaredMethods(Class.java:3402) ~[?:?] at java.lang.Class.privateGetPublicMethods(Class.java:3427) ~[?:?] at java.lang.Class.getMethods(Class.java:2019) ~[?:?] at org.apache.cxf.common.jaxb.JAXBContextCache.checkObjectFactoryNamespaces(JAXBContextCache.java:270) ~[cxf-core-4.0.4.jar:4.0.4] at org.apache.cxf.common.jaxb.JAXBContextCache.getCachedContextAndSchemas(JAXBContextCache.java:182) ~[cxf-core-4.0.4.jar:4.0.4] at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:499) ~[cxf-rt-databinding-jaxb-4.0.4.jar:4.0.4] at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:358) ~[cxf-rt-databinding-jaxb-4.0.4.jar:4.0.4] at org.apache.cxf.service.factory.AbstractServiceFactoryBean.initializeDataBindings(AbstractServiceFactoryBean.java:87) ~[cxf-core-4.0.4.jar:4.0.4] at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:469) ~[cxf-rt-wsdl-4.0.4.jar:4.0.4] at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:693) ~[cxf-rt-frontend-jaxws-4.0.4.jar:4.0.4] at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:529) ~[cxf-rt-wsdl-4.0.4.jar:4.0.4] at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:262) ~[cxf-rt-wsdl-4.0.4.jar:4.0.4] at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:199) ~[cxf-rt-frontend-jaxws-4.0.4.jar:4.0.4] at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:103) ~[cxf-rt-frontend-simple-4.0.4.jar:4.0.4] at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:91) ~[cxf-rt-frontend-simple-4.0.4.jar:4.0.4] at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:158) ~[cxf-rt-frontend-simple-4.0.4.jar:4.0.4] at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142) ~[cxf-rt-frontend-jaxws-4.0.4.jar:4.0.4]
pom.xml配置片段
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>4.0.4</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-ws-security</artifactId> <version>4.0.4</version> <exclusions> <exclusion> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <classifier>jakarta</classifier> <version>3.10.8</version> <exclusions> <exclusion> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.santuario</groupId> <artifactId>xmlsec</artifactId> <version>2.3.4</version> </dependency> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>4.0.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.15.2</version> </dependency>
Spring Bean配置代码
<bean id="myJaxWsClient" class="com.package.SoapClient" factory-bean="soapClientFactory" factory-method="create"/> <bean id="soapClientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.package.SoapClient" /> <property name="address" value="${EVENT_END_POINT}" /> </bean>
解决方案
1. 显式指定CXF使用Jakarta JAXB实现
在Spring配置中强制设置CXF使用Jakarta版本的JAXBDataBinding,避免默认加载javax类:
<bean id="soapClientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.package.SoapClient" /> <property name="address" value="${EVENT_END_POINT}" /> <!-- 绑定Jakarta版本JAXBContext --> <property name="dataBinding"> <bean class="org.apache.cxf.jaxb.JAXBDataBinding"> <constructor-arg value="jakarta.xml.bind.JAXBContext" /> </bean> </property> </bean>
2. 彻底排除所有javax.xml.bind相关依赖
执行mvn dependency:tree查看依赖树,找出所有引入javax JAXB的依赖并排除,以cxf-rt-ws-security为例:
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-ws-security</artifactId> <version>4.0.4</version> <exclusions> <exclusion> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </exclusion> <!-- 新增排除javax JAXB依赖 --> <exclusion> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> </exclusion> </exclusions> </dependency>
3. 确认客户端代码为Jakarta命名空间
如果com.package.SoapClient是通过wsdl2java生成的,必须使用CXF 4.x版本工具并添加-jakarta参数,确保生成的代码引用jakarta.xml.bind.annotation.*注解而非javax包下的类。手动编写的接口也需同步替换所有JAXB注解的命名空间。
4. 可选:添加CXF Jakarta迁移支持依赖
若上述步骤仍未解决,可引入CXF的Jakarta桥接依赖辅助命名空间转换:
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-jakarta</artifactId> <version>4.0.4</version> </dependency>
内容的提问来源于stack exchange,提问作者Mehul
相关产品推荐
相关产品推荐

