In springboot-redis project,error ClassCastException is reported - spring-boot

The stored objects are nested.
I don't understand why there are problems.
I want him to be inverted correctly.
Who can help me?
RedisConfig:
#Configuration
public class RedisConfig {
#Bean
#SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
Method with error:
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
The error info:
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.maple.webserver.security.SecurityUserDetails (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.maple.webserver.security.SecurityUserDetails is in unnamed module of loader 'app')

Related

How to use Redis template in an async annotated method in spring boot

I am trying to use hash operations of Redis from an async (performTask) method, but I keep getting this exception,
java.lang.IllegalStateException: JedisConnectionFactory was destroyed and cannot be used anymore
this async method is called from another service class in a loop like shown in the below code snippet of service class,
Service class:
....
for(CacheJob job : jobs.getJobs()) {
if(job.getCacheKey() != null && job.getLupdTSSQL() != null) {
asyncService.performTask(job.getCacheKey(), job.getLupdTSSQL());
}
}
....
Async service class:
#Autowired
private HashOperations<String, String, String> lupdTSHashOperations;
#Async
public void performTask(String cacheKey, String sql) throws Exception {
String lupdTSFromCacheStr = null;
System.out.println("Execute method asynchronously. Thread Id"
+ Thread.currentThread().getId()+": cacheKey :"+cacheKey);
....
String lupdTSCacheKey = null;
...
try {
lupdTSCacheKey = cacheKey + Constants.SUFFIX_LUPDTS;
lupdTSFromCacheStr = lupdTSHashOperations.get(cacheKey, lupdTSCacheKey);
....
.....
AsyncConfig
#Configuration
#EnableAsync
public class MyAsyncConfig implements AsyncConfigurer{
#Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("my-cache-jobs-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
.....
Redis config
#Configuration
public class MyCacheRedisConfig {
#Value("${spring.redis.host}")
private String redisHost;
#Value("${spring.redis.port}")
private String redisPort;
#Value("${spring.redis.password}")
private String redisPassword;
#SuppressWarnings("deprecation")
#Bean(name = "jedisConnectionFactory")
JedisConnectionFactory jedisConnectionFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);
poolConfig.setMaxIdle(8);
poolConfig.setMinIdle(0);
JedisConnectionFactory rsc = new JedisConnectionFactory();
rsc.setPoolConfig(poolConfig);
rsc.setHostName(redisHost);
rsc.setPort(Integer.parseInt(redisPort));
rsc.setPassword(redisPassword);
rsc.setUseSsl(true);
return rsc;
}
.....
....
#Bean(name = "lupdTSRedisTemplate")
public RedisTemplate<String, String> lupdTSRedisTemplate() {
final RedisTemplate<String, String> template = new RedisTemplate<String, String>();
template.setConnectionFactory(jedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
#Bean(name="lupdTSHashOperations")
public HashOperations<String, String, String> lupdTSHashOperations(
#Qualifier("lupdTSRedisTemplate") RedisTemplate<String, String> lupdTSRedisTemplate) {
return lupdTSRedisTemplate.opsForHash();
}
this exception is only occurring when I try to use the Redis hash operations from async method

springboot configuration redis serialization

Why is the error "Could not autowire. No beans of 'RedisConnectionFactory' type found" reported here?
Serialization doesn't work
I used the new way to inject the object and it didn't solve the problem:
#Configuration
public class RedisConfig {
#Resource
private RedisConnectionFactory redisConnectionFactory;
#Bean
public RedisTemplate<Object,Object> redisTemplate(){
RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setStringSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
When I was implementing redis server I solved this issue by writing code like this
#Configuration
public class RedisConfiguration {
#Bean
#ConditionalOnMissingBean(name = "redisTemplate")
#Primary
public <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory connectionFactory) {
final RedisTemplate<String, T> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
ObjectMapper om = new ObjectMapper();
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new JavaTimeModule());
template.setKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer(om));
template.setValueSerializer(new GenericJackson2JsonRedisSerializer(om));
return template;
}
}
This code may be little different from your requirements, but I think if you look closely you can modified according with your needs.

RedisTemplate nullException

There was a problem when I used Springboot to integrate Redis. I want to customize a RedisTemplate, and when I use it, I find that it is always empty and cannot be injected. My code is as follows:
#Configuration
public class RedisConfig {
#Bean(name = "myRedisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
#Autowired
#Qualifier(value = "myRedisTemplate")
private RedisTemplate<String, Object> redisTemplate;
redisTemplate is empty in debug mode.I don't know what went wrong
It could be caused by jedisConnectionFactory do you have such a Bean
#Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}

When set ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to IntegerSerializer in ProducerConfigs in Spring boot kafka, it gives class cast exception

I m using this Spring boot with kafka
to setup my project. but when i run it it will give org.apache.kafka.common.errors.SerializationException: Can't convert key of class java.lang.Integer to class org.apache.kafka.common.serialization.StringSerializer specified in key.serializer
Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
this exception when send the request using kafka template.
#EmbeddedKafka(partitions = 1)
#SpringBootTest
class KafkaApplicationTests {
#Autowired
private MyKafkaListener listener;
#Autowired
private KafkaTemplate<Integer, String> template;
#Autowired
private EmbeddedKafkaBroker embeddedKafka;
#Test
public void testSimple() throws Exception {
template.send("annotated1", 0, "foo");
template.flush();
assertTrue(this.listener.latch1.await(10, TimeUnit.SECONDS));
}
#Configuration
#EnableKafka
public class Config {
#Bean
ConcurrentKafkaListenerContainerFactory<Integer, String>
kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<Integer, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
#Bean
public ConsumerFactory<Integer, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}
#Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
// props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, embeddedKafka.getBrokersAsString());
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
return props;
}
#Bean
public ProducerFactory<Integer, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
#Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class);
// props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, embeddedKafka.getBrokersAsString());
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
return props;
}
#Bean
public KafkaTemplate<Integer, String> kafkaTemplate() {
return new KafkaTemplate<Integer, String>(producerFactory());
}
}
}
But when I change that template.send("annotated1", "key-foo", "foo"); it will work. I have used
#Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class);
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
return props;
}
this configuration as well. But it is still giving me the
Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
If someone there please help me. thanks
You need to add the main application class and Config class to the #SpringBootTest
#SpringBootTest(classes = { So61985794Application.class, So61985794ApplicationTests.Config.class })
to override Boot's normal configuration.

Redis: class java.lang.String cannot be cast to class java.util.List in #Cacheable method

I need to add a Redis cache in a method that returns a list of values.
I'm using this tutorial as basis https://www.baeldung.com/spring-data-redis-tutorial
The exception shows this
java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.List (java.lang.String and java.util.List are in module java.base of loader 'bootstrap')
at
#Cacheable(cacheNames = "customerDetailByParam", key="{#searchParams.toString()}")
#Retryable(value = { HttpServerErrorException.class }, maxAttempts = RETRY_ATTEMPTS, backoff = #Backoff(delay = 5000))
public List<ObjectResponse> searchCustomerDetailByParam(MultiValueMap<String, String> searchParams)
I've been looking for some solutions, however, none seems to work.
CacheConfig.java
#Configuration
#EnableCaching
#ConditionalOnMissingBean(value = CacheManager.class)
#Slf4j
public class CacheConfig {
#Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379);
//redisStandaloneConfiguration.setPassword(RedisPassword.of("yourRedisPasswordIfAny"));
return new JedisConnectionFactory(redisStandaloneConfiguration);
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(jedisConnectionFactory());
template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
template.setDefaultSerializer(serializer);
return template;
}
}
ObjectResponse.java
#Data
#NoArgsConstructor
#AllArgsConstructor
public class ObjectResponse implements Serializable {
#JsonProperty("id")
private String customerId;
#JsonProperty("name")
#JsonAlias("full_name")
private String customerName;
private String document;
private String email;
}
I was able to fix the problem changing the template to the following configuration.
#Bean
public RedisTemplate<String, Object> redisTemplate() {
final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(jedisConnectionFactory());
return template;
}

Resources