Infinispan with Spring,从缓存中转换失败
我有部署到WildFly 10的Spring 1.4应用程序,它使用的是WildFly内置的Infinispan 8.1。
我已经设法正确部署了应用程序,这是Infinispan的配置:1)CacheManager
@Bean public CacheManager cacheManager() throws Exception { JndiTemplate jndiTemplate = new JndiTemplate(); EmbeddedCacheManager embededCacheManager = (EmbeddedCacheManager) jndiTemplate.lookup("java:jboss/infinispan/container/CONTAINER"); SpringEmbeddedCacheManager cacheManager = new SpringEmbeddedCacheManager(embededCacheManager); }
2)pom.xml
org.infinispan infinispan-spring 8.1.0.Final org.springframework.boot spring-boot-starter-logging javax.servlet servlet-api org.apache.logging.log4j log4j-core org.apache.logging.log4j log4j-jcl org.apache.logging.log4j log4j-slf4j-impl org.apache.maven.plugins maven-war-plugin org.infinispan, org.infinispan.commons, org.jboss.as.clustering.infinispan export
当我第一次部署应用程序时,一切正常。 但是,在启动缓存后,以及重新部署应用程序时,使用缓存时出现以下错误:
java.lang.ClassCastException: com.dplesa.Class cannot be cast to com.dplesa.Class
我尝试了不同的类,不管我做什么,错误是一样的。 但是,我没有从缓存简单字符串的缓存中得到此错误。 什么可能导致这个问题?
这可能听起来很可怕,但在这种情况下,行为是正确的。
类始终绑定到特定的类加载器。 Wildfly使用模块化类加载器,每个部署使用不同的类加载器实例。 现在假设您使用类加载器’A’放置了类的一些实例,进行重新部署(使用类加载器’B’处理类加载器’A’并使用类加载器’B’加载新部署)并尝试使用类加载器’B’从缓存中读取数据。 这些类加载器不匹配,这会导致exception – 类com.dplesa.Class
无法转换为com.dplesa.Class
。
有几种方法可以解决这个问题:
-
将Infinispan嵌入您的应用程序(例如使用
infinispan-embedded
工件)。 有了这个技巧,Infinispan将加载与您的域类相同的类加载器。 -
将您的域类放在Wildfly模块中。
-
单独部署Infinispan集群并使用HotRod Client连接到它(例如,使用
infinispan-remote
工件)。
解决方案#1是最简单的,但您需要注意重新部署期间群集发生的情况(确保您的节点正确加入/离开群集,您的数据可以根据需要进行复制等)。