JAXB2生成类含@XmlRootElement仍序列化失败求助
通过JAXB2从XSD生成Java类后,测试XML序列化时抛出上述错误,但生成的AudioService类明明带有@XmlRootElement(name = "audio-service")注解。
测试代码:
public static void marshal() throws JAXBException, IOException { AudioService audioService = new AudioService(); audioService.setName("TTS1"); audioService.setEngineClass("Toto"); JAXBContext context = JAXBContext.newInstance(AudioService.class); Marshaller mar= context.createMarshaller(); mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); mar.marshal(audioService, new File("./test.xml")); }
生成的AudioService类片段:
package com.xxx.xxx; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlElementRef; import jakarta.xml.bind.annotation.XmlMixed; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlType; import jakarta.xml.bind.annotation.XmlValue; @XmlRootElement(name = "audio-service") public class AudioService { @XmlElement(name = "property") protected List<AudioService.Property> properties; @XmlElement(required = true) protected AudioService.Tts tts; // 其他代码省略 }
环境:Java17,Maven依赖包含javax.xml.bind:jaxb-api = 2.3.1和jakarta.xml.bind:jakarta.xml.bind-api=4.0.0
核心问题是javax和Jakarta版本的JAXB API冲突:
- 生成的
AudioService类使用的是jakarta.xml.bind.annotation.XmlRootElement(Jakarta EE的新注解) - 但项目中同时引入了旧版的
javax.xml.bind:jaxb-api,导致运行时JAXBContext加载了旧的javax.xml.bind.annotation.XmlRootElement类,无法识别新的Jakarta注解,因此判定类缺少该注解。
Java17已移除所有Java EE模块(包括javax.xml.bind),官方推荐使用Jakarta EE的替代API,同时引入两个版本必然导致类加载混乱。
移除旧版javax依赖
在pom.xml中删除javax.xml.bind:jaxb-api的依赖配置,只保留jakarta.xml.bind:jakarta.xml.bind-api。添加Jakarta版本的JAXB实现
仅引入API还不够,需要添加对应的运行时实现,比如GlassFish的JAXB runtime:<dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>4.0.4</version> </dependency>版本号要和
jakarta.xml.bind-api的版本匹配(4.x系列适配Java17+)。检查依赖树
执行mvn dependency:tree命令,确认没有其他依赖间接引入javax.xml.bind:jaxb-api,如果有,通过<exclusions>排除:<dependency> <!-- 某个第三方依赖 --> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <exclusions> <exclusion> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </exclusion> </exclusions> </dependency>验证测试代码
确保测试代码中导入的JAXB相关类都是Jakarta版本的:import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Marshaller;而不是旧的
javax.xml.bind.*。
内容的提问来源于stack exchange,提问作者Pichou Bichou

