skip to Main Content

I have a method

  @Cacheable(value = USER_IDENTITIES_PROTO_CACHE)
    public UserIdentitiesResponseOuterClass.UserIdentitiesResponse findUserIdentitiesProto(UUID userId) {

where UserIdentitiesResponseOuterClass.UserIdentitiesResponse is a class generated by protobuff.

When using JVM everything works well but in the native image I am getting the exception

"Failure putting into cache: user_identities_proto. Cannot serialize"

I have tried to add

 hints.serialization()
                .registerType(TypeReference.of(UserIdentitiesResponseOuterClass.class))
                .registerType(UserIdentitiesResponseOuterClass.UserIdentity.class)
                .registerType(UserIdentitiesResponseOuterClass.UserIdentitiesResponse.class);

but it did not help.

I am using Redis as a cache and using JdkSerializationRedisSerializer to serialize.

Content of proto file below:

syntax = "proto3";

package identity;

message UserIdentity {
  string provider = 1;
  string sub = 2;
}

message UserIdentitiesResponse {
  UserIdentity primary = 1;
  repeated UserIdentity identities = 2;
}

if an application is run in JVM mode (not native) protobuff object is successfully serialized/deserialized. But in native image the mentioned problem happens.

I am assuming the solution would be to add the runtime hints.serialization(), but as I mentioned I did it and it did not help, so something is still missing, but it’s not clear what exactly

How to fix it?

2

Answers


  1. "Failure putting into cache: user_identities_proto. Cannot serialize" indicates that GraalVM cannot serialize the UserIdentitiesResponse object when you’re trying to cache it using Redis.
    The @Cacheable annotation in Spring uses Java’s default serialization mechanism, but protobuf classes do not support Java serialization out of the box. They need to be serialized using protobuf’s own serialization mechanisms.
    JdkSerializationRedisSerializer relies on Java’s built-in serialization, which is incompatible with protobuf objects.
    You should use a different Redis serializer compatible with protobuf. Spring Data Redis provides a few options, but you might need to implement your own or find a third-party library that supports protobuf.

    Login or Signup to reply.
  2. Use this solution. Add RuntmeHints to your spring initialization class and add all the classes you will cache.

    @SpringBootApplication
    @ImportRuntimeHints(Main.RuntimeHints.class)
    public class Main {
    
    public static void main(String[] args) {
        new SpringApplicationBuilder(WebServerConfig.class)
                .bannerMode(Banner.Mode.OFF)
                .run(args);
    }
    
    @PostConstruct
    public void init(){
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
    static class RuntimeHints implements RuntimeHintsRegistrar {
        @Override
        public void registerHints(org.springframework.aot.hint.RuntimeHints hints, ClassLoader classLoader) {
            // Register serialization
            hints.serialization()
                    .registerType(MacroRegion.class)
                    .registerType(ZipCode.class)
                    .registerType(MacroRegioesCollection.class)
                    .registerType(BranchRegionalization.class)
                    .registerType(ZipCodeRange.class)
                    .registerType(FilialRegionalizacaoCollection.class)
                    .registerType(HashMap.class)
                    .registerType(HashSet.class)
                    .registerType(ArrayList.class)
                    .registerType(LinkedList.class);
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search