Spring 的 Infinispan,从缓存投射失败
Infinispan with Spring, casting from cache failing
我有 Spring 1.4 应用程序部署到 WildFly 10,它使用 WildFly 内置的 Infinispan 8.1。
我已经成功部署了应用程序,这是 Infinispan 的配置:
1) 缓存管理器
@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
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-spring</artifactId>
<version>8.1.0.Final</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.infinispan, org.infinispan.commons, org.jboss.as.clustering.infinispan export</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
当我第一次部署应用程序时,一切正常。但是,在启动缓存后,重新部署应用程序时,我在使用缓存时收到以下错误:
java.lang.ClassCastException: com.dplesa.Class cannot be cast to com.dplesa.Class
我用不同的 类 尝试过,但无论我做什么,错误都是一样的。但是,我没有从缓存简单字符串的缓存中得到这个错误。是什么导致了这个问题?
这听起来很可怕,但在本例中,行为是正确的。
A class 总是绑定到特定的 classloader。 Wildfly 使用模块化 classloader,每个部署使用不同的 classloader 实例。现在假设您使用 classloader 'A' 放置了 class 的一些实例,进行重新部署(classloader 'A' 正在处理并使用加载新部署classloader 'B') 并尝试使用 classloader 'B' 从缓存中读取数据。那些 class 加载器不匹配,这导致您的异常 - Class com.dplesa.Class
无法转换为 com.dplesa.Class
.
有几种方法可以解决这个问题:
将 Infinispan 嵌入您的应用程序(例如使用 infinispan-embedded
工件)。有了这个技巧,Infinispan 将加载与您的域 classes.
相同的 classloader
将您的域 class 放入 Wildfly 模块中。
单独部署 Infinispan 集群并使用 HotRod 客户端连接到它(例如使用 infinispan-remote
工件)。
解决方案 #1 是最简单的,但您需要注意在重新部署期间您的集群发生了什么(确保您的节点 join/leave 集群正确,您的数据按您的需要复制等)。
我有 Spring 1.4 应用程序部署到 WildFly 10,它使用 WildFly 内置的 Infinispan 8.1。
我已经成功部署了应用程序,这是 Infinispan 的配置: 1) 缓存管理器
@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
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-spring</artifactId>
<version>8.1.0.Final</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.infinispan, org.infinispan.commons, org.jboss.as.clustering.infinispan export</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
当我第一次部署应用程序时,一切正常。但是,在启动缓存后,重新部署应用程序时,我在使用缓存时收到以下错误:
java.lang.ClassCastException: com.dplesa.Class cannot be cast to com.dplesa.Class
我用不同的 类 尝试过,但无论我做什么,错误都是一样的。但是,我没有从缓存简单字符串的缓存中得到这个错误。是什么导致了这个问题?
这听起来很可怕,但在本例中,行为是正确的。
A class 总是绑定到特定的 classloader。 Wildfly 使用模块化 classloader,每个部署使用不同的 classloader 实例。现在假设您使用 classloader 'A' 放置了 class 的一些实例,进行重新部署(classloader 'A' 正在处理并使用加载新部署classloader 'B') 并尝试使用 classloader 'B' 从缓存中读取数据。那些 class 加载器不匹配,这导致您的异常 - Class com.dplesa.Class
无法转换为 com.dplesa.Class
.
有几种方法可以解决这个问题:
将 Infinispan 嵌入您的应用程序(例如使用
infinispan-embedded
工件)。有了这个技巧,Infinispan 将加载与您的域 classes. 相同的 classloader
将您的域 class 放入 Wildfly 模块中。
单独部署 Infinispan 集群并使用 HotRod 客户端连接到它(例如使用
infinispan-remote
工件)。
解决方案 #1 是最简单的,但您需要注意在重新部署期间您的集群发生了什么(确保您的节点 join/leave 集群正确,您的数据按您的需要复制等)。