OpenJDK 19+Spring Boot 3.x迁移后SOAP Fault解析报错求助
问题根源
Spring Boot 3.x全面切换到Jakarta EE API,原javax.xml相关包已替换为jakarta.xml,同时适配Boot 3的Spring Web Services(Spring WS)4.x对SOAP Fault解析逻辑做了对应调整。当前代码在抛出SoapFaultClientException时,底层无法适配Jakarta版本的SOAP节点转换,导致出现Cannot find SOAP wrapper for element [soap:Fault: null]错误。
解决方案
1. 确保依赖适配
确认spring-boot-starter-web-services依赖版本与Spring Boot 3.x匹配,该依赖会自动引入适配Jakarta的Spring WS 4.x,无需手动指定Spring WS版本。
2. 替换JAXB注解
检查所有SOAP实体类,将旧的javax.xml.bind.annotation.*注解替换为jakarta.xml.bind.annotation.*(比如@XmlRootElement、@XmlElement等),确保Marshaller/Unmarshaller能正确识别Jakarta规范的注解。
3. 调整Fault处理逻辑
修改WebServiceMessageExtractor中的Fault处理代码,避免直接将SoapMessage传入SoapFaultClientException,改为先获取SoapFault再处理:
@Override public Object extractData(final WebServiceMessage response) throws IOException { if (unmarshaller == null) { throw new IllegalStateException("No unmarshaller registered. Check configuration of WebServiceTemplate."); } if (hasFault(response)) { SoapMessage soapMessage = (SoapMessage) response; SoapFault soapFault = soapMessage.getSoapBody().getFault(); // 可按需解析Fault的code、message、detail等内容 String faultDetail = soapFault.getFaultStringOrReason(); throw new SoapFaultClientException(soapMessage); } else { return MarshallingUtils.unmarshal(unmarshaller, response); } }
4. 配置Jakarta兼容的Marshaller
如果自定义了Jaxb2Marshaller,确保使用Spring Boot 3.x提供的适配版本,配置示例:
@Bean public Jaxb2Marshaller jaxb2Marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); // 设置使用Jakarta注解的实体类所在包 marshaller.setPackagesToScan("com.yourpackage.soap.model"); // 配置Marshaller属性(可选) Map<String, Object> properties = new HashMap<>(); properties.put(jakarta.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setMarshallerProperties(properties); return marshaller; }
关键说明
Spring Boot 3.x与Spring WS 4.x完全基于Jakarta EE,所有原javax命名空间的API都已迁移到jakarta,必须确保代码、依赖、配置全链路适配。若仍存在节点转换问题,可尝试在WebServiceTemplate配置中指定Jakarta版本的SOAP消息工厂(如SaajSoapMessageFactory)。
内容的提问来源于stack exchange,提问作者Jagannath Jha

