Versión: 2.0
Fecha: 2026-05-11
Autor: Carlos Alberto Torres Camargo (arquitecto)
Documentos relacionados: ADR-002 División Libraries Nebula, Patrón Arquitectura Backend, Estándares de Desarrollo
Nebula define tres libraries compartidas en el grupo GitLab nebula/core/:
| Library | groupId:artifactId | Rol |
|---|---|---|
nebula-commons |
com.centrica.nebula:nebula-commons |
Utilidades, helpers, base classes, auto-configuraciones Spring, constantes internas |
nebula-models |
com.centrica.nebula:nebula-models |
DTOs, Records y Value Objects que viajan por la red entre microservicios |
nebula-shared |
com.centrica.nebula:nebula-shared |
Contratos de comunicación REST entre microservicios (interfaces @HttpExchange / Feign), excepciones y códigos de error transversales |
Cada microservicio Nebula consume estas libraries vía Maven (Nexus). La distribución es:
develop) → SNAPSHOT a Nexus automáticamente vía pipeline (libraryPipeline.groovy).main) → RELEASE a Nexus con gate manual.Las tres son ensambladas con mvn deploy -P centrica por la pipeline shared library, sin Docker, sin deploy a nodos.
Esta tabla es la fuente de verdad para decidir en qué repo colocar una clase nueva. Si una clase puede aplicar a más de uno, prevalece la fila de mayor especificidad (de arriba hacia abajo).
| Pregunta | nebula-models | nebula-shared | nebula-commons | Microservicio local |
|---|---|---|---|---|
| ¿Es un DTO que viaja en request/response HTTP? | Si | No | No | No |
¿Es un Record de respuesta tipo *Response (Flat-Record ADR-001)? |
Si | No | No | No |
¿Es un mapper entidad→DTO/Record genérico (NebulaEnrichedMapper, etc.)? |
Si | No | No | No |
¿Es un Value Object inmutable de dominio (Money, Address, Periodo, etc.)? |
Si | No | No | No |
¿Es una interfaz @HttpExchange / @FeignClient para invocar otro microservicio? |
No | Si | No | No |
¿Es una excepción transversal (NebulaBusinessException, ErrorCode, *Exception)? |
No | Si | No | No |
¿Es un header HTTP custom o constante de contrato REST (X-Nebula-*)? |
No | Si | No | No |
¿Es una utilidad pura (DateUtil, StringHelper, validador NIT, etc.)? |
No | No | Si | No |
¿Es una @Configuration o auto-config (Spring Boot autoconfig) reutilizable? |
No | No | Si | No |
| ¿Es una constante interna sin relación con un contrato HTTP (cache TTL, page size)? | No | No | Si | No |
| ¿Es una clase específica de la lógica de negocio de un microservicio (Service, Component, Controller, Repository, Entity JPA)? | No | No | No | Si |
Regla simple para devs:
nebula-models (datos) o nebula-shared (contrato/interface).nebula-commons.Paquete raíz: com.centrica.nebula.models
Estructura aprobada:
com.centrica.nebula.models
├── common/ # transversal entre dominios
│ ├── record/ # PageResponse, ErrorResponse, etc.
│ └── (Value Objects globales)
└── <dominio>/ # accounting, government, commerce, etc.
├── dto/ # *Dto (request payloads)
├── record/ # *Response (Flat-Records de consulta)
├── mapper/ # interfaces *Mapper si son genéricas
└── enums/ # enums del dominio que el FE necesita conocer
Lo que SÍ va aquí:
@Builder (regla del equipo, ver ESTANDARES_DESARROLLO).*Response (formato Flat-Record, ver ADR-FLAT_RECORD).Money, Direccion, Periodo).NebulaEnrichedMapper<E, R>).Lo que NO va aquí:
@Entity, @Table, @Column). Las entidades viven en el microservicio dueño del dominio.@Service, @Component, @Repository, @RestController. Estos repos son de datos puros.spring-boot-starter-web o JPA.Versionado: versión 0.x.y-SNAPSHOT mientras se estabiliza el dominio. Bump de minor (0.x → 0.(x+1)) cuando se agregan DTOs no breaking; bump de major cuando hay break de contrato.
Paquete raíz: com.centrica.nebula.shared
Estructura aprobada:
com.centrica.nebula.shared
├── api/ # interfaces de comunicación inter-servicios
│ └── <dominio>/ # accounting, masters, etc.
│ └── <Servicio>Client.java # @HttpExchange / @FeignClient
├── exception/ # excepciones transversales
│ ├── NebulaBusinessException.java
│ ├── NebulaSecurityException.java
│ └── ErrorCode.java # enum de códigos de error
├── constants/ # constantes de contrato HTTP
│ └── HttpHeaders.java # X-Nebula-Client-Id, X-Correlation-Id, etc.
└── i18n/ # llaves de mensajes compartidas (no los bundles)
Lo que SÍ va aquí:
@HttpExchange ó @FeignClient).ErrorCode enum) y estructura de error response (ErrorResponse record).PageRequest, SortRequest).Lo que NO va aquí:
nebula-models).nebula-commons).Paquete raíz: com.centrica.nebula.commons
Estructura aprobada:
com.centrica.nebula.commons
├── util/ # utilidades puras (sin Spring)
│ ├── DateUtil.java
│ ├── NitValidator.java # validador NIT/DV colombiano
│ └── ColombiaUtils.java
├── config/ # auto-configuraciones Spring Boot
│ ├── NebulaSecurityAutoConfiguration.java
│ └── NebulaWebClientAutoConfiguration.java
├── base/ # base classes de los 4 capas del patrón
│ ├── BaseComponent.java
│ ├── BaseService.java
│ └── BaseRepository.java
└── constants/ # constantes INTERNAS (no contractuales)
├── CacheConstants.java
└── PaginationConstants.java
Lo que SÍ va aquí:
static (Lombok @UtilityClass recomendado).NitValidator, EmailValidator).META-INF/spring.factories o META-INF/spring/...AutoConfiguration.imports).Lo que NO va aquí:
nebula-models).nebula-shared).@Service, @RestController, @Repository (sí se permiten @Configuration con métodos @Bean para autoconfig).Auditoría sobre los 22 repos backend revela los siguientes desvíos de la regla. Este documento existe en parte para frenarlos.
Hoy en nebula-shared vive GlobalConstants.java con:
DATE_FORMAT, DATETIME_FORMAT) — debe ir a nebula-commons/constants/DateConstants.HEADER_CLIENT_ID, HEADER_CORRELATION_ID) — sí pertenecen aquí, en constants/HttpHeaders.REGEX_EMAIL, REGEX_PHONE) — deben ir a nebula-commons/util/Regex ó a un EmailValidator.DEFAULT_CACHE_TTL_SECONDS) — debe ir a nebula-commons/constants/CacheConstants.Refactor: dividir GlobalConstants.java en sus componentes y mover cada uno al repo correcto.
nebula-commons actualmente solo contiene la clase NebulaCommonsApplication (scaffold inicial). El equipo nunca depositó utilidades aquí — las re-implementa dentro de cada microservicio o las amontona en nebula-shared o nebula-models.
Refactor: auditar los 19 microservicios. Buscar *Util, *Helper, *Validator, @UtilityClass, @Configuration candidatos y promoverlos a nebula-commons.
Probable: archivos en nebula-models que no son DTO/Record/Mapper/Enum. Auditar antes del Sprint siguiente.
Cuando un microservicio necesita comunicarse con otro, la práctica observada es copiar el DTO localmente en lugar de declarar dependencia a nebula-models. Esto rompe el contrato compartido en silencio.
Refactor: revisar cada microservicio que ya consume datos de nebula-masters o nebula-accounting-core. Sustituir DTOs locales por imports de nebula-models.
Las tres libraries usan el pipeline compartido libraryPipeline.groovy (declarado en cada Jenkinsfile):
| Branch | Acción del pipeline |
|---|---|
feature/*, hotfix/* |
Build + Sonar (sin deploy). Validación temprana. |
develop |
Build + Sonar + mvn deploy -P centrica (publica SNAPSHOT a Nexus). |
qa |
Build + Sonar (sin deploy). Permite ejecutar análisis sobre rama estable antes de promover. |
main |
Build + Sonar + input manual + mvn deploy -P centrica (publica RELEASE a Nexus). |
Detalles del pipeline shared library: ver Pipeline CI/CD (cuando se actualice a v2 que documente la shared library).
Como las 3 libs comparten dependientes (los 19 microservicios), el bump de versión debe ser coordinado:
<version> en pom.xml hacia 0.X.Y-SNAPSHOT, merge a develop → publica SNAPSHOT a Nexus.<nebula-commons.version> (ó la propiedad correspondiente) en <properties> del pom, merge a develop.qa y luego main para release.Para PROD, las 3 libs y los microservicios consumidores deben quedar todos en versiones compatibles antes del cutover.
En el <properties> del pom del microservicio:
<properties>
<nebula-commons.version>0.0.1-SNAPSHOT</nebula-commons.version>
<nebula-models.version>0.0.3-SNAPSHOT</nebula-models.version>
<nebula-shared.version>0.0.1-SNAPSHOT</nebula-shared.version>
</properties>
En <dependencies>:
<dependency>
<groupId>com.centrica.nebula</groupId>
<artifactId>nebula-commons</artifactId>
<version>${nebula-commons.version}</version>
</dependency>
<dependency>
<groupId>com.centrica.nebula</groupId>
<artifactId>nebula-models</artifactId>
<version>${nebula-models.version}</version>
</dependency>
<dependency>
<groupId>com.centrica.nebula</groupId>
<artifactId>nebula-shared</artifactId>
<version>${nebula-shared.version}</version>
</dependency>
Las tres ya están publicadas en Nexus (https://nexus.centricasoluciones.com/repository/centrica/) y el settings.xml de Jenkins ya tiene el repositorio declarado, por lo que no requiere configuración adicional en CI. Para desarrollo local, ver Configuración Maven settings.xml (cuando se documente).
Para garantizar el cumplimiento sostenido de esta división, se está proponiendo el ADR-002 que define un módulo adicional nebula-arch-rules con reglas ArchUnit que validan automáticamente la pertenencia de clases por paquete.
El módulo nebula-arch-rules existe ya como scaffold pero NO está integrado a los pipelines hasta llegar a acuerdo con los gatekeepers del proyecto. Ver ADR-002 División Libraries Nebula para detalle.
| Versión | Fecha | Autor | Cambio |
|---|---|---|---|
| 2.0 | 2026-05-11 | Carlos Torres | Reescritura completa. Incorpora nebula-models (faltaba), tabla de decisión, anti-patrones observados, política de versionado coordinado, referencia a ADR-002. |
| 1.0 | 2026-03 | Carlos Torres | Versión inicial. Solo definía nebula-commons y nebula-shared. |