Skip to main content

Showroom Client

1. Descripción general

showroom-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con el marketplace Showroom (Showroomprivé). El proyecto no expone ningún endpoint REST propio; se publica en el registro de artefactos Maven interno y es consumido por otros microservicios del ecosistema Hawkers que necesiten aceptar pedidos, consultar ofertas, actualizar tracking/envío e importar ficheros de stock en Showroom.

La librería implementa un patrón de cliente dual: dos beans (ShowroomClient y ShowroomFlashClient) que comparten exactamente el mismo contrato de operaciones (ShowroomOperations) pero se configuran con URL y API key independientes, para cubrir el canal estándar y el canal "Flash" (ventas flash) de Showroom respectivamente.

2. Información técnica

PropiedadValor
artifactIdshowroom-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.showroomclient
├── ShowroomClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ ├── ShowroomOperations.java # Interfaz @HttpExchange con las 7 operaciones de negocio (contrato común)
│ ├── ShowroomClient.java # Interfaz marcadora que extiende ShowroomOperations (canal estándar)
│ └── ShowroomFlashClient.java # Interfaz marcadora que extiende ShowroomOperations (canal Flash)
├── config/
│ ├── ShowroomConfig.java # @AutoConfiguration de ShowroomClient (prefijo showroom.credentials)
│ └── ShowroomFlashConfig.java # @AutoConfiguration de ShowroomFlashClient (prefijo showroom-flash.credentials)
├── request/
│ ├── AcceptOrderShowroomRequest.java # Aceptación/rechazo de líneas de pedido
│ └── TrackingShowroomRequest.java # Datos de transportista y número de seguimiento
└── response/
├── OrdersShowroomResponse.java # Respuesta de listado de pedidos
└── OffersShowroomResponse.java # Respuesta de listado de ofertas

Flujo principal (patrón dual)

sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Client as ShowroomClient / ShowroomFlashClient
participant API as API Showroom (estándar o Flash)

Consumidor->>Client: acceptOrder / getOrderList / updateTracking / importStockFile / ...
Client->>API: request + header Authorization: <apiKey>
API-->>Client: ResponseEntity<T>
Client-->>Consumidor: ResponseEntity<T>

ShowroomOperations define las siete operaciones de negocio como interfaz @HttpExchange; ShowroomClient y ShowroomFlashClient son interfaces vacías que únicamente extienden ShowroomOperations — este patrón de "interfaz marcadora" permite que HttpServiceProxyFactory genere dos beans Spring de tipo distinto (necesario para que Spring pueda diferenciarlos por tipo al inyectarlos) a partir del mismo contrato de métodos, evitando duplicar las anotaciones @HttpExchange en dos interfaces separadas.

ShowroomConfig (@ConditionalOnProperty sobre showroom.credentials.url/key) construye el RestClient de ShowroomClient con la cabecera Authorization fijada al valor de la API key. ShowroomFlashConfig (@ConditionalOnProperty sobre showroom-flash.credentials.url/key) hace lo mismo para ShowroomFlashClient, añadiendo además Content-Type: application/json como cabecera por defecto (diferencia menor respecto a ShowroomConfig, que no la fija).

El registro de ambas autoconfiguraciones se realiza mediante el fichero estándar de Spring Boot:

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

4. Dependencias principales

DependenciaVersiónPropósito
spring-boot-starter(gestionada SB4)Base de Spring Boot (contexto, autoconfiguración)
spring-web(gestionada SB4)RestClient + @HttpExchange / HttpServiceProxyFactory / soporte multipart
com.google.code.gson:gson2.14.0Anotaciones @SerializedName 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.46Generación de boilerplate en los modelos (@Data, getters, setters)
spring-boot-starter-test(gestionada SB4)Testing (scope test)

5. API / Endpoints

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

6. Integraciones externas

API de Showroom (ShowroomOperations, común a ambos canales)

MétodoHTTPRuta remotaDescripción
acceptOrderPUT/api/orders/{orderId}/acceptAcepta un pedido especificando qué líneas se aceptan
getOrderListWithStatusGET/api/orders?order_state_codes&start_date&max&offsetLista pedidos paginados filtrados por estado y fecha de inicio
getOrderListGET/api/orders?start_date&max&offsetLista pedidos paginados desde una fecha de inicio, sin filtro de estado
getOffersGET/api/offers?max&offsetLista ofertas paginadas
updateOffersPOST/api/offersActualiza ofertas mediante un payload JSON crudo
updateTrackingPUT/api/orders/{orderId}/trackingActualiza la información de tracking de un pedido
updateShipPUT/api/orders/{orderId}/shipMarca un pedido como enviado
importStockFilePOST/api/offers/stock/importsImporta niveles de stock desde un fichero (multipart)

Ejemplo de payload acceptOrder (AcceptOrderShowroomRequest):

{
"order_lines": [
{ "id": "ORDLINE-001", "accepted": true },
{ "id": "ORDLINE-002", "accepted": false }
]
}

Ejemplo de payload updateTracking (TrackingShowroomRequest):

{
"carrier_code": "DHL",
"carrier_name": "DHL Express",
"carrier_url": "https://dhl.example/tracking",
"tracking_number": "1234567890"
}

Protocolo: HTTPS REST (JSON; multipart/form-data para importStockFile). Autenticación: cabecera estática Authorization con la API key correspondiente a cada canal (estándar o Flash), sin flujo de token/refresh.

7. Configuración

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

Propiedades requeridas

PropiedadDescripciónEjemplo de valor
showroom.credentials.urlURL base del canal estándar de Showroom (activa ShowroomConfig)${SHOWROOM_URL}
showroom.credentials.keyAPI key del canal estándar (cabecera Authorization)${SHOWROOM_API_KEY}
showroom-flash.credentials.urlURL base del canal Flash de Showroom (activa ShowroomFlashConfig)${SHOWROOM_FLASH_URL}
showroom-flash.credentials.keyAPI key del canal Flash (cabecera Authorization)${SHOWROOM_FLASH_API_KEY}

Importante: Cada bean se activa de forma independiente; un consumidor puede usar solo el canal estándar, solo el Flash, o ambos, según qué pares url/key declare.

Variables de entorno recomendadas

VariablePropiedad mapeada
SHOWROOM_URLshowroom.credentials.url
SHOWROOM_API_KEYshowroom.credentials.key
SHOWROOM_FLASH_URLshowroom-flash.credentials.url
SHOWROOM_FLASH_API_KEYshowroom-flash.credentials.key

8. Persistencia

No aplica a este proyecto. La librería no accede a ninguna base de datos ni mantiene estado en memoria.

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

showroom-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 -B -DskipTests clean install

# Compilar con tests
./mvnw clean install

# Ejecutar tests
./mvnw test

Uso como dependencia en un microservicio consumidor

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

Cada uno de los dos beans (ShowroomClient/ShowroomFlashClient) se activa independientemente según las propiedades declaradas por el consumidor.

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.

CLAUDE.md documenta un pipeline de tres etapas (Build, SonarQube, Clean) vía scripts (jenkins/scripts/mvn.sh/clean.sh), que no se corresponde con el Jenkinsfile actual del repositorio (dos etapas: Checkout y Publish to Artifact Registry). Se documenta el Jenkinsfile realmente presente.

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/showroom-client/

12. Manejo de errores y logging

La librería no implementa ninguna estrategia propia de manejo de excepciones ni logging estructurado. Ningún método de ShowroomOperations declara throws explícito; las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor. No hay configuración de logback ni de niveles de log específicos en la librería.

13. Notas y consideraciones

  • Parámetro offersDecathlonResponse en updateOffers: El método updateOffers de ShowroomOperations recibe un parámetro llamado offersDecathlonResponse (@RequestBody String), un nombre que referencia claramente a Decathlon, no a Showroom — indicio de que este método fue copiado desde un cliente similar para Decathlon (decathlon-client) y el nombre del parámetro no se actualizó. No afecta al comportamiento (el nombre del parámetro no forma parte del contrato HTTP), pero es una inconsistencia de legibilidad a corregir.

  • importStockFile no documentado en CLAUDE.md: La tabla de operaciones de CLAUDE.md no incluye importStockFile (POST /api/offers/stock/imports, multipart), pese a estar presente en ShowroomOperations — documentación heredada incompleta respecto al código actual.

  • Patrón de interfaz marcadora (ShowroomClient/ShowroomFlashClient vacías): Ambas interfaces no añaden ningún método propio; existen únicamente para permitir que Spring registre dos beans de tipos distintos con el mismo conjunto de operaciones. Quien mantenga este código debe recordar que cualquier cambio de contrato se hace en ShowroomOperations, no en las interfaces concretas.

  • Diferencia menor entre ShowroomConfig y ShowroomFlashConfig: Solo ShowroomFlashConfig fija explícitamente Content-Type: application/json como cabecera por defecto del RestClient; ShowroomConfig no lo hace (aunque los métodos con @RequestBody que especifican contentType en su propia anotación no se ven afectados). Pendiente de verificar si esta asimetría es intencional o un descuido al escribir ShowroomFlashConfig a partir de ShowroomConfig.

  • @SuppressWarnings("unused") en AcceptOrderShowroomRequest: La anotación sugiere que en algún momento el compilador/IDE marcó campos como no utilizados (probablemente porque Lombok genera los accesores en tiempo de compilación y algunas herramientas de análisis estático no lo detectan) — no indica un problema funcional real.

  • Sin tests implementados: No se ha encontrado directorio src/test/ en el proyecto.

  • ShowroomClientApplication.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.