从缓存中获取时反序列化带有 @AutoValue 注解的类,在 SpringBoot 应用程序中

huangapple go评论82阅读模式
英文:

Deserialize class with @AutoValue annotation during getting from cache in SpringBoot application

问题

我使用了com.google.auto.value.AutoValue注解创建了一个值类:

@AutoValue
@JsonDeserialize(builder = AutoValue_Company.Builder.class)
public abstract class Company {

public static Builder newBuilder() {
    return new AutoValue_Company.Builder();
}

@JsonProperty("id")
public abstract long id();

@JsonProperty("description")
public abstract String description();

@JsonProperty("websiteUrl")
public abstract String websiteUrl();

@AutoValue.Builder
public interface Builder {
    @JsonProperty("id")
    Builder id(long id);

    @JsonProperty("description")
    Builder description(String description);

    @JsonProperty("websiteUrl")
    Builder websiteUrl(String url);

    Company build();
}
}

这样的类的实例是从服务中接收的,并且结果被缓存在Redis中:

@Cacheable(value = "company")
public Company getValue(String id)

以下是RedisCacheManager的配置:

@Bean(name = "valueCacheManager")
public RedisCacheManager valueCacheManager(final RedisConnectionFactory connectionFactory) {
    final RedisCacheWriter redisCacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
    RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(100));
    return new RedisCacheManager(redisCacheWriter, cacheConfiguration);
}

结果是与反序列化相关的问题:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.test.models.AutoValue_Company and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
英文:

I've created a value class with com.google.auto.value.AutoValue annotation:

@AutoValue
@JsonDeserialize(builder = AutoValue_Company.Builder.class)
public abstract class Company {

public static Builder newBuilder() {
    return new AutoValue_Company.Builder();
}

@JsonProperty("id")
public abstract long id();

@JsonProperty("description")
public abstract String description();

@JsonProperty("websiteUrl")
public abstract String websiteUrl();

@AutoValue.Builder
public interface Builder {
    @JsonProperty("id")
    Builder id(long id);

    @JsonProperty("description")
    Builder description(String description);

    @JsonProperty("websiteUrl")
    Builder websiteUrl(String url);

    Company build();
}
}

Instance of such class is received from service and result is cached in Redis:

@Cacheable(value = "company")
public Company getValue(String id)

Here is the config of RedisCacheManager:

@Bean(name = "valueCacheManager")
public RedisCacheManager valueCacheManager(final RedisConnectionFactory connectionFactory) {
    final RedisCacheWriter redisCacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
    RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(100));
    return new RedisCacheManager(redisCacheWriter, cacheConfiguration);
}

As a result the issue that is connected to deserialization:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.test.models.AutoValue_Company and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

答案1

得分: 2

The solution was found by changing serializer GenericJackson2JsonRedisSerializer to Jackson2JsonRedisSerializer<>(Company.class).

So the cache config now looks like that:

@Bean(name = "valueCacheManager")
public RedisCacheManager valueCacheManager(final RedisConnectionFactory connectionFactory) {
    final RedisCacheWriter redisCacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
    RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
             .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Company.class)));
    cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(100));
    return new RedisCacheManager(redisCacheWriter, cacheConfiguration);
}
英文:

The solution was found by changing serializer GenericJackson2JsonRedisSerializer to Jackson2JsonRedisSerializer<>(Company.class)

So the cache config now looks like that:

@Bean(name = "valueCacheManager")
public RedisCacheManager valueCacheManager(final RedisConnectionFactory connectionFactory) {
    final RedisCacheWriter redisCacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
    RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
             .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Company.class)));
    cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(100));
    return new RedisCacheManager(redisCacheWriter, cacheConfiguration);
}

答案2

得分: 0

或许你应该使用getter的命名约定来命名你的方法,例如getId()等?我认为这个链接与此相关。

英文:

Maybe you should name your methods using getters convention e.g. getId() etc? I think this is related.

huangapple
  • 本文由 发表于 2020年7月27日 20:58:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63115839.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定