You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomee Plume 9.1.0中REST XML服务设置MinumEscapeHandler失败求助

问题解答:JAXB EscapeHandler 设置失败但服务正常运行的问题

1. 这个错误是否可忽略?

是的,这个错误完全可以暂时忽略。理由很明确:

  • 日志级别是INFO而非ERROR,说明这只是一个非关键性的提示信息,不是致命错误
  • 核心的XML序列化逻辑没有被阻断,服务依然能正常返回XML响应
  • 本质是Apache CXF尝试给JAXB Marshaller设置自定义转义处理器失败,但JAXB会自动 fallback 到默认处理器,不影响核心功能

2. 错误原因分析

TomEE Plume 9.1.0默认搭载的是GlassFish JAXB实现(org.glassfish.jaxb),而非传统的Sun/Oracle JAXB(com.sun.xml.bind)。你看到的解决方案里提到的com.sun.xml.bind.v2.ContextFactory属于Sun JAXB专属类,在当前环境中不存在,所以添加该属性无效。

错误的触发逻辑:

  • CXF的JAXBUtils尝试设置Sun JAXB专属的com.sun.xml.bind.characterEscapeHandler属性
  • 但当前使用的GlassFish JAXB Marshaller不识别该属性,抛出PropertyException
  • 异常被CXF捕获并记录为INFO日志,未中断服务流程

3. 彻底消除日志的两种方案

如果不想看到这条日志,可以通过以下方式解决:

方案一:切换到Sun JAXB实现

在项目依赖中添加Jakarta版本的Sun JAXB包(适配TomEE 9.x的Jakarta EE 9规范):

<!-- Maven依赖配置 -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>3.0.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>3.0.2</version>
    <scope>provided</scope>
</dependency>

然后添加配置指定ContextFactory:

# 在项目的jaxb.properties文件或系统属性中添加
jakarta.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory

方案二:禁用CXF的最小转义处理器设置

通过CXF配置关闭这个无效的尝试:

  • 自定义JAX-RS应用配置类:
import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class RestApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<>();
        classes.add(HelloWorld.class);
        return classes;
    }

    @Override
    public Set<Object> getSingletons() {
        Set<Object> singletons = new HashSet<>();
        JAXBElementProvider<?> provider = new JAXBElementProvider<>();
        // 禁用最小转义处理器设置
        provider.setMinimumEscapeHandler(null);
        singletons.add(provider);
        return singletons;
    }
}

或者在TomEE的conf/system.properties中添加全局配置:

org.apache.cxf.jaxrs.jaxb.minimum-escape-handler=false

附:问题相关代码与日志

服务实现代码

@Path("/rs")
public class HelloWorld {
    @GET
    @Path("/sayHello")
    @Produces(MediaType.APPLICATION_XML)
    public Student sayHello() {
        return new Student("Peter");
    }
}

@XmlRootElement
class Student {
    int id;
    String name;
    public Student() {}
    public Student(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    @XmlAttribute
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    @XmlElement
    public void setName(String name) {
        this.name = name;
    }
}

错误日志

06-Jan-2024 22:25:19.420 INFO [http-nio-8080-exec-8] org.apache.cxf.common.jaxb.JAXBUtils.setEscapeHandler Failed to set MinumEscapeHandler to jaxb marshaller
    jakarta.xml.bind.PropertyException: name: com.sun.xml.bind.characterEscapeHandler value: null
        at jakarta.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:343)
        at org.glassfish.jaxb.runtime.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:499)
        at org.apache.cxf.common.jaxb.JAXBUtils.setEscapeHandler(JAXBUtils.java:1135)
        at org.apache.cxf.common.jaxb.JAXBUtils.lambda$setMinimumEscapeHandler$0(JAXBUtils.java:1121)
        at java.base/java.util.Optional.ifPresent(Optional.java:178)
        at org.apache.cxf.common.jaxb.JAXBUtils.setMinimumEscapeHandler(JAXBUtils.java:1121)
        at org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalToOutputStream(JAXBElementProvider.java:610)
        at org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshal(JAXBElementProvider.java:576)
        at org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshal(JAXBElementProvider.java:441)
        at org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo(JAXBElementProvider.java:317)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.writeMessageBody(JAXRSUtils.java:1651)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:249)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:122)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:84)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
        at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:90)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
        at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:265)

内容的提问来源于stack exchange,提问作者Steffano Aravico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:15:22