In spring-data-redis, How do we need configure custom converters that can be auto-wired/injected from Spring boot application or configuration.
I read about @R
Tested with spring-boot-starter-data-redis:2.0.4.RELEASE.
I was facing a problem where my OffsetDateTime
properties of my @RedisHash
entity were not being stored when using CrudRepository
.
The problem was that Jsr310Converters
does not have a converter of OffsetDateTime
.
To solve this, I created a reading converter:
@Component
@ReadingConverter
public class BytesToOffsetDateTimeConverter implements Converter<byte[], OffsetDateTime> {
@Override
public OffsetDateTime convert(final byte[] source) {
return OffsetDateTime.parse(new String(source), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
}
and writing converter:
@Component
@WritingConverter
public class OffsetDateTimeToBytesConverter implements Converter<OffsetDateTime, byte[]> {
@Override
public byte[] convert(final OffsetDateTime source) {
return source.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME).getBytes();
}
}
And registered a RedisCustomConversions
bean in the configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import java.util.Arrays;
@Configuration
@EnableRedisRepositories
public class RedisConfiguration {
@Bean
public RedisCustomConversions redisCustomConversions(OffsetDateTimeToBytesConverter offsetToBytes,
BytesToOffsetDateTimeConverter bytesToOffset) {
return new RedisCustomConversions(Arrays.asList(offsetToBytes, bytesToOffset));
}
}
You have to declare CustomConversions bean named "redisCustomConversions" in your application configuration.
@Bean
public CustomConversions redisCustomConversions(){
return new CustomConversions(Arrays.asList(new YourWritingConverter(), new YourReadingConverter()));
}
Try to implement this way.
import java.sql.Timestamp;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.stereotype.Component;
@Component
@ReadingConverter
public class BytesToDateConverter implements Converter<byte[], Timestamp> {
@Override
public Timestamp convert(final byte[] source) {
String value = new String(source);
return new Timestamp(Long.parseLong(value));
}
}
and resister to the Bean.
@Bean
public MappingRedisConverter redisConverter(RedisMappingContext mappingContext,
RedisCustomConversions customConversions, ReferenceResolver referenceResolver) {
MappingRedisConverter mappingRedisConverter = new MappingRedisConverter(mappingContext, null, referenceResolver,
customTypeMapper());
mappingRedisConverter.setCustomConversions(redisCustomConversions());
return mappingRedisConverter;
}
@Bean
public RedisTypeMapper customTypeMapper() {
return new CustomRedisTypeMapper();
}
public RedisCustomConversions redisCustomConversions() {
return new RedisCustomConversions(
Arrays.asList(new OffsetDateTimeToBytesConverter(), new BytesToOffsetDateTimeConverter(),new BytesToDateConverter()));
}
class CustomRedisTypeMapper extends DefaultRedisTypeMapper {
}
These code may help anyone. Thanks @Mikhail
@Component
public class RedisObjectHelper {
@Resource
private RedisTemplate<String, ?> redisTemplate;
private HashOperations<String, byte[], byte[]> hashOperations;
private HashMapper<Object, byte[], byte[]> mapper;
@PostConstruct
public void init() {
mapper = new ObjectHashMapper(new CustomConversions(Arrays.asList(new Timestamp2ByteConverter(), new Byte2TimestampConverter())));
hashOperations = redisTemplate.opsForHash();
}
// and any methods
}
tested with spring-data-redis-1.8.4.RELEASE