Skip to main content

The Iconic Client

1. Descripción general

theiconic-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con la API de The Iconic, marketplace de moda integrado en el ecosistema de microservicios de Hawkers. El proyecto no expone ningún endpoint REST propio; se publica en el registro de artefactos Maven interno y es consumido por otros microservicios que necesiten consultar y gestionar pedidos, ítems de pedido, productos y stock en The Iconic.

El proyecto contiene dos clientes de API: TheIconicRestClient, el cliente activo que consume la API v2 mediante @HttpExchange, y TheIconicClient, un cliente explícitamente marcado como @Deprecated que refleja una API v1 basada en parámetros de firma HMAC en la query string (heredada de una integración previa con Feign, hoy comentada en el código).

2. Información técnica

PropiedadValor
artifactIdtheiconic-client
groupIdcom.hawkersco
version1.0.25-SNAPSHOT
Java25
Spring Boot4.0.6
Tipo de artefactoJAR (librería, no ejecutable)
MódulosProyecto único (no multi-módulo)

3. Arquitectura y diseño

Estructura del proyecto:

com.hawkersco.theiconicclient
├── TheIconicClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ ├── TheIconicRestClient.java # Interfaz @HttpExchange ACTIVA: pedidos, ítems, productos, stock (API v2)
│ ├── TheIconicTokenRestClient.java # Interfaz @HttpExchange para /oauth/client-credentials
│ └── TheIconicClient.java # @Deprecated — API v1 legacy basada en firma HMAC en query string
├── config/
│ ├── TheIconicAutoConfiguration.java # @AutoConfiguration principal (registra ambos clientes v2)
│ ├── TheIconicRestConfig.java # @ConfigurationProperties (grantType, clientId, clientSecret)
│ ├── TheIconicClientConfig.java # Configuración vacía retenida para el cliente legacy (ver sección 13)
│ ├── CacheStore.java # Cache genérica en memoria (Guava)
│ └── CacheStoreBeans.java # Bean CacheStore<String> (TTL 1h) para tokens, no usado por la autoconfiguración actual (ver sección 13)
├── request/ # ProductRequest, ProductStockRequest, TheIconicOrderIDs, TheIconicReadyToShipRequest,
│ # TheIconicTokenResponse, ProductResponse
├── response/ # OrdersTheIconicRestResponse, TheIconicItemsResponse, ProductStocksTheIconicResponse,
│ # StockProductResponse, y modelos legacy (OrdersTheIconicResponse, OrderItems*TheIconicResponse)
└── utils/
└── TheIconicUtils.java # Utilidades legacy: timestamps ISO 8601, firma HMAC, query string, marshalling JAXB

Flujo principal (TheIconicRestClient, API v2 activa)

sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Client as TheIconicRestClient
participant TokenClient as TheIconicTokenRestClient
participant API as API The Iconic v2

Consumidor->>Client: getOrders / getItems / putStockProduct / ...
Client->>TokenClient: getToken(grant_type, client_id, client_secret)
TokenClient->>API: POST /oauth/client-credentials
API-->>TokenClient: { "access_token": "..." }
TokenClient-->>Client: token
Client->>API: request + Authorization: Bearer <token>
API-->>Client: ResponseEntity<T>
Client-->>Consumidor: ResponseEntity<T>

La autoconfiguración (TheIconicAutoConfiguration) se activa condicionalmente con @ConditionalOnProperty(prefix = "theiconic.api", name = "url") y usa @EnableConfigurationProperties(TheIconicRestConfig.class) para vincular grantType/clientId/clientSecret. Registra dos beans (ambos con @ConditionalOnMissingBean, permitiendo que un consumidor los sobrescriba):

  • theIconicTokenRestClientRestClient sin interceptor, usado únicamente para /oauth/client-credentials.
  • theIconicRestClientRestClient cuyo requestInterceptor solicita un token nuevo en cada petición (sin ninguna consulta a caché previa, ver sección 13) e inyecta Authorization: Bearer <token>.

El registro de la autoconfiguración se realiza mediante el fichero estándar de Spring Boot:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

TheIconicClient (API v1 legacy) contiene una línea comentada //@FeignClient(...), confirmando que el proyecto migró de Spring Cloud OpenFeign a Spring @HttpExchange; sin embargo, la interfaz legacy conserva anotaciones Spring MVC (@GetMapping/@PostMapping) en lugar de anotaciones Feign nativas, y no está registrada en ninguna autoconfiguración — no hay ningún bean que la instancie automáticamente. TheIconicUtils contiene la lógica de apoyo para esta API v1 (firma HMAC, timestamps con formato específico, marshalling JAXB de ProductRequest).

4. Dependencias principales

DependenciaVersiónPropósito
spring-boot-starter(gestionada SB4)Base de Spring Boot (contexto, autoconfiguración, @ConfigurationProperties)
spring-web(gestionada SB4)RestClient + @HttpExchange / HttpServiceProxyFactory
jakarta.xml.bind:jakarta.xml.bind-api4.0.2Anotaciones JAXB para el marshalling XML legacy (TheIconicUtils.jaxbObjectToXML)
com.sun.xml.bind:jaxb-impl4.0.5Implementación de referencia de JAXB
com.google.guava:guava33.4.0-jreImplementación de caché en CacheStore (CacheBuilder)
com.google.code.gson:gson(gestionada SB4)Serialización Gson en los modelos (soporte dual con Jackson)
com.fasterxml.jackson.core:jackson-databind(gestionada SB4)Serialización/deserialización Jackson en los modelos
org.projectlombok:lombok1.18.42 (dependencia; annotationProcessorPath del compilador usa 1.18.46)Generación de boilerplate en los modelos
spring-boot-starter-test(gestionada SB4)Testing (scope test)

5. API / Endpoints

No aplica a este proyecto. theiconic-client es una librería cliente JAR que no expone endpoints REST propios. Las operaciones que encapsula sobre la API de The Iconic se detallan en la sección 6.

6. Integraciones externas

API v2 de The Iconic — TheIconicRestClient (activo)

MétodoHTTPRuta remotaDescripción
getOrdersGET/v2/ordersLista todos los pedidos
getOrderByIdGET/v2/orders/{orderId}Consulta un pedido por ID numérico
getOrdersPendingGET/v2/orders?section=status_pending&limit=&offset=Lista pedidos pendientes, paginado
setStatusReadyToShipPOST/v2/orders/statuses/set-to-ready-to-shipMarca líneas de pedido como listas para envío (body JSON crudo)
setStatusShippedPOST/v2/orders/statuses/set-to-shippedMarca líneas de pedido como enviadas
getItemsGET/v2/order-items?orderNumbers[]=&limit=&offset=Consulta ítems de pedido por número(s) de pedido, paginado
getProductBySellerSkuGET/v2/product/seller-sku/{sku}Consulta un producto por SKU del vendedor
getStockProductByIdGET/v2/stock/product/{productId}Consulta el stock de un producto por ID
putStockProductPUT/v2/stock/productActualiza stock en lote para varios productos

API v1 de The Iconic — TheIconicClient (@Deprecated, sin autoconfiguración)

MétodoHTTPDescripción
getGETLlamada genérica con Action/Version/Format/Signature/Timestamp/UserID/Filter
getOrdersGETLista pedidos pendientes creados después de una fecha, firmados con HMAC
getOrderItemsGETConsulta ítems de un pedido por OrderId
productStockUpdatePOSTActualiza stock de producto (body XML, generado vía TheIconicUtils.jaxbObjectToXML)
getProductStocksGETConsulta stock de todos los productos
setStatusToReadyToShipGETMarca ítems de pedido como listos para envío
setStatusToShipGETMarca un ítem de pedido como enviado

Todas las operaciones de TheIconicClient requieren que el consumidor calcule manualmente Signature (HMAC, vía TheIconicUtils.hmacDigest) y Timestamp, y las pase como parámetros de query — no hay ningún interceptor que automatice esta firma.

Ejemplo de payload putStockProduct (ProductStockRequest, API v2):

[
{ "productId": 12345, "quantity": 10 }
]

Protocolo: HTTPS REST (JSON en la API v2; XML/query-string firmado con HMAC en la API v1 legacy). Autenticación: OAuth2 client credentials (Bearer token) en la API v2, sin caché (ver sección 13); firma HMAC manual por petición en la API v1 legacy.

7. Configuración

No se incluye ningún application.properties/application.yml en la librería (confirmado en CLAUDE.md). Las propiedades deben ser inyectadas por la aplicación consumidora.

Propiedades requeridas (prefijo theiconic.api, API v2)

PropiedadDescripciónEjemplo de valor
theiconic.api.urlURL base de la API de The Iconic (activa la autoconfiguración)${THEICONIC_API_URL}
theiconic.api.grantTypeGrant type OAuth2 (típicamente client_credentials)client_credentials
theiconic.api.clientIdClient ID de la integración${THEICONIC_CLIENT_ID}
theiconic.api.clientSecretClient secret de la integración${THEICONIC_CLIENT_SECRET}

Importante: Si theiconic.api.url no está definida, ninguno de los dos beans v2 se registra (condición @ConditionalOnProperty). Las credenciales de firma HMAC de la API v1 legacy (TheIconicClient) no se configuran mediante propiedades Spring, ya que dicha interfaz no tiene autoconfiguración.

Variables de entorno recomendadas

VariablePropiedad mapeada
THEICONIC_API_URLtheiconic.api.url
THEICONIC_CLIENT_IDtheiconic.api.clientId
THEICONIC_CLIENT_SECRETtheiconic.api.clientSecret

8. Persistencia

No aplica a este proyecto. La librería no accede a ninguna base de datos. CacheStore/CacheStoreBeans exponen un bean de caché de token (TTL 1 hora) que, sin embargo, no es utilizado por la autoconfiguración activa (ver sección 13) — en la práctica no hay ningún estado cacheado en memoria en el flujo real de autenticación.

9. Procesos programados y mensajería

No aplica a este proyecto. No existen jobs @Scheduled, listeners de colas/topics ni runners batch.

10. Ejecución en local

theiconic-client es una librería JAR, no una aplicación ejecutable. No tiene servidor embebido ni endpoint de health.

Requisitos previos

  • Java 25
  • Maven 3.x
  • Acceso al registro de artefactos Maven interno (europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven) para resolver/publicar dependencias.

Compilar e instalar en repositorio local

# Compilar sin tests
./mvnw clean install -DskipTests

# Compilar con tests
./mvnw clean install

# Empaquetar
./mvnw package -DskipTests

Uso como dependencia en un microservicio consumidor

<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>theiconic-client</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>

La autoconfiguración activa (TheIconicAutoConfiguration) se activa automáticamente al declarar theiconic.api.url (y las credenciales OAuth2) en la aplicación consumidora. Cualquier uso de TheIconicClient (API v1 legacy) debe evitarse en código nuevo, según indica su anotación @Deprecated.

11. Despliegue

El pipeline de Jenkins (Jenkinsfile) consta de dos etapas:

  1. Checkout — descarga el código del repositorio.
  2. Publish to Artifact Registry — ejecuta mvn deploy -DskipTests para publicar el JAR en Google Artifact Registry.
ParámetroValor
JDKJDK25 (tool Jenkins)
MavenMaven3 (tool Jenkins)
Repositorioeurope-west3-maven.pkg.dev/pi-saldum/pi-repo-maven (Artifact Registry GCP)

No existe Dockerfile ni despliegue como servicio independiente; el artefacto es un JAR publicado en el registro Maven.

Job de Jenkins:

https://jenkins-pi.hawkersco.net/job/theiconic-client/

12. Manejo de errores y logging

Los métodos de TheIconicRestClient y TheIconicClient no declaran throws explícito; las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor. En el requestInterceptor de theIconicRestClient, si la respuesta de token no es 2xx o no tiene body, el interceptor deja token como cadena vacía ("") e igualmente inyecta Authorization: Bearer — el fallo se manifestará como un error HTTP del lado de The Iconic (probablemente 401), no como un fallo explícito en la obtención del token. TheIconicUtils usa java.util.logging.Logger internamente para registrar fallos de firma HMAC/marshalling XML, distinto del resto de la librería, que no registra logs. No hay configuración de logback específica.

13. Notas y consideraciones

  • Sin caché de token en el flujo activo (v2): A diferencia de la mayoría de clientes del ecosistema, el requestInterceptor de theIconicRestClient en TheIconicAutoConfiguration solicita un token OAuth2 nuevo en cada llamada de negocio, sin consultar ninguna caché — pese a que existe un bean CacheStore<String> con TTL de 1 hora expuesto por CacheStoreBeans precisamente para este propósito (según su Javadoc: "Provides a CacheStore for OAuth2 access tokens"). El resultado es una petición HTTP adicional de autenticación en cada operación de negocio contra The Iconic, con el consiguiente impacto en latencia y en la cuota de peticiones de autenticación de la API. Esto es una regresión de rendimiento significativa respecto al patrón habitual del ecosistema (auro-client, meli-client, privalia-client, etc., todos con caché de token activa).

  • Cliente v1 (TheIconicClient) deprecado pero sin autoconfiguración: La interfaz está marcada @Deprecated y no tiene ningún bean asociado (TheIconicClientConfig es una clase @Configuration vacía, con un comentario explícito: "Legacy config for deprecated TheIconicClient — no longer contains Feign beans"). Cualquier consumidor que necesite usarla debe instanciarla o registrarla manualmente; no está pensada para uso vía inyección de dependencias estándar de esta librería.

  • Mezcla de anotaciones Spring MVC en una interfaz sin autoconfiguración: TheIconicClient usa @GetMapping/@PostMapping (anotaciones típicamente asociadas a controladores REST, no a clientes @HttpExchange), heredadas de una configuración previa con Feign (@FeignClient comentado). Sin un @HttpExchange/HttpServiceProxyFactory que la respalde, esta interfaz no puede usarse directamente como cliente declarativo sin una infraestructura adicional no presente en el código actual.

  • Firma HMAC completamente manual en la API v1: El consumidor de TheIconicClient debe calcular Signature y Timestamp invocando manualmente TheIconicUtils.hmacDigest/getTimestamp/getCurrentTimestamp antes de cada llamada — no hay ningún interceptor que automatice este proceso, a diferencia de otros esquemas de firma del ecosistema (p. ej. pim-client).

  • @ConditionalOnMissingBean en ambos beans v2: A diferencia de la mayoría de autoconfiguraciones del ecosistema, aquí se permite explícitamente que un consumidor sobrescriba TheIconicTokenRestClient/TheIconicRestClient definiendo sus propios beans con el mismo tipo.

  • Sin tests implementados: Confirmado en CLAUDE.md: el directorio src/test/java/ está vacío.

  • TheIconicClientApplication.java: Clase principal de Spring Boot en el paquete raíz, sin funcionalidad operativa. Artefacto residual de la generación inicial del proyecto con Spring Initializr, mismo patrón observado en otros clientes del ecosistema.