Skip to main content

xml-to-xlsx-converter

1. Descripción general

Según el pom.xml, el proyecto se describe como "Xls to xlsx converter". Es un microservicio batch (runner) que descarga por SFTP los ficheros de movimientos pendientes del proveedor logístico Auro (en formato XLS o XML), los convierte a XLSX, sube el resultado a una carpeta de intercambio en el mismo servidor SFTP, archiva los ficheros originales y limpia la carpeta de pendientes.

2. Información técnica

CampoValor
artifactIdxml-to-xlsx-converter
groupIdcom.hawkersco
version1.0.25
Java25
Spring Boot4.0.6
Tipo de artefactojar (ejecutable, Spring Boot batch/CLI)
MódulosNo aplica (proyecto de módulo único)

3. Arquitectura y diseño

No es una API REST: es una aplicación Spring Boot CLI con un único CommandLineRunner (XlsToXlsxConverterRunner). Toda la lógica de procesamiento vive en métodos estáticos de utilidad, no en beans de Spring.

  • .configSftpProperties (@ConfigurationProperties, conexión y rutas SFTP).
  • .modelXLSModel (POJO de fila de datos, 9 campos: FECHA_MOVIMIENTO, COD_ARTICULO, DOCUMENTO, etc.).
  • .utilSftpUtil (operaciones SFTP vía JSch), XmlUtil (parseo de XLS/XLSX/XML a List<XLSModel> con Apache POI, soportando tanto HSSF como XSSF), WriteToExcelUtil (escritura de XLSX con cabecera naranja en Arial 16pt negrita), ToolsUtil (gestión de carpetas locales).
flowchart TD
A[XlsToXlsxConverterRunner] -->|conecta| B[SFTP sftp.hawkersco.com]
A -->|descarga XLS/XML| C[/src/AURO/MOVS/PENDIENTE/]
A -->|parsea con Apache POI| D[XLSModel]
D -->|escribe XLSX| E[xlsxFiles local]
A -->|sube XML original| F[/src/AURO/MOVS/HISTORICO/]
A -->|sube XLSX| G[/src/AURO/MOVS/XLSX/]
A -->|borra tras subir| C

Flujo: crea las carpetas de trabajo locales (xmlFiles/, xlsxFiles/), abre sesión SFTP y, si se conecta correctamente, ejecuta 3 pasos: (1) descarga todos los ficheros de /src/AURO/MOVS/PENDIENTE a xmlFiles/ local y, por cada fichero XLS/XML descargado, lo parsea a una lista de XLSModel y lo escribe como XLSX en xlsxFiles/; (2) sube en una única operación tanto los XML originales a /src/AURO/MOVS/HISTORICO como los XLSX generados a /src/AURO/MOVS/XLSX; (3) borra de /src/AURO/MOVS/PENDIENTE los ficheros ya procesados. Un fallo al parsear un fichero individual se registra y no interrumpe el resto del lote.

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot (sin web, es un runner CLI)
org.apache.poi:poi / poi-ooxmlLectura/escritura de Excel, formatos HSSF (.xls) y XSSF (.xlsx)
com.jcraft:jschConectividad SFTP
Lombok (@Data, @Slf4j)Generación de código boilerplate

5. API / Endpoints

No aplica a este proyecto. Es un batch/runner sin capa REST.

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
Servidor SFTP (sftp.hawkersco.com, usuario conc-mov-auro)SFTP (JSch)Entrante/SalienteDescarga de ficheros pendientes de Auro, subida de XML archivado y XLSX generado, borrado de pendientes procesados

7. Configuración

En producción (application-pro.properties) las credenciales de conexión llegan por variables de entorno inyectadas como Secret de Kubernetes; en local (application.properties) el repositorio contiene actualmente valores reales hardcodeados (ver alerta de seguridad).

ClaveDescripción
sftp.host / .port / .username / .passwordConexión al servidor SFTP
sftp.knownhostspatchRuta al fichero known_hosts para verificación de host SSH (ver hallazgo en la sección 13: actualmente apunta a una ruta remota, no a un fichero local)
sftp.path-pendiente / .path-historico / .path-xlsxRutas remotas de pendientes, histórico y XLSX generado

⚠️ Alerta de seguridad

El fichero src/main/resources/application.properties (perfil local) contiene actualmente la contraseña real en texto plano del usuario SFTP conc-mov-auro. No se ha reproducido en este documento. Se recomienda:

  1. Rotar la contraseña del usuario SFTP.
  2. Sustituir el valor hardcodeado de application.properties por credenciales de un entorno de desarrollo aislado.
  3. Revisar el historial de control de versiones, ya que esta credencial puede seguir expuesta en commits anteriores.

8. Persistencia

No aplica a este proyecto. No usa base de datos: el estado se gestiona íntegramente mediante las carpetas del servidor SFTP (PENDIENTEHISTORICO/XLSX) y carpetas de trabajo locales temporales.

9. Procesos programados y mensajería

No hay @Scheduled ni listeners de colas: la periodicidad la impone el CronJob de Kubernetes (k8s/cronjob.yaml), que ejecuta el contenedor una vez al día a las 15:00 (schedule: "0 15 * * *", concurrencyPolicy: Forbid). Único runner, descrito en la sección 3.

10. Ejecución en local

Requisitos previos: JDK 25, Maven, credenciales válidas del servidor SFTP.

# Compilar
mvn clean package

# Ejecutar tests
mvn test

# Ejecutar un test concreto
mvn test -Dtest=ClassName

# Ejecutar la aplicación localmente
mvn spring-boot:run

# Build Docker
docker build -t xml-to-xlsx-converter .
docker run xml-to-xlsx-converter

Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el contenido de las carpetas HISTORICO/XLSX en el servidor SFTP.

11. Despliegue

  • Imagen: construida con jib-maven-plugin (base eclipse-temurin:25-jre, containerizingMode=packaged), publicada en europe-west3-docker.pkg.dev/pi-saldum/pi-repo/xml-to-xlsx-converter:<tag>.
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw, namespace pi, contenedor no privilegiado, ejecutándose diariamente a las 15:00.
  • CI/CD (Jenkins): pipeline de 3 etapas — CheckoutBuild & Push (sustituye application-pro.properties por application.properties, mvn clean package jib:build) → Deploy to GKE.

Job de Jenkins: https://jenkins-pi.hawkersco.net/job/xml-to-xlsx-converter/

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). El parseo de cada fichero individual se envuelve en su propio try/catch de IOException, registrando el error y continuando con el resto del lote. Los métodos de subida/borrado por SFTP capturan SftpException por fichero dentro de sus bucles internos, sin interrumpir el resto de la operación. Logging vía Lombok @Slf4j.

13. Notas y consideraciones

  • sftp.knownhostspatch apunta a una ruta remota, no a un fichero local: en ambos perfiles (application.properties y application-pro.properties) esta propiedad tiene el mismo valor que sftp.path-pendiente (/src/AURO/MOVS/PENDIENTE), pero se usa en SftpUtil.getSessionSFTP como argumento de JSch.setKnownHosts(knownPath), que espera la ruta de un fichero known_hosts en el sistema de ficheros local. Es casi con toda seguridad un resto de copia/pegado sin corregir. En la práctica no tiene efecto observable porque StrictHostKeyChecking ya está fijado a "no" en el propio código, deshabilitando la verificación de host sea cual sea el valor de esta propiedad — pero conviene corregirla antes de que alguien reactive la verificación estricta de host, momento en el que este valor erróneo causaría un fallo de conexión.
  • Mensaje de log del paso 3 potencialmente confuso: el runner registra "3.- Moving files xml from PENDIENTE to HISTORICO" justo antes de llamar a deleteFilesFromSFTP, pero el traslado real a HISTORICO ya ocurrió en el paso 2 (transferFileToSftp); el paso 3 solo borra los ficheros ya procesados de PENDIENTE. El mensaje de log no describe con precisión la operación que realiza, lo que puede confundir a quien diagnostique un incidente a partir de los logs.
  • CLAUDE.md verificado y consistente en el resto de aspectos: el flujo de 7 pasos, las clases clave y las dependencias (Apache POI, JSch) coinciden con el código real, verificado directamente en XlsToXlsxConverterRunner y SftpUtil.
  • Ver alerta de seguridad en la sección 7 sobre la contraseña SFTP expuesta en application.properties.