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

Mule ESB异步场景下JAXB转换出现ConcurrentModificationException问题

Mule 3.9.x异步块中JAXB对象转XML触发ConcurrentModificationException的解决方案

问题场景

在Mule 3.9.x社区版环境下,将jaxb-object-to-xml-transformer组件放入<async>异步块执行对象转XML操作时,触发java.util.ConcurrentModificationException异常。同步场景下该功能运行正常,升级至Mule 3.9.5后问题仍未解决,需在不升级到Mule 4+的前提下修复此问题。

异常栈信息

Message               : null (java.util.ConcurrentModificationException)
Element               : /test/processors/0 @ test-masked:masked.xml:685 (JAXB Object to JMSMessage (XML string))
--------------------------------------------------------------------------------
Exception stack is:
null (java.util.ConcurrentModificationException) (org.mule.api.transformer.TransformerException)
  java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
  java.util.ArrayList$Itr.next(ArrayList.java:851)
  com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister$1.next(Lister.java:284)
  com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:135)
  com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:155)
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
  com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
  com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593)
  com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:324)
  com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
  com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
  com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244)
  javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:116)
  org.mule.module.xml.transformer.jaxb.JAXBMarshallerTransformer.doTransform(JAXBMarshallerTransformer.java:77)
  org.mule.transformer.AbstractTransformer.transform(AbstractTransformer.java:415)
  org.mule.transformer.AbstractTransformer.transform(AbstractTransformer.java:366)
  (40 more...)

异步配置代码

<async>
    <mulexml:jaxb-object-to-xml-transformer
                returnClass="java.lang.String" mimeType="text/xml"
                jaxbContext-ref="JAXB_Context_Update_Journey"/>

    <logger
                message="#[message:correlationId] | pushing to cache.inbox -payload - #[payload]"
                level="INFO" category="update cache" />
</async>

原因分析

从异常栈可以看出,JAXB在序列化ArrayList集合时,迭代器检测到集合正在被并发修改。根本原因是:

  • Mule的<async>块会共享原消息对象,若原线程在异步线程执行JAXB序列化的同时,继续修改payload中的集合属性,就会触发ConcurrentModificationException。
  • 同步场景下是单线程执行,不存在并发修改问题,因此运行正常。

解决方案

1. 进入异步块前深拷贝对象

确保异步块处理的是对象的独立副本,彻底隔离原线程的修改操作。可以使用Apache Commons Lang的序列化工具实现深拷贝,示例如下:

<!-- 在async块前添加深拷贝转换器 -->
<scripting:transformer doc:name="Deep Copy Payload">
    <scripting:script engine="Groovy">
        import org.apache.commons.lang3.SerializationUtils
        // 需确保JAXB注解的类实现Serializable接口
        def copiedPayload = SerializationUtils.clone(payload)
        return copiedPayload
    </scripting:script>
</scripting:transformer>

<async>
    <mulexml:jaxb-object-to-xml-transformer
                returnClass="java.lang.String" mimeType="text/xml"
                jaxbContext-ref="JAXB_Context_Update_Journey"/>

    <logger
                message="#[message:correlationId] | pushing to cache.inbox -payload - #[payload]"
                level="INFO" category="update cache" />
</async>

如果目标类无法实现Serializable,可以手动创建对象副本,逐个复制属性(集合类型需重新创建并复制元素),示例Groovy代码:

// 假设原对象是Journey类,包含List<Step> steps属性
def original = payload
def copied = new Journey()
copied.setId(original.getId())
// 复制集合:创建新ArrayList并添加所有元素
copied.setSteps(new ArrayList<>(original.getSteps()))
// 复制其他属性...
return copied

2. 禁止原线程修改异步块共享的对象

如果业务允许,确保进入<async>块后,原线程不再修改payload中的任何对象属性(尤其是集合类型)。这种方式无需修改代码,但需要严格控制业务逻辑的执行顺序,避免并发修改。

3. 验证JAXB上下文配置

虽然JAXBContext本身是线程安全的,但需确认Mule配置的jaxbContext-ref是否正确初始化。若使用自定义JAXBContext,确保其配置支持并发场景,但此方案仅解决上下文本身的线程安全问题,无法解决对象被并发修改的核心问题,因此仅作为辅助验证手段。

内容的提问来源于stack exchange,提问作者Mahesh A R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:32