spring-boot-devtools 在从缓存获取时导致 ClassCastException。
spring-boot-devtools causing ClassCastException while getting from cache.
我在从缓存中获取值时遇到问题。
java.lang.RuntimeException: java.lang.ClassCastException: com.mycom.admin.domain.User cannot be cast to com.mycom.admin.domain.User
缓存配置
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class, DatabaseConfiguration.class })
@Profile("!" + Constants.SPRING_PROFILE_FAST)
public class MemcachedCacheConfiguration extends CachingConfigurerSupport {
private final Logger log = LoggerFactory.getLogger(MemcachedCacheConfiguration.class);
@Override
@Bean
public CacheManager cacheManager() {
ExtendedSSMCacheManager cacheManager = new ExtendedSSMCacheManager();
try {
List<SSMCache> list = new ArrayList<>();
list.add(new SSMCache(defaultCache("apiCache"), 86400, false));
cacheManager.setCaches(list);
} catch (Exception e) {
e.printStackTrace();
}
return cacheManager;
}
@Override
public CacheResolver cacheResolver() {
return null;
}
@Override
public CacheErrorHandler errorHandler() {
return null;
}
private Cache defaultCache(String cacheName) throws Exception {
CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName(cacheName);
cacheFactory.setCacheClientFactory(new MemcacheClientFactoryImpl());
String serverHost = "127.0.0.1:11211";
cacheFactory.setAddressProvider(new DefaultAddressProvider(serverHost));
cacheFactory.setConfiguration(cacheConfiguration());
return cacheFactory.getObject();
}
@Bean
public CacheConfiguration cacheConfiguration() {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setConsistentHashing(true);
return cacheConfiguration;
}
}
并用
注释
@Cacheable(value = "apiCache#86400", key = "'User-'.concat(#login)")
我正在使用 com.google.code.simple-spring-memcached 3.5.0
正在缓存值,但在获取应用程序时抛出 class 转换错误。可能的问题是什么。
这是a known limitation of Devtools。反序列化缓存条目时,对象未附加到正确的类加载器。
您可以通过多种方式解决此问题:
- 当您 运行 开发中的应用程序时禁用缓存
- 使用不同的缓存管理器(如果您使用的是 Spring Boot 1.3,您可以使用
spring.cache.type
属性 中的 simple
强制使用 simple
缓存管理器12=] 并在 IDE) 中启用开发配置文件
- 将 memcached(以及缓存的内容)配置为 run in the application classloader。我不推荐该选项,因为上面的前两个更容易实现
好吧,我遇到了同样的错误,但缓存不是原因。其实我在使用缓存,但是评论缓存没有帮助。
根据这里和那里的提示,我刚刚介绍了额外的 serialization/derialization 我的对象。这绝对是最好的方法(性能问题),但它确实有效。
所以,为了其他人,我更改了我的代码:
@Cacheable("tests")
public MyDTO loadData(String testID) {
// add file extension to match XML file
return (MyDTO) this.xmlMarshaller.loadXML(String.format("%s/%s.xml", xmlPath, testID));
}
至:
@Cacheable("tests")
public MyDTO loadData(String testID) {
// add file extension to match XML file
Object dtoObject = this.xmlMarshaller.loadXML(String.format("%s/%s.xml", xmlPath, testID));
byte[] data = serializeDTO(dtoObject);
MyDTO dto = deserializeDTO(data);
return dto;
}
private MyDTO deserializeDTO(byte[] data) {
MyDTO dto = null;
try {
ByteArrayInputStream fileIn = new ByteArrayInputStream(data);
ObjectInputStream in = new ConfigurableObjectInputStream(fileIn,
Thread.currentThread().getContextClassLoader());
dto = (MyDTO) in.readObject();
in.close();
fileIn.close();
} catch (Exception e) {
String msg = "Deserialization of marshalled XML failed!";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
return dto;
}
private byte[] serializeDTO(Object dtoObject) {
byte[] result = null;
try {
ByteArrayOutputStream data = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(data);
out.writeObject(dtoObject);
out.close();
result = data.toByteArray();
data.close();
} catch (IOException e) {
String msg = "Serialization of marshalled XML failed!";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
return result;
}
注意:这不是任何复杂的解决方案,而只是使用 ConfigurableObjectInputStream class.
的提示
当 运行 eclipse 中启用了 STS 插件的项目时,我 运行 遇到了同样的问题。即使我从项目中完全删除了 devtools 依赖项。它仍然在 eclipse 中启用。为了解决这个问题,我不得不禁用 devtools。
我在从缓存中获取值时遇到问题。
java.lang.RuntimeException: java.lang.ClassCastException: com.mycom.admin.domain.User cannot be cast to com.mycom.admin.domain.User
缓存配置
@Configuration
@EnableCaching
@AutoConfigureAfter(value = { MetricsConfiguration.class, DatabaseConfiguration.class })
@Profile("!" + Constants.SPRING_PROFILE_FAST)
public class MemcachedCacheConfiguration extends CachingConfigurerSupport {
private final Logger log = LoggerFactory.getLogger(MemcachedCacheConfiguration.class);
@Override
@Bean
public CacheManager cacheManager() {
ExtendedSSMCacheManager cacheManager = new ExtendedSSMCacheManager();
try {
List<SSMCache> list = new ArrayList<>();
list.add(new SSMCache(defaultCache("apiCache"), 86400, false));
cacheManager.setCaches(list);
} catch (Exception e) {
e.printStackTrace();
}
return cacheManager;
}
@Override
public CacheResolver cacheResolver() {
return null;
}
@Override
public CacheErrorHandler errorHandler() {
return null;
}
private Cache defaultCache(String cacheName) throws Exception {
CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName(cacheName);
cacheFactory.setCacheClientFactory(new MemcacheClientFactoryImpl());
String serverHost = "127.0.0.1:11211";
cacheFactory.setAddressProvider(new DefaultAddressProvider(serverHost));
cacheFactory.setConfiguration(cacheConfiguration());
return cacheFactory.getObject();
}
@Bean
public CacheConfiguration cacheConfiguration() {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setConsistentHashing(true);
return cacheConfiguration;
}
}
并用
注释@Cacheable(value = "apiCache#86400", key = "'User-'.concat(#login)")
我正在使用 com.google.code.simple-spring-memcached 3.5.0
正在缓存值,但在获取应用程序时抛出 class 转换错误。可能的问题是什么。
这是a known limitation of Devtools。反序列化缓存条目时,对象未附加到正确的类加载器。
您可以通过多种方式解决此问题:
- 当您 运行 开发中的应用程序时禁用缓存
- 使用不同的缓存管理器(如果您使用的是 Spring Boot 1.3,您可以使用
spring.cache.type
属性 中的simple
强制使用simple
缓存管理器12=] 并在 IDE) 中启用开发配置文件
- 将 memcached(以及缓存的内容)配置为 run in the application classloader。我不推荐该选项,因为上面的前两个更容易实现
好吧,我遇到了同样的错误,但缓存不是原因。其实我在使用缓存,但是评论缓存没有帮助。
根据这里和那里的提示,我刚刚介绍了额外的 serialization/derialization 我的对象。这绝对是最好的方法(性能问题),但它确实有效。
所以,为了其他人,我更改了我的代码:
@Cacheable("tests")
public MyDTO loadData(String testID) {
// add file extension to match XML file
return (MyDTO) this.xmlMarshaller.loadXML(String.format("%s/%s.xml", xmlPath, testID));
}
至:
@Cacheable("tests")
public MyDTO loadData(String testID) {
// add file extension to match XML file
Object dtoObject = this.xmlMarshaller.loadXML(String.format("%s/%s.xml", xmlPath, testID));
byte[] data = serializeDTO(dtoObject);
MyDTO dto = deserializeDTO(data);
return dto;
}
private MyDTO deserializeDTO(byte[] data) {
MyDTO dto = null;
try {
ByteArrayInputStream fileIn = new ByteArrayInputStream(data);
ObjectInputStream in = new ConfigurableObjectInputStream(fileIn,
Thread.currentThread().getContextClassLoader());
dto = (MyDTO) in.readObject();
in.close();
fileIn.close();
} catch (Exception e) {
String msg = "Deserialization of marshalled XML failed!";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
return dto;
}
private byte[] serializeDTO(Object dtoObject) {
byte[] result = null;
try {
ByteArrayOutputStream data = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(data);
out.writeObject(dtoObject);
out.close();
result = data.toByteArray();
data.close();
} catch (IOException e) {
String msg = "Serialization of marshalled XML failed!";
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
return result;
}
注意:这不是任何复杂的解决方案,而只是使用 ConfigurableObjectInputStream class.
的提示当 运行 eclipse 中启用了 STS 插件的项目时,我 运行 遇到了同样的问题。即使我从项目中完全删除了 devtools 依赖项。它仍然在 eclipse 中启用。为了解决这个问题,我不得不禁用 devtools。