Servientrega Client
1. Descripción general
servientrega-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con el servicio web SOAP de Servientrega, transportista logístico colombiano 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 validar/enviar salidas (pedidos de envío) y consultar su tracking en el sistema de Servientrega.
El host remoto (wms.servientrega.com) requiere una configuración TLS especial: la librería desactiva la validación de certificados para las peticiones que realiza, ver detalle y consideración de seguridad en la sección 13.
2. Información técnica
| Propiedad | Valor |
|---|---|
artifactId | servientrega-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.servientregaclient
├── ServientregaClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ └── ServientregaSoapClient.java # Interfaz @HttpExchange: sendOrder, trackingSalidas
├── config/
│ ├── ServientregaAutoConfiguration.java # @AutoConfiguration principal (SSL trust-all + resolver de ParamsForm)
│ ├── ParamsFormArgumentResolver.java # HttpServiceArgumentResolver que expande ParamsForm en query params planos
│ ├── NaiveSSLSocketFactory.java # Utilidad SSL heredada, no instanciada por la autoconfiguración actual (ver sección 13)
│ ├── NaiveHostnameVerifier.java # Utilidad heredada, no instanciada por la autoconfiguración actual (ver sección 13)
│ └── ServientregaSoapConfig.java # Clase vacía, retenida solo por compatibilidad (comentario explícito en el código)
└── entity/
├── ParamsForm.java # Parámetros de autenticación/config enviados como query params
├── Salidas.java # Envelope SOAP de request para validarSalidas
└── SalidasResponse.java # Envelope SOAP de response para validarSalidas
Flujo principal
sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Resolver as ParamsFormArgumentResolver
participant Client as ServientregaSoapClient
participant API as wms.servientrega.com
Consumidor->>Client: sendOrder(xmlSalidas, paramsForm) / trackingSalidas(xmlTracking, paramsForm)
Client->>Resolver: expande ParamsForm en params.login, params.use, params.password, ...
Client->>API: POST /suite/webservices/salidas.php | trackingsalidas.php (query params + XML body, TLS sin validar certificado)
API-->>Client: ResponseEntity<String> (XML crudo)
Client-->>Consumidor: ResponseEntity<String>
La autoconfiguración (ServientregaAutoConfiguration) se activa condicionalmente con @ConditionalOnProperty(prefix = "logisticco.servientrega.client", name = "url"), registrando el bean ServientregaSoapClient con:
- Un
RestClientcuyarequestFactoryes unJdkClientHttpRequestFactoryconstruido con unSSLContextque confía en cualquier certificado (X509TrustManagersin validación) y con verificación de hostname desactivada (SSLParameters.setEndpointIdentificationAlgorithm("")). - Un
customArgumentResolver(ParamsFormArgumentResolver) que, al recibir un parámetroParamsFormen un método@HttpExchange, lo expande en los query params planosparams.login,params.use,params.password,params.style,params.uriyparams.location— replicando el comportamiento que antes ofrecía Spring Cloud OpenFeign al anotar un POJO con@RequestParam.
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
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 / HttpServiceArgumentResolver |
jakarta.xml.bind:jakarta.xml.bind-api | 4.0.1 | Anotaciones JAXB para el mapeo XML/SOAP de Salidas/SalidasResponse |
org.projectlombok:lombok | 1.18.46 | Generación de boilerplate en los modelos (getters, setters, constructores) |
spring-boot-starter-test | (gestionada SB4) | Testing (scope test) |
5. API / Endpoints
No aplica a este proyecto. servientrega-client es una librería cliente JAR que no expone endpoints REST propios. Las operaciones SOAP que encapsula se detallan en la sección 6.
6. Integraciones externas
Servicio web SOAP de Servientrega (wms.servientrega.com)
| Método cliente | HTTP | Ruta remota | Descripción |
|---|---|---|---|
sendOrder | POST | /suite/webservices/salidas.php | Valida y envía una salida (pedido de envío) — operación SOAP validarSalidas |
trackingSalidas | POST | /suite/webservices/trackingsalidas.php | Consulta el tracking de salidas existentes |
Ambos métodos reciben el cuerpo XML SOAP completo como String (@RequestBody, construido por el consumidor a partir de los POJOs JAXB Salidas) y un objeto ParamsForm que se expande automáticamente en query params de autenticación (params.login, params.use, params.password, params.style, params.uri, params.location).
Ejemplo de estructura del envelope SOAP para sendOrder (simplificado, a partir de Salidas):
<soapenv:Envelope xmlns:soapenv="..." xmlns:sal="...">
<soapenv:Header/>
<soapenv:Body>
<sal:validarSalidas>
<arreglo_salidas>
<punto>1</punto>
<salida>ORD-000123</salida>
<identificacion>1234567890</identificacion>
<nombre>Cliente</nombre>
<apellido>Final</apellido>
<direccion>Calle Ejemplo 1</direccion>
<ciudad>Bogotá</ciudad>
<pais>CO</pais>
<detalles>
<secuencia>1</secuencia>
<articulo>SKU-001</articulo>
<cantidad>2</cantidad>
<valor_base>19.99</valor_base>
</detalles>
</arreglo_salidas>
</sal:validarSalidas>
</soapenv:Body>
</soapenv:Envelope>
Ejemplo de estructura de respuesta (SalidasResponse):
<Envelope>
<Body>
<validarSalidasResponse>
<arreglo_respuestas>
<punto>1</punto>
<salida>ORD-000123</salida>
<estado>OK</estado>
<mensaje>Salida registrada correctamente</mensaje>
</arreglo_respuestas>
</validarSalidasResponse>
</Body>
</Envelope>
trackingSalidas no dispone de un POJO JAXB de respuesta propio en este proyecto: devuelve ResponseEntity<String> con el XML crudo.
Protocolo: SOAP sobre HTTPS (text/xml;charset=UTF-8), con validación de certificado TLS desactivada para el host de Servientrega. Autenticación: credenciales (login, password) enviadas como query params planos derivados de ParamsForm.
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
| Propiedad | Descripción | Ejemplo de valor |
|---|---|---|
logisticco.servientrega.client.url | URL base del servicio SOAP Servientrega (activa la autoconfiguración) | ${SERVIENTREGA_CLIENT_URL} |
Las credenciales (login, password, use, style, uri, location) no se configuran como propiedades Spring: el consumidor debe construir un objeto ParamsForm con estos valores y pasarlo en cada llamada.
Variables de entorno recomendadas
| Variable | Propiedad mapeada |
|---|---|
SERVIENTREGA_CLIENT_URL | logisticco.servientrega.client.url |
Importante: Si
logisticco.servientrega.client.urlno está definida, el beanServientregaSoapClientno se registra (condición@ConditionalOnProperty).
Logging detallado
Para obtener el equivalente al nivel FULL de logging que ofrecía la antigua integración con OpenFeign, CLAUDE.md recomienda:
logging.level.org.springframework.web.client.RestClient=DEBUG
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
servientrega-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 e instalar
./mvnw clean install
# Compilar sin tests (como en CI)
./mvnw -B -DskipTests clean install
# Ejecutar tests
./mvnw test
Uso como dependencia en un microservicio consumidor
<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>servientrega-client</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>
La autoconfiguración se activa automáticamente al declarar logisticco.servientrega.client.url en la aplicación consumidora; ya no es necesario @EnableFeignClients.
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.
CLAUDE.md menciona que el build se ejecuta vía jenkins/scripts/mvn.sh, script no presente en este repositorio ni referenciado directamente en el Jenkinsfile actual. Se documenta el Jenkinsfile realmente presente.
| 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/servientrega-client/
12. Manejo de errores y logging
La librería no implementa ninguna estrategia propia de manejo de excepciones ni logging estructurado más allá de la recomendación de habilitar DEBUG sobre RestClient para depuración (ver sección 7). Las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor, ya que ningún método de ServientregaSoapClient declara throws explícito.
13. Notas y consideraciones
-
Validación de certificado TLS desactivada para todo el cliente:
ServientregaAutoConfigurationconstruye unSSLContextque confía en cualquier certificado y desactiva la verificación de hostname (setEndpointIdentificationAlgorithm("")) para todas las peticiones delRestClient(no solo para un host concreto). Dado que labaseUrlde este cliente está siempre fijada al host de Servientrega víalogisticco.servientrega.client.url, el efecto práctico queda acotado a ese host, pero expone al consumidor a riesgo de man-in-the-middle si dicha URL apuntase alguna vez a un host distinto o si el tráfico se intercepta en la red. El comentario del propio código indica que esto reproduce intencionalmente el comportamiento previo con Feign, sugiriendo que el certificado dewms.servientrega.comes autofirmado o está mal configurado en origen. -
NaiveSSLSocketFactoryyNaiveHostnameVerifierno están en uso: Ambas clases implementan un enfoque más granular (confiar únicamente en hostnames concretos pasados por parámetro, delegando el resto al comportamiento por defecto de la JVM), pero no son instanciadas porServientregaAutoConfiguration, que en su lugar construye su propioSSLContext/SSLParametersinline con un alcance más amplio (todo elRestClient, no por hostname). Son código retenido de la integración anterior con Feign, documentado como tal en el propio código, y podrían eliminarse sin impacto si se confirma que ningún otro componente las usa. -
ServientregaSoapConfigcomo stub vacío documentado: La clase está vacía y su Javadoc indica explícitamente que se retiene solo por compatibilidad hacia atrás, con la configuración real ahora enServientregaAutoConfiguration— mismo patrón de placeholder "muerto pero documentado" observado enprivalia-marketplace-client. -
trackingSalidassin modelo de respuesta tipado: A diferencia desendOrder(que tieneSalidasResponse), la operación de tracking no cuenta con ningún POJO JAXB de respuesta en este proyecto — el consumidor recibe el XML crudo y debe parsearlo por su cuenta. -
Expansión de
ParamsFormacoplada a nombres de campo fijos:ParamsFormArgumentResolverconstruye los nombres de query param (params.login,params.use, etc.) de forma manual y explícita por cada campo deParamsForm.Params— cualquier campo nuevo que se añada aParamsrequeriría actualizar también el resolver, ya que no hay reflexión ni generación automática. -
Sin tests implementados: No se ha encontrado directorio
src/test/en el proyecto. -
ServientregaClientApplication.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.