Obteniendo un IllegalArgumentException: No se puede convertir un String a AtomicInteger al intentar agregar datos que contienen un int de tipo AtomicInteger en la caché de Redis.
Estoy tratando de agregar un modelo de datos a una caché de Redis. Cuando saco el modelo, obtengo la excepción
org.springframework.core.convert.ConversionFailedException: No se pudo convertir desde el tipo [byte[]] al tipo [java.util.concurrent.atomic.AtomicInteger] para el valor '{53}'; la excepción anidada es java.lang.IllegalArgumentException: No se puede convertir la cadena [5] a la clase de destino [java.util.concurrent.atomic.AtomicInteger]] con causa raíz
El modelo es
@RedisHash(value = "ThottleRate", timeToLive = 5)
<p>public class ThottleRate implements Serializable {</p>
<pre><code> private static final long serialVersionUID = 1L;
@Id
private String url;
private AtomicInteger rate;
public ThottleRate(String url, int rate) {
super();
this.url = url;
this.rate = new AtomicInteger(rate);
}
public boolean isAllowed(){
if(this.rate.decrementAndGet() <= 0) {
return false;
}
return true;
}
</code></pre>
<p><code>
El código de llamada es
</code>
try {
option = throttleRateRepository.findById(url);
ThottleRate rate = option.get();
allow = rate.isAllowed();
} catch(NoSuchElementException e) {
throttleRateRepository.save(new ThottleRate(url, 5));
allow = true;
}
Lo que estoy tratando de hacer es la funcionalidad de limitación de frecuencia, usando la caché de Redis. Tiene un tiempo de vida, y dentro de ese tiempo un número de veces que una URL puede ser accedida.
Pero cuando se hace la llamada
option = throttleRateRepository.findById(url);
esto genera la IllegalArgumentException
Esto parece la forma más simple de usar la caché de Redis con un tiempo de vida y un número de tasas.
davy.ai
El problema parece estar en la conversión del tipo de dato de byte[] a AtomicInteger. Cuando se recupera el modelo de Redis, el campo rate se devuelve como byte[] en lugar de AtomicInteger. Esto hace que se produzca una ConversionFailedException al intentar convertirlo de nuevo a AtomicInteger.
Para solucionar este problema, es necesario implementar un RedisSerializer personalizado para AtomicInteger. Este serializer convertirá el objeto AtomicInteger a byte[] antes de guardarlo en Redis, y lo volverá a convertir en AtomicInteger al recuperarlo de Redis.
Aquí hay un ejemplo de implementación del RedisSerializer personalizado para AtomicInteger:
Para utilizar este serializer personalizado, se debe registrar con el RedisTemplate utilizado para interactuar con Redis. Esto puede hacerse añadiendo el siguiente código:
Este código establece el serializer de clave en el StringRedisSerializer predeterminado y el serializer de valor en el AtomicIntegerSerializer personalizado.
Con este serializer personalizado en su lugar, el modelo ThrottleRate debería poder recuperarse de Redis sin que se produzca ningún ConversionFailedException.