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 on Graal: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor #194

Open
4 tasks done
j1cs opened this issue Apr 29, 2021 · 11 comments
Labels
type: bug Something isn't working

Comments

@j1cs
Copy link

j1cs commented Apr 29, 2021

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Create a new app with: mn create-app me.jics.backend -b maven -f graalvm,lombok,openapi,redis-lettuce,cache-ehcache -t spock
  2. Configure Redis cache as shown in the documentation
  3. Run ./mvnw package -Dpackaging=native-image

Expected Behaviour

after starting it should caching the result

Actual Behaviour

Doesn't caching anything.
With this error:

[lettuce-nioEventLoop-5-4] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor
io.micronaut.core.serialize.exceptions.SerializationException: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor

Environment Information

  • Operating System: Arch Linux

  • Micronaut Version: 2.5.0

  • JDK Version:

     $ native-image --version
     GraalVM 21.1.0 Java 11 CE (Java Version 11.0.11+8-jvmci-21.1-b05)
    
     $ java -version
      openjdk version "11.0.11" 2021-04-20
      OpenJDK Runtime Environment GraalVM CE 21.1.0 (build 11.0.11+8-jvmci-21.1-b05)
      OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (build 11.0.11+8-jvmci-21.1-b05, mixed mode, sharing)
    

Example Application

Complete stacktrace

15:32:30.361 [default-nioEventLoopGroup-1-5] INFO  me.jics.StoreController - Entering to StoreController.getAll
15:32:30.363 [lettuce-nioEventLoop-5-4] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor
io.micronaut.core.serialize.exceptions.SerializationException: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor
	at io.micronaut.core.serialize.JdkSerializer.deserialize(JdkSerializer.java:82)
	at io.micronaut.core.serialize.ObjectSerializer.deserialize(ObjectSerializer.java:109)
	at io.micronaut.core.serialize.ObjectSerializer.deserialize(ObjectSerializer.java:127)
	at io.micronaut.configuration.lettuce.cache.RedisCache$RedisAsyncCache.getWithExpire(RedisCache.java:407)
	at io.micronaut.configuration.lettuce.cache.RedisCache$RedisAsyncCache.lambda$get$0(RedisCache.java:330)
	at java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1072)
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
	at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2073)
	at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:122)
	at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111)
	at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:737)
	at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:672)
	at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:589)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:829)
	at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:553)
	at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: java.io.InvalidClassException: java.util.ArrayList; no valid constructor
	at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:159)
	at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:875)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2170)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
	at io.micronaut.core.serialize.JdkSerializer.deserialize(JdkSerializer.java:72)
	... 30 common frames omitted
@graemerocher
Copy link
Contributor

graemerocher commented Apr 29, 2021

Can you try using the Jackson serializer https://micronaut-projects.github.io/micronaut-redis/latest/guide/#sessions

JDK serialisation will be deprecated soon

@j1cs
Copy link
Author

j1cs commented Apr 29, 2021

@j1cs
Copy link
Author

j1cs commented Apr 29, 2021

I checked redis and still using java serializer:

127.0.0.1:6379> get "stores:ParametersKey: "
"\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\a~w\x04\x00\x00\a~sr\x00\rme.jics.Store\x962\x93\x90\xbe\xe8\xf4\xd3\x02\x00\x0eL\x00\aaddresst\x00\x12Ljava/lang/String;L\x00\aborought\x00\x13Ljava/lang/Integer;L\x00\x0bboroughNameq\x00~\x00\x03L\x00\x0cclosingHourst\x00\x15Ljava/time/LocalTime;L\x00\x04datet\x00\x15Ljava/time/LocalDate;L\x00\x02idq\x00~\x00\x03L\x00\blatitudet\x00\x12Ljava/lang/Double;L\x00\blocationq\x00~\x00\x03L\x00\tlongitudeq\x00~\x00\aL\x00\x04nameq\x00~\x00\x03L\x00\nopeningDayq\x00~\x00\x03L\x00\x0copeningHoursq\x00~\x00\x05L\x00\x05phoneq\x00~\x00\x03L\x00\x06regionq\x00~\x00\x04xpt\x00\x15AVENIDA EL SALTO 2972sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00zt\x00\bRECOLETAsr\x00\rjava.time.Ser\x95]\x84\xba\x1b\"H\xb2\x0c\x00\x00xpw\x03\x04\x13\xe1xsq\x00~\x00\x0ew\a\x03\x00\x00\a\xe5\x04\x1dxt\x00\x03534sr\x00\x10java.lang.Double\x80\xb3\xc2J)k\xfb\x04\x02\x00\x01D\x00\x05valuexq\x00~\x00\x0b\xc0@\xb3'>2j\xb6t\x00\bRECOLETAsq\x00~\x00\x12\xc0Q\xa8@\xb7\x14\xd4\xa4t\x00\nTORRES MPDt\x00\x06juevessq\x00~\x00\x0ew\x03\x04\n\xe1xt\x00\r+560225053570sq\x00~\x00\n\x00\x00\x00\asq\x00~\x00\x02t\x00\x0eSAN MARTIN 174sq\x00~\x00\n\x00\x00\x00St\x00\x04BUINsq\x00~\x00\x0ew\x02\x04\xe9xsq\x00~\x00\x0ew\a\x03\x00\x00\a\xe5\x04\x1dxt\x00\x03753sq\x00~\x00\x12\xc0@\xdd\xb2-\x0eV

Updated: setting @Cacheable in the controller didn't work too.

@j1cs
Copy link
Author

j1cs commented Apr 29, 2021

Now adding

redis:
  uri: redis://${REDI_URI:localhost}
  cache:
    value-serializer: io.micronaut.jackson.serialize.JacksonObjectSerializer

It works when running with the openjdk:

127.0.0.1:6379> get "stores:ParametersKey: "
"[{\"date\":[2021,4,29],\"id\":\"534\",\"name\":\"Torres Mpd\",\"boroughName\":\"Recoleta\",\"location\":\"Recoleta\",\"address\":\"Avenida El Salto 2972\",\"openingHours\":[10,30],\"closingHours\":[19,30],\"phone\":\"+560225053570\",\"latitude\":-33.3996351,\"longitude\":-70.62894990000001,\"openingDay\":\"jueves\",\"region\":7,\"borough\":122},{\"date\":[2021,4,29],\"id\":\"753\",\"name\":\"Ahumada\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"San Martin 174\",\"openingHours\":[8,30],\"closingHours\":[22,0],\"phone\":\"+560226313086\",\"latitude\":-33.732,\"longitude\":-70.735941,\"openingDay\":\"jueves\",\"region\":7,\"borough\":83},{\"date\":[2021,4,29],\"id\":\"754\",\"name\":\"Ahumada\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"Bernardino Bravo  0115\",\"openingHours\":[9,0],\"closingHours\":[22,0],\"phone\":\"+560226313531\",\"latitude\":-33.733602,\"longitude\":-70.733803,\"openingDay\":\"jueves\",\"region\":7,\"borough\":83},{\"date\":[2021,4,29],\"id\":\"755\",\"name\":\"Buin\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"Manuel Rodriguez 270\",\"openingHours\":[9,30],\"closingHours\":[20,30],\"phone\":\"+560228213917\",\"latitude\":-33.729515,\"longitude\":-70.739232,\"openingDay\":\"jueves\",\"r

However doesn't work with the native image:

15:48:21.841 [default-nioEventLoopGroup-1-2] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

Message: Error resolving field value [redis.cache.value-serializer]. Property doesn't exist or cannot be converted
Path Taken: new $StoreControllerDefinition$Intercepted([IStoreService service],BeanContext $beanContext,Qualifier $qualifier,List $interceptors) --> new $StoreServiceDefinition$Intercepted(PharmacyClient pharmacyClient,BeanContext $beanContext,Qualifier $qualifier,[List $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager) --> new RedisCache([DefaultRedisCacheConfiguration defaultRedisCacheConfiguration],RedisCacheConfiguration redisCacheConfiguration,ConversionService conversionService,BeanLocator beanLocator) --> DefaultRedisCacheConfiguration.valueSerializer
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

@graemerocher
Copy link
Contributor

Try add @TypeHint(io.micronaut.jackson.serialize.JacksonObjectSerializer.class) to your Application class

@j1cs
Copy link
Author

j1cs commented Apr 29, 2021

Didn't work:

16:30:35.727 [lettuce-nioEventLoop-5-4] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor
io.micronaut.core.serialize.exceptions.SerializationException: I/O error occurred during deserialization: java.util.ArrayList; no valid constructor

Redis shows:

127.0.0.1:6379> get "stores:ParametersKey: "
"\xac\xed\x00\x05sr\x00\x13java.util.ArrayList\x18\xfc\xda\xcfW\xa5^h\x02\x00\x00xp"

(changes pushed btw)

@j1cs
Copy link
Author

j1cs commented Apr 30, 2021

Now adding

redis:
  uri: redis://${REDI_URI:localhost}
  cache:
    value-serializer: io.micronaut.jackson.serialize.JacksonObjectSerializer

It works when running with the openjdk:

127.0.0.1:6379> get "stores:ParametersKey: "
"[{\"date\":[2021,4,29],\"id\":\"534\",\"name\":\"Torres Mpd\",\"boroughName\":\"Recoleta\",\"location\":\"Recoleta\",\"address\":\"Avenida El Salto 2972\",\"openingHours\":[10,30],\"closingHours\":[19,30],\"phone\":\"+560225053570\",\"latitude\":-33.3996351,\"longitude\":-70.62894990000001,\"openingDay\":\"jueves\",\"region\":7,\"borough\":122},{\"date\":[2021,4,29],\"id\":\"753\",\"name\":\"Ahumada\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"San Martin 174\",\"openingHours\":[8,30],\"closingHours\":[22,0],\"phone\":\"+560226313086\",\"latitude\":-33.732,\"longitude\":-70.735941,\"openingDay\":\"jueves\",\"region\":7,\"borough\":83},{\"date\":[2021,4,29],\"id\":\"754\",\"name\":\"Ahumada\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"Bernardino Bravo  0115\",\"openingHours\":[9,0],\"closingHours\":[22,0],\"phone\":\"+560226313531\",\"latitude\":-33.733602,\"longitude\":-70.733803,\"openingDay\":\"jueves\",\"region\":7,\"borough\":83},{\"date\":[2021,4,29],\"id\":\"755\",\"name\":\"Buin\",\"boroughName\":\"Buin\",\"location\":\"Buin\",\"address\":\"Manuel Rodriguez 270\",\"openingHours\":[9,30],\"closingHours\":[20,30],\"phone\":\"+560228213917\",\"latitude\":-33.729515,\"longitude\":-70.739232,\"openingDay\":\"jueves\",\"r

However doesn't work with the native image:

15:48:21.841 [default-nioEventLoopGroup-1-2] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

Message: Error resolving field value [redis.cache.value-serializer]. Property doesn't exist or cannot be converted
Path Taken: new $StoreControllerDefinition$Intercepted([IStoreService service],BeanContext $beanContext,Qualifier $qualifier,List $interceptors) --> new $StoreServiceDefinition$Intercepted(PharmacyClient pharmacyClient,BeanContext $beanContext,Qualifier $qualifier,[List $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager) --> new RedisCache([DefaultRedisCacheConfiguration defaultRedisCacheConfiguration],RedisCacheConfiguration redisCacheConfiguration,ConversionService conversionService,BeanLocator beanLocator) --> DefaultRedisCacheConfiguration.valueSerializer
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

I think this is a bug. Because when you put the deserialization form in the application.yml file and micronaut-redis is not able to inject the value correctly.

@graemerocher graemerocher transferred this issue from micronaut-projects/micronaut-core Apr 30, 2021
@j1cs
Copy link
Author

j1cs commented May 1, 2021

I was able to replicate the error in a newly created project: https://github.com/j1cs/micronaut-redis-cache-issue
I executed:

$ ./mvnw package -Dpackaging=native-image
[INFO] Executing: /usr/lib/jvm/java-11-graalvm/lib/svm/bin/native-image -cp  ...
$ docker-compose up
Creating redis ... done
Attaching to redis
redis    | 1:C 01 May 2021 17:09:27.724 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis    | 1:C 01 May 2021 17:09:27.724 # Redis version=6.2.2, bits=64, commit=00000000, modified=0, pid=1, just started
$ ./target/cache
13:03:40.275 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 34ms. Server Running: http://localhost:8080
$ curl http://localhost:8080/main
13:03:46.274 [default-nioEventLoopGroup-1-3] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

Message: Error resolving field value [redis.cache.value-serializer]. Property doesn't exist or cannot be converted
Path Taken: new MainController([MainService service]) --> new $MainServiceDefinition$Intercepted(BeanContext $beanContext,Qualifier $qualifier,[List $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager) --> new RedisCache([DefaultRedisCacheConfiguration defaultRedisCacheConfiguration],RedisCacheConfiguration redisCacheConfiguration,ConversionService conversionService,BeanLocator beanLocator) --> DefaultRedisCacheConfiguration.valueSerializer
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for field [valueSerializer] of class: io.micronaut.configuration.lettuce.cache.DefaultRedisCacheConfiguration

Message: Error resolving field value [redis.cache.value-serializer]. Property doesn't exist or cannot be converted
Path Taken: new MainController([MainService service]) --> new $MainServiceDefinition$Intercepted(BeanContext $beanContext,Qualifier $qualifier,[List $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager) --> new RedisCache([DefaultRedisCacheConfiguration defaultRedisCacheConfiguration],RedisCacheConfiguration redisCacheConfiguration,ConversionService conversionService,BeanLocator beanLocator) --> DefaultRedisCacheConfiguration.valueSerializer

Hope helps.

@graemerocher graemerocher added the type: bug Something isn't working label May 1, 2021
@j1cs
Copy link
Author

j1cs commented Aug 21, 2021

this error doesn't occur with version 3

@j1cs j1cs closed this as completed Aug 21, 2021
@j1cs
Copy link
Author

j1cs commented Aug 21, 2021

I'm sorry. I was wrong the issue still persist.

@Alex100

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants