Spring RestClient puede convertir el JSON directamente en un record de Java. Conserva los tipos como BigDecimal, inyecta la clave desde la configuración y no descartes source, market_session ni data_updated_at.
RestClient para un cliente síncrono tipado.BigDecimal.EXCHANGERATE_API_KEY, nunca desde un archivo de propiedades incluido en el repositorio.data_updated_at junto con el tipo.Crea un RestClient tipado
El record conserva el mapa de tipos y los campos necesarios para interpretarlo. Jackson asigna los nombres snake_case con @JsonProperty y Spring decodifica el JSON.
package com.example.fx;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
record LatestRates(
String base,
String source,
@JsonProperty("market_session") String marketSession,
@JsonProperty("data_updated_at") Instant dataUpdatedAt,
Map<String, BigDecimal> rates
) {}
@Component
public final class ExchangeRateClient {
private final RestClient client;
public ExchangeRateClient(
RestClient.Builder builder,
@Value("${exchangerate.api-key}") String apiKey
) {
this.client = builder
.baseUrl("https://api.exchangerate.dev/v1")
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
.build();
}
public LatestRates latest(String base) {
return client.get()
.uri("/latest/{base}?symbols=EUR,GBP", base)
.retrieve()
.body(LatestRates.class);
}
}Carga la clave desde el entorno
exchangerate:
api-key: ${EXCHANGERATE_API_KEY}Trata la frescura y los errores de forma explícita
RestClient.retrieve() lanza una excepción ante respuestas 4xx y 5xx, de modo que una llamada fallida nunca se convierte en un cero almacenado en caché. Añade límites de tiempo y reintenta solo fallos transitorios. Un 401 exige corregir la clave; un 429 sostenido exige reducir tráfico o ampliar el límite.
BigDecimal, multiplica con una política de redondeo explícita y redondea solo el monto final para la moneda de destino. El tipo de la API debe conservar su precisión completa.- Reutiliza un RestClient configurado.
- Define límites de conexión y lectura.
- Almacena solo respuestas correctas.
- Conserva source, marketSession y dataUpdatedAt.
