Logisfashion Client
1. Descripción general
logisfashion-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con la API de Logisfashion, proveedor logístico 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 importar pedidos de venta (sales orders) hacia el sistema de gestión de almacén de Logisfashion.
Expone una única operación: el envío de un pedido de venta (con dirección de entrega, líneas de producto, lotes y datos auxiliares) al endpoint de importación de Logisfashion.
2. Información técnica
| Propiedad | Valor |
|---|---|
artifactId | logisfashion-client |
groupId | com.hawkersco |
version | 1.0.25-SNAPSHOT |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo de artefacto | JAR (librería, no ejecutable) |
| Módulos | Proyecto único (no multi-módulo) |
3. Arquitectura y diseño
Estructura del proyecto:
com.hawkersco.logisfashionclient
├── LogisfashionClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ └── LogisfashionClient.java # Interfaz @HttpExchange con la operación de importación
├── config/
│ └── LogisfashionClientAutoConfiguration.java # @AutoConfiguration principal
└── pojo/
└── SalesOrders.java # POJO del payload completo de pedido de venta
Flujo principal
sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Client as LogisfashionClient
participant API as API Logisfashion
Consumidor->>Client: importSalesOrders(apiKey, jsonPedido)
Client->>API: POST /api/import/sales-orders + header X-LF-ApiKey
API-->>Client: ResponseEntity<String>
Client-->>Consumidor: ResponseEntity<String>
La autoconfiguración (LogisfashionClientAutoConfiguration) se activa condicionalmente con @ConditionalOnProperty(prefix = "logisfashion.api", name = "url"), registrando el bean LogisfashionClient con un RestClient simple (sin interceptores) apuntando a logisfashion.api.url.
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
A diferencia de otros clientes del ecosistema, la cabecera de autenticación (X-LF-ApiKey) no se inyecta en el RestClient de la autoconfiguración, sino que se declara como parámetro @RequestHeader del propio método importSalesOrders: es el servicio consumidor quien debe pasar el API key en cada llamada, en lugar de configurarlo una única vez.
4. Dependencias principales
| Dependencia | Versión | Propósito |
|---|---|---|
spring-boot-starter | (gestionada SB4) | Base de Spring Boot (contexto, autoconfiguración) |
spring-web | (gestionada SB4) | RestClient + @HttpExchange / HttpServiceProxyFactory |
org.projectlombok:lombok | 1.18.42 (fijada en dependencies; el annotationProcessorPath del compilador usa 1.18.46) | Generación de boilerplate en SalesOrders (getters, setters, constructores) |
spring-boot-starter-test | (gestionada SB4) | Testing (scope test) |
5. API / Endpoints
No aplica a este proyecto. logisfashion-client es una librería cliente JAR que no expone endpoints REST propios. La operación que encapsula sobre la API de Logisfashion se detalla en la sección 6.
6. Integraciones externas
API de Logisfashion (importación de pedidos)
| Método cliente | HTTP | Ruta remota | Dirección | Descripción |
|---|---|---|---|---|
importSalesOrders | POST | /api/import/sales-orders | Saliente | Importa un pedido de venta en el WMS de Logisfashion |
Firma del método:
ResponseEntity<String> importSalesOrders(
@RequestHeader("X-LF-ApiKey") String token,
@RequestBody String json);
El cuerpo se envía como String JSON crudo (no se pasa directamente una instancia de SalesOrders); el consumidor es responsable de serializar el POJO SalesOrders a JSON antes de invocar el método.
Ejemplo de payload (SalesOrders, resumido):
{
"deliveryId": "DEL-000123",
"purchaseOrder": "PO-000456",
"address": {
"code": "ADDR-001",
"name": "Almacén Central",
"address": "Calle Ejemplo 1",
"postalCode": "28001",
"city": "Madrid",
"countryIsoId": 724,
"countryIso": "ES",
"telephone1": "+34000000000",
"email": "almacen@hawkers.example",
"active": true
},
"expectedShipmentDate": "2026-07-15",
"expectedDeliveryDate": "2026-07-17",
"carrier": "GLS",
"shipMethod": "STANDARD",
"priority": "NORMAL",
"type": "SALE",
"lines": [
{
"lineNumber": 1,
"sku": "SKU-001",
"expectedQuantity": 10,
"batchArticle": { "batch": "LOTE-2026-07", "startDate": "2026-07-01", "endDate": "2027-07-01" }
}
]
}
Protocolo: HTTPS REST (JSON, contentType = application/json). Autenticación: cabecera X-LF-ApiKey, pasada explícitamente por el consumidor en cada llamada (no configurada de forma global en el RestClient).
7. Configuración
No se incluye ningún application.properties/application.yml en la librería (no existe fichero de propiedades en src/main/resources, salvo el registro de autoconfiguración). Las propiedades deben ser inyectadas por la aplicación consumidora.
Propiedades requeridas (prefijo logisfashion.api)
| Propiedad | Descripción | Ejemplo de valor |
|---|---|---|
logisfashion.api.url | URL base de la API de Logisfashion (activa la autoconfiguración) | ${LOGISFASHION_API_URL} |
El API key (X-LF-ApiKey) no se configura como propiedad Spring: debe ser gestionado y suministrado por el consumidor en cada invocación del método importSalesOrders.
Variables de entorno recomendadas
| Variable | Propiedad mapeada |
|---|---|
LOGISFASHION_API_URL | logisfashion.api.url |
Importante: Si
logisfashion.api.urlno está definida, el beanLogisfashionClientno se registra (condición@ConditionalOnProperty).
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
logisfashion-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
mvn -B -DskipTests clean install
# Compilar con tests
mvn clean install
# Ejecutar tests
mvn test
Uso como dependencia en un microservicio consumidor
<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>logisfashion-client</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>
La autoconfiguración se activa automáticamente al declarar logisfashion.api.url en la aplicación consumidora; el API key debe pasarse explícitamente en cada llamada a importSalesOrders.
11. Despliegue
El pipeline de Jenkins (Jenkinsfile) consta de dos etapas:
- Checkout — descarga el código del repositorio.
- Publish to Artifact Registry — ejecuta
mvn deploy -DskipTestspara publicar el JAR en Google Artifact Registry.
| Parámetro | Valor |
|---|---|
| JDK | JDK25 (tool Jenkins) |
| Maven | Maven3 (tool Jenkins) |
| Repositorio | europe-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/logisfashion-client/
12. Manejo de errores y logging
La librería no implementa ninguna estrategia propia de manejo de excepciones ni logging estructurado. Las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor, ya que importSalesOrders no declara ningún throws explícito. No hay configuración de logback ni de niveles de log específicos en la librería.
13. Notas y consideraciones
-
Versión de Lombok inconsistente: El
pom.xmlfija la dependenciaorg.projectlombok:lomboken la versión1.18.42, mientras que elannotationProcessorPathdelmaven-compiler-pluginusa1.18.46(la misma versión que el resto de clientes del ecosistema). Esta discrepancia de versiones podría causar comportamientos inconsistentes entre la anotación en tiempo de compilación y la dependencia en tiempo de ejecución. Pendiente de verificar si es intencional. -
Body como
Stringen lugar deSalesOrders: El métodoimportSalesOrdersrecibe el pedido ya serializado comoStringJSON en lugar de aceptar directamente una instancia deSalesOrders. Esto traslada la responsabilidad de serialización (y de mantener el JSON sincronizado con el POJO) al consumidor, a diferencia del patrón habitual en otros clientes del ecosistema donde el@RequestBodyes un objeto tipado. -
Autenticación por parámetro en cada llamada: A diferencia de otros clientes del ecosistema (
liverpool-client,justeat-client) que inyectan la cabecera de autenticación de forma estática en elRestClientvía autoconfiguración, aquí el API key (X-LF-ApiKey) se pasa como argumento explícito en cada invocación del método. Esto da más flexibilidad (posibilidad de usar distintas claves por llamada) pero traslada la gestión de la credencial completamente al consumidor. -
Sin manejo de excepciones declarado: A diferencia de otros clientes (
liverpool-client,justeat-client), el métodoimportSalesOrdersno declarathrows RestClientResponseException, aunque el comportamiento subyacente deRestClientes el mismo (la excepción no comprobada se propagará igualmente). -
SalesOrderscon campoDateen lugar de tipos modernos:BatchArticle.startDate/endDateusanjava.util.Dateen lugar dejava.time.LocalDate/LocalDateTime, inconsistente con el resto de POJOs del ecosistema que suelen usarLocalDate(p. ej.hk-timeslogistics-client) oStringpara fechas. -
Único test: carga de contexto:
LogisfashionClientApplicationTests.javacontiene únicamente el testcontextLoads()generado por defecto por Spring Initializr. No existe ninguna prueba real sobre el cliente ni sobre el POJOSalesOrders. -
LogisfashionClientApplication.java: Existe una 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.