Feeds Commons
1. Descripción general
feeds-commons es una librería compartida (JAR) del ecosistema de microservicios de Hawkers que centraliza el acceso a la base de datos PostgreSQL de feeds. Expone entidades JPA, repositorios Spring Data y servicios que los servicios consumidores inyectan directamente en su contexto de Spring.
El objetivo es evitar la duplicación de queries y lógica de acceso a datos entre los distintos microservicios que trabajan con feeds de productos, columnas protegidas y redirecciones cortas (HawkeRs). No contiene capa REST, punto de entrada principal ni fichero de configuración propio — la conexión a base de datos la provee siempre el servicio consumidor.
2. Información técnica
| Propiedad | Valor |
|---|---|
artifactId | feeds-commons |
groupId | com.hawkersco |
version | 1.0.25-SNAPSHOT |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo artefacto | JAR (librería, sin main) |
| Módulos | Proyecto simple (mono-módulo) |
| Repositorio | GCP Artifact Registry (europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven) |
3. Arquitectura y diseño
La librería sigue una estructura de tres capas estrictamente separadas bajo el paquete base com.hawkersco.feedscommons:
com.hawkersco.feedscommons
├── dao/ → Entidades JPA + clases @IdClass de clave compuesta
├── repository/ → Interfaces Spring Data CrudRepository
└── service/ → Beans @Service que delegan en los repositorios
No existe capa controller, configuración propia ni punto de entrada. El consumidor importa la dependencia Maven y los beans se registran automáticamente en su contexto de Spring gracias al component-scan estándar de Spring Boot.
graph TD
CS[Servicio consumidor] -->|@Autowired| SVC[Service Bean]
SVC --> REPO[Repository Interface]
REPO -->|Spring Data JPA / Hibernate 7| DB[(PostgreSQL)]
Cada entidad utiliza @IdClass (no @EmbeddedId) para gestionar claves primarias compuestas y cumple Serializable tal y como exige la especificación JPA.
4. Dependencias principales
| Dependencia | Versión | Propósito |
|---|---|---|
spring-boot-starter | gestionada por BOM 4.0.6 | Autoconfiguración base de Spring Boot |
spring-boot-starter-data-jpa | gestionada por BOM 4.0.6 | Spring Data JPA + Hibernate 7.x como proveedor ORM |
org.postgresql:postgresql | 42.7.11 | Driver JDBC para PostgreSQL |
org.projectlombok:lombok | 1.18.46 | Generación de getters/setters/constructores en tiempo de compilación |
spring-boot-starter-test | gestionada por BOM 4.0.6 | Scope test — para los servicios consumidores |
artifactregistry-maven-wagon | 2.2.1 | Extensión Maven para publicar en GCP Artifact Registry |
5. API / Endpoints
No aplica a este proyecto.
Esta librería no expone ningún endpoint REST. Es un artefacto de tipo commons pensado para ser importado como dependencia Maven.
6. Integraciones externas
No aplica a este proyecto.
La única integración es con la base de datos PostgreSQL, que es responsabilidad del servicio consumidor configurar. No hay llamadas a APIs externas, colas de mensajería ni otros sistemas.
7. Configuración
Esta librería no incluye application.yml ni application.properties. El servicio consumidor debe proveer la configuración de datasource en su propio fichero de propiedades:
| Propiedad | Descripción | Ejemplo de valor |
|---|---|---|
spring.datasource.url | URL JDBC de la base de datos PostgreSQL | jdbc:postgresql://host:5432/feeds_db |
spring.datasource.username | Usuario de la base de datos | ${DB_USER} |
spring.datasource.password | Contraseña de la base de datos | ${DB_PASSWORD} |
spring.jpa.hibernate.ddl-auto | Estrategia DDL de Hibernate | validate o none |
spring.jpa.show-sql | Log de queries SQL (solo desarrollo) | false |
Sin estas propiedades el contexto de Spring del consumidor fallará al arrancar.
8. Persistencia
Base de datos: PostgreSQL (driver 42.7.11).
Entidades y tablas
| Entidad | Tabla | Campos clave (@IdClass) | Otros campos |
|---|---|---|---|
FieldFeed | field_feed | countryIso, site, fieldTitle | fieldValue, sku |
HawkeRsRedirection | hawke_rs_redirection | code, site | shortUrl, url |
ProtectedColumn | protected_column | site, countryIso, fieldTitle | — |
Nota:
FieldFeedIddeclaraskucomo parte de la clase de clave compuesta, pero en la entidadFieldFeedel camposkuno está anotado con@Id. Ver sección 13.
Todas las entidades implementan Serializable y usan anotaciones jakarta.persistence.* (Jakarta EE 10+).
No existen migraciones Flyway ni Liquibase en esta librería. El esquema se asume preexistente en la base de datos del consumidor.
API de repositorios
FieldFeedRepository
List<FieldFeed> findBySiteAndCountryIsoOrderBySku(String site, String countryIso);
HawkeRsRedirectionRepository
HawkeRsRedirection findTop1ByCodeAndSite(String code, String site);
ProtectedColumnRepository
List<ProtectedColumn> findBySiteOrderByCountryIso(String site);
List<ProtectedColumn> findBySiteAndCountryIsoOrderByCountryIso(String site, String countryIso);
List<ProtectedColumn> findBySiteAndCountryIsoOrderByFieldTitle(String site, String countryIso);
API de servicios
Los servicios son finas capas de delegación sobre los repositorios:
FieldFeedService
| Método | Descripción |
|---|---|
save(FieldFeed) | Persiste o actualiza un registro field_feed |
delete(FieldFeed) | Elimina un registro field_feed |
findBySiteAndCountryIsoOrderBySku(site, countryIso) | Devuelve todos los feeds de un sitio y país, ordenados por SKU |
HawkeRsRedirectionService
| Método | Descripción |
|---|---|
findTop1ByCodeAndSite(code, site) | Devuelve la primera redirección que coincide con el código corto y el sitio |
ProtectedColumnService
| Método | Descripción |
|---|---|
save(ProtectedColumn) | Persiste o actualiza una columna protegida |
findBySiteOrderByCountryIso(site) | Devuelve todas las columnas protegidas de un sitio, ordenadas por país |
findBySiteAndCountryIsoOrderByCountryIso(site, countryIso) | Filtra por sitio y país, ordena por país |
findBySiteAndCountryIsoOrderByFieldTitle(site, countryIso) | Filtra por sitio y país, ordena por título de campo |
9. Procesos programados y mensajería
No aplica a este proyecto.
No hay jobs @Scheduled, listeners de Kafka/RabbitMQ ni runners batch.
10. Ejecución en local
Esta librería no es un servicio ejecutable. No tiene main ni servidor embebido.
Para compilar e instalar en el repositorio local Maven:
./mvnw clean install -DskipTests
Para compilar con tests (requiere PostgreSQL accesible con las propiedades de datasource configuradas):
./mvnw clean install
Para publicar en GCP Artifact Registry (requiere credenciales GCP configuradas):
mvn deploy -DskipTests
Para consumir la librería desde otro proyecto, añadir al pom.xml del consumidor:
<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>feeds-commons</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>
11. Despliegue
El pipeline de CI/CD está definido en el Jenkinsfile del repositorio. Utiliza el agente any con las herramientas JDK25 y Maven3 configuradas en Jenkins.
Etapas del pipeline:
| Etapa | Descripción |
|---|---|
Checkout | Descarga el código fuente del repositorio |
Publish to Artifact Registry | Ejecuta mvn deploy -DskipTests y publica el JAR en GCP Artifact Registry |
El artefacto se publica en:
artifactregistry://europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven
Job de Jenkins:
https://jenkins-pi.hawkersco.net/job/feeds-commons/
12. Manejo de errores y logging
No hay gestión de excepciones propia ni configuración de logging en esta librería. Los errores JPA/JDBC (entidad no encontrada, violación de constraint, problema de conexión) se propagan como excepciones estándar de Spring Data (DataAccessException y subtipos) al servicio consumidor, que es el responsable de capturarlas y gestionarlas.
El logging de queries SQL puede activarse en el consumidor mediante spring.jpa.show-sql=true.
13. Notas y consideraciones
-
Inconsistencia en
FieldFeedId: La clase de clave compuestaFieldFeedIddeclara cuatro campos:countryIso,site,fieldTitleysku. Sin embargo, en la entidadFieldFeedsolocountryIso,siteyfieldTitleestán anotados con@Id;skuno lo está. Esto es técnicamente inconsistente según la especificación JPA para@IdClassy puede provocar comportamiento inesperado en Hibernate al calcular la identidad de la entidad. Pendiente de revisar siskudebe formar parte de la PK o eliminarse deFieldFeedId. -
Uso de
@Autowireden lugar de inyección por constructor: Los servicios usan@Autowiredsobre campo, patrón desaconsejado desde Spring 4.x en favor de inyección por constructor (mejor testabilidad y detección temprana de dependencias circulares). -
Sin tests propios: La librería no contiene ningún test. La dependencia
spring-boot-starter-testestá declarada en scopetestpensando en los consumidores, no en esta librería. Sería recomendable añadir tests de integración con una base de datos embebida (H2 en modo PostgreSQL o Testcontainers). -
HawkeRsRedirectionRepository.findTop1ByCodeAndSiteretornanull: El método puede devolvernullen lugar deOptional<HawkeRsRedirection>. Los consumidores deben comprobarlo explícitamente para evitarNullPointerException.