Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis repository: Error while converting to Timestamp #2898

Open
soheilrahsaz opened this issue Apr 21, 2024 · 3 comments
Open

Redis repository: Error while converting to Timestamp #2898

soheilrahsaz opened this issue Apr 21, 2024 · 3 comments
Assignees
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@soheilrahsaz
Copy link

Using Spring data Redis 3.2.5 and repository,
Given this structure

@RedisHash("Fruit")
public class Fruit {
    @Id
    private Integer id;
    private String name;
    private Timestamp createdAt;
}

And

public interface FruitRedisRepository extends CrudRepository<Fruit, Integer> {}
@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisConnectionFactory()
    {
        return new LettuceConnectionFactory("localhost", 16379);
    }
}

This test fails and throws exception:

@SpringBootTest
class TestSpringRedisApplicationTests {

    @Autowired
    FruitRedisRepository fruitRedisRepository;

    @Test
    void test() {
        //creating sample fruit
        Fruit fruit = new Fruit(1, "banana", Timestamp.from(Instant.now()));

        //fruit is saved into redis with no problem
        assertThat(fruitRedisRepository.save(fruit)).isNotNull();

        //this should work fine but throws exception because of the timestamp
        assertThat(fruitRedisRepository.findById(1)).isNotNull();
    }
}

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [byte[]] to type [java.sql.Timestamp]

at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:294)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:185)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:165)
at org.springframework.data.redis.core.convert.MappingRedisConverter.fromBytes(MappingRedisConverter.java:998)
at org.springframework.data.redis.core.convert.MappingRedisConverter.readProperty(MappingRedisConverter.java:329)
at org.springframework.data.redis.core.convert.MappingRedisConverter.lambda$doReadInternal$0(MappingRedisConverter.java:245)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:298)
at org.springframework.data.redis.core.convert.MappingRedisConverter.doReadInternal(MappingRedisConverter.java:237)
at org.springframework.data.redis.core.convert.MappingRedisConverter.read(MappingRedisConverter.java:183)
at org.springframework.data.redis.core.convert.MappingRedisConverter.read(MappingRedisConverter.java:114)
at org.springframework.data.redis.core.RedisKeyValueAdapter.get(RedisKeyValueAdapter.java:290)
at org.springframework.data.keyvalue.core.KeyValueTemplate.lambda$findById$3(KeyValueTemplate.java:241)
at org.springframework.data.keyvalue.core.KeyValueTemplate.execute(KeyValueTemplate.java:314)
at org.springframework.data.keyvalue.core.KeyValueTemplate.findById(KeyValueTemplate.java:239)
at org.springframework.data.keyvalue.repository.support.SimpleKeyValueRepository.findById(SimpleKeyValueRepository.java:98)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy2/jdk.proxy2.$Proxy59.findById(Unknown Source)
at ir.co.rrr.testspringredis.TestSpringRedisApplicationTests.test(TestSpringRedisApplicationTests.java:30)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

But the timestamp is saved correctly in redis:
hmget Fruit:1 id name createdAt

  1. "1"
  2. "banana"
  3. "1713704899797"
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 21, 2024
@mp911de
Copy link
Member

mp911de commented Apr 23, 2024

Have you tried registering a custom Converter<byte[], Timestamp>? We don't support the SQL timestamp as Redis isn't SQL.

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Apr 23, 2024
@mp911de mp911de added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged labels Apr 23, 2024
@soheilrahsaz
Copy link
Author

I was mistaking that because it did convert Timestamp to byte[], then it should do the inverse conversion as well.
(The conversion from Timestamp to byte[] was because of a BinaryConverter from java.util.date to byte[])

By following documentations, I created a Converter<byte[], Timestamp> and registered it using RedisCustomConversions, but still it throws the same exception and I couldn't find out what am I doing wrong here.
Could you give me a hint on this?

@ReadingConverter
@Component
public class CustomReadingTimestampConverter implements Converter<byte[], Timestamp> {
    @Override
    public Timestamp convert(byte @NonNull [] source) {
        return new Timestamp(Long.parseLong(new String(source)));
    }
}
@Configuration
public class RedisConfig {

    @Bean
    public RedisCustomConversions customConversions(CustomReadingTimestampConverter customTimestampConverter){
        return new RedisCustomConversions(List.of(customTimestampConverter));
    }

@mp911de mp911de added status: waiting-for-triage An issue we've not yet triaged and removed status: invalid An issue that we don't feel is valid labels Apr 23, 2024
@mp911de mp911de reopened this Apr 23, 2024
@mp911de mp911de self-assigned this Apr 29, 2024
@SergeyBasharkin
Copy link

You must register a bean with the name redisCustomConversions like this:

@Bean
public RedisCustomConversions redisCustomConversions(CustomReadingTimestampConverter customTimestampConverter){
    return new RedisCustomConversions(List.of(customTimestampConverter));
}

Please add to the documentation that the bean must match by name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

4 participants