Wildfly部署时Infinispan缓存序列化误用过时DOMSerializerImpl问题
问题:向Infinispan缓存存入对象时出现序列化错误
报错详情
存入缓存时触发以下错误:
ISPN000559: Cannot marshall 'class org.infinispan.marshall.protostream.impl.MarshallableUserObject': org.w3c.dom.ls.LSException
堆栈信息显示程序调用了过时的org.apache.xerces@2.12.0.SP03//org.apache.xml.serialize.DOMSerializerImpl.writeToString(DOMSerializerImpl.java:518)类,而预期应使用xalan serializer 2.7.2。
代码逻辑背景
应用内直接执行序列化时可正常使用正确的序列化器,逻辑来自xercesImpl-2.12.2的CoreDomImplementationImpl.java:
public LSSerializer createLSSerializer() { try { Class serializerClass = ObjectFactory.findProviderClass( "org.apache.xml.serializer.dom3.LSSerializerImpl", ObjectFactory.findClassLoader(), true); return (LSSerializer) serializerClass.newInstance(); } catch (Exception e) {} // Fall back to Xerces' deprecated serializer if // the Xalan based serializer is unavailable. return new DOMSerializerImpl(); }
业务侧的序列化调用代码:
public static @Null String documentToString(@Null Document document) { if (document == null) { return null; } DOMImplementationLS domImplementation = (DOMImplementationLS) document.getImplementation(); LSSerializer lsSerializer = domImplementation.createLSSerializer(); String result = lsSerializer.writeToString(document); return result; }
环境配置:WEB-INF/lib已包含xalan-2.7.2,使用Wildfly 26.1.2.Final、Infinispan 13.0.10.Final。
原因分析
- 容器类加载器优先级冲突:Wildfly容器自带了
xerces 2.12.0.SP03,容器类加载器的优先级高于应用WEB-INF/lib的类加载器,导致org.apache.xml.serializer.dom3.LSSerializerImpl无法被加载,触发了代码中的降级逻辑,转而使用过时的DOMSerializerImpl。 - Infinispan序列化上下文差异:存入Infinispan缓存时,序列化操作是在Infinispan的类加载器上下文中执行的,而非应用自身的类加载器,此时无法找到WEB-INF/lib中的xalan序列化器类,最终触发fallback逻辑。
修复方案
方案1:调整Wildfly类加载优先级
在应用的jboss-deployment-structure.xml中配置,让应用优先加载自身WEB-INF/lib中的xerces和xalan相关类,避免容器类覆盖:
<jboss-deployment-structure> <deployment> <exclusions> <!-- 排除容器自带的xerces和xalan模块 --> <module name="org.apache.xerces"/> <module name="org.apache.xalan"/> </exclusions> <dependencies> <!-- 可选:如果需要依赖容器模块时使用应用类 --> <module name="org.apache.xerces" export="true" optional="true"/> <module name="org.apache.xalan" export="true" optional="true"/> </dependencies> </deployment> </jboss-deployment-structure>
方案2:显式指定序列化器类
绕过自动查找逻辑,直接在代码中实例化xalan的序列化器,避免fallback到过时实现:
public static @Null String documentToString(@Null Document document) { if (document == null) { return null; } LSSerializer lsSerializer; try { // 直接加载xalan的LSSerializer实现类 Class<?> serializerClass = Class.forName("org.apache.xml.serializer.dom3.LSSerializerImpl"); lsSerializer = (LSSerializer) serializerClass.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { // 降级到原有逻辑作为兜底 DOMImplementationLS domImplementation = (DOMImplementationLS) document.getImplementation(); lsSerializer = domImplementation.createLSSerializer(); } return lsSerializer.writeToString(document); }
方案3:验证依赖完整性
确认构建脚本(如pom.xml)中xalan依赖的scope为compile,且没有被其他依赖排除;同时检查WEB-INF/lib中是否同时存在xalan-2.7.2.jar和对应的serializer-2.7.2.jar(xalan序列化器依赖该组件)。
内容的提问来源于stack exchange,提问作者Victoria
相关产品推荐
相关产品推荐

