WildFly22+Java11配置Infinispan缓存时序列化失败求助
解决WildFly22+Java11下Infinispan分布式会话缓存序列化异常问题
环境与问题
使用WildFly22搭配Java11,配置Infinispan分布式会话缓存时,出现序列化异常,无法将缓存内容写入文件存储。
当前配置
distributable-web.xml
<distributable-web xmlns="urn:jboss:distributable-web:2.0"> <infinispan-session-management cache-container="web" cache="corpapp-session-cache-web" granularity="SESSION"> <primary-owner-affinity/> </infinispan-session-management> </distributable-web>
standalone-ha.xml
<cache-container name="web" default-cache="passivation" marshaller="PROTOSTREAM" modules="org.wildfly.clustering.web.infinispan"> <local-cache name="corpapp-session-cache-web"> <file-store path="corpapp-cache" passivation="false" purge="false" shared="false"/> </local-cache> <local-cache name="passivation"> <expiration interval="0"/> <file-store passivation="true" purge="false"/> </local-cache> <local-cache name="sso"> <expiration interval="0"/> </local-cache> </cache-container>
错误现象
- 设置marshaller为
PROTOSTREAM时,出现警告:
WARN [org.infinispan.PERSISTENCE] (default task-2) ISPN000559: Cannot marshall 'class org.infinispan.marshall.protostream.impl.MarshallableUserObject': java.io.NotSerializableException: java.lang.Object at org.jboss.marshalling.river@2.0.12.Final//org.jboss.marshalling.river.RiverMarshaller.writeKnownObject(RiverMarshaller.java:990)
- 设置marshaller为
JBOSS时,出现请求处理错误:
ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /corporateInterface/login.do: org.infinispan.persistence.spi.PersistenceException: org.infinispan.commons.marshall.MarshallingException: org.wildfly.clustering.web.infinispan.session.SessionAccessMetaDataKey
完整堆栈:
WARN [org.infinispan.PERSISTENCE] (default task-2) ISPN000559: Cannot marshall 'class org.infinispan.marshall.protostream.impl.MarshallableUserObject': java.io.NotSerializableException: java.lang.Object at org.jboss.marshalling.river@2.0.12.Final//org.jboss.marshalling.river.RiverMarshaller.writeKnownObject(RiverMarshaller.java:990) ... Caused by: an exception which occurred: in object java.lang.Object@284f63da in object java.util.HashMap@f6e39bcd in object java.util.concurrent.ConcurrentHashMap@16d76032
解决方案
1. 修复会话中的非序列化对象
从堆栈信息可以看出,会话中存储了未实现java.io.Serializable接口的java.lang.Object实例,嵌套在HashMap和ConcurrentHashMap中:
- 排查代码中所有调用
HttpSession.setAttribute()的逻辑,确保存入会话的所有对象(包括集合中的元素)都实现java.io.Serializable接口。 - 若必须存储非序列化对象,可将其转换为可序列化的包装类型,或者避免存入会话。
2. 配置与WildFly兼容的Marshaller
WildFly22的web集群缓存容器需使用与集群模块匹配的Marshaller:
- 使用PROTOSTREAM Marshaller(推荐):
- 确保所有自定义会话属性类型都注册了对应的ProtoStream Marshaller。Java标准类型Infinispan已提供默认支持,自定义类需编写
.protoschema文件,通过org.infinispan.protostream.annotations.AutoProtoSchemaBuilder注解或编程方式注册。 - 保持
cache-container的modules="org.wildfly.clustering.web.infinispan"配置,确保WildFly集群类能被正确序列化。
- 确保所有自定义会话属性类型都注册了对应的ProtoStream Marshaller。Java标准类型Infinispan已提供默认支持,自定义类需编写
- 使用JBOSS Marshaller:
- 在
standalone-ha.xml的cache-container中添加unmarshaller="JBOSS",确保org.wildfly.clustering.web.infinispan模块中的类(如SessionAccessMetaDataKey)能被JBOSS Marshaller正确识别,同时检查模块依赖完整性。
- 在
3. 确保部署依赖正确
在应用的jboss-deployment-structure.xml中添加必要的WildFly集群模块依赖,避免类加载问题:
<jboss-deployment-structure> <deployment> <dependencies> <module name="org.wildfly.clustering.web.infinispan" /> <module name="org.infinispan.commons" /> <module name="org.jboss.marshalling.river" /> </dependencies> </deployment> </jboss-deployment-structure>
4. 调试会话内容定位问题
添加Servlet过滤器,实时检查会话中的非序列化属性,快速定位问题代码:
public class SessionSerializableCheckerFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(false); if (session != null) { Enumeration<String> attrNames = session.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = attrNames.nextElement(); Object attrValue = session.getAttribute(attrName); if (attrValue != null && !(attrValue instanceof Serializable)) { System.err.printf("Non-serializable attribute found in session: name=%s, type=%s%n", attrName, attrValue.getClass().getName()); } } } chain.doFilter(request, response); } }
在web.xml中注册该过滤器,覆盖所有请求路径:
<filter> <filter-name>SessionSerializableChecker</filter-name> <filter-class>com.yourpackage.SessionSerializableCheckerFilter</filter-class> </filter> <filter-mapping> <filter-name>SessionSerializableChecker</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

