Backend TiFacturaOnlineNext¶
Referencia técnica del backend de facturación electrónica AFIP (WSFEv1 + WSAA), migrado de Seam/JBoss a Spring Boot. Esta es la página ancla de la referencia: stack exacto, layout de paquetes, capas y build. Para el porqué de cada decisión de migración mirá Migración Seam → Spring; para las reglas que NO se pueden romper, Invariantes.
Datos medidos sobre el código
Todo lo de esta página está validado contra pom.xml, src/main/resources/application*.yml y el árbol src/main/java. Las versiones salen del pom.xml real, no de memoria.
Stack¶
| Pieza | Versión / valor |
|---|---|
| Lenguaje | Java 17 (java.version en pom.xml; el compilar-jar.bat fuerza JDK 17 — NO compila con JDK 25) |
| Framework | Spring Boot 4.0.7 (spring-boot-starter-parent) |
| GroupId / Artifact / Versión | com.tipre / tifactura-spring / 2.0.0-SNAPSHOT |
| Empaquetado | jar (finalName = tifactura-spring) |
| Clase main | com.tipre.tifacturaonlinemanager.Application |
| Web | spring-boot-starter-web + spring-boot-starter-tomcat (Tomcat embebido) |
| Persistencia | spring-boot-starter-data-jpa / Hibernate 7.2.x (lo gestiona el BOM de SB 4.0), SQL Server |
| Driver DB | com.microsoft.sqlserver:mssql-jdbc 12.8.1.jre11 (scope runtime) |
| SOAP | Apache CXF 4.2.2 (cxf-spring-boot-starter-jaxws), contract-first vía cxf-codegen-plugin |
| Scheduling | spring-boot-starter-quartz (Quartz 2.3.2 vía starter) |
| Seguridad | spring-boot-starter-security (scaffold: todo permitAll, ver abajo) |
| Validación | spring-boot-starter-validation (Jakarta Bean Validation) |
| Firma CMS / WSAA | BouncyCastle bcprov-jdk18on + bcpkix-jdk18on 1.78.1 |
| JSON legacy | Jackson 1.x ASL 1.9.13 (org.codehaus.jackson, EOL — usado por las entidades, no se migra en Fase 1) |
| Utils | commons-lang3 (versión vía BOM) |
| Namespace JEE | jakarta.* (persistence, xml.ws, xml.bind, validation, servlet, jws) |
| CXF context path | /TiFacturaOnlineManagerWS (cxf.path en application.yml) |
| Perfil por defecto | dev (spring.profiles.default) |
Bloques de dependencias por SPEC
El pom.xml mantiene comentados —rotulados por SPEC— los bloques pesados aún no abordados: Email (starter-mail + starter-thymeleaf), PDF (iText5 5.5.13.3, PDFBox 2.0.31, Flying Saucer 9.1.22, ZXing 3.5.3), cache de 2do nivel (hibernate-jcache + ehcache), y JAX-RS. Lo que está activo es el núcleo: web, JPA, security, CXF JAX-WS, Quartz y BouncyCastle. Las versiones de los bloques inactivos viven en <properties> pero no se resuelven hasta descomentar el bloque.
Layout de paquetes¶
Raíz: com.tipre.tifacturaonlinemanager. Convive con un paquete org.jboss.seam.* que es el seam-compat propio (un subset reimplementado de Seam 2.3.1 que da soporte a Component, EntityHome, EntityQuery, Controller, logging #0). Ver Seam-compat.
com.tipre.tifacturaonlinemanager
├── Application.java @SpringBootApplication + @EnableScheduling (extends SpringBootServletInitializer)
├── model/ entidades JPA (dominio) — ver modelo-dominio.md
│ ├── afip/ TipoComprobante, TipoDocumento, TipoConcepto, TipoIva, TipoMoneda, TipoTributo
│ ├── trx/ Trx, TrxDetalle, AlicuotaIva, Tributo, Opcional, ComprobanteAsociado, Caea, CaeaSinMovimiento
│ │ └── id/ CaeaSinMovimientoId (clave compuesta @IdClass)
│ ├── error/ TrxErrorLog
│ ├── job/ JobEjecucion
│ ├── tarea/ Tarea, ThreadSafety
│ ├── user/ entidades de usuario
│ ├── EnteFacturador.java comercio emisor (cert AFIP por comercio)
│ ├── SucPosPV.java mapeo sucursal+POS -> PV CAE/CAEA de AFIP
│ └── CockpitStat.java snapshot de métricas del cockpit
├── action/ lógica de negocio portada del legacy
│ ├── db/ SQLServerDialect (dialecto propio) — ver persistencia.md
│ ├── home/ *Home (CRUD por entidad, extends EntityHome)
│ ├── list/ *List (queries, extends EntityQuery)
│ ├── parent/ ParentEntityHome, ParentEntityManager, ParentEntityQuery (núcleo de facturación)
│ ├── ws/ servicios de negocio (FacturacionService, CaeaConsultaService, ...)
│ │ ├── client/ clientes AFIP migrados
│ │ │ ├── wsaa/ WsaaClient, WsaaTokenCache, credenciales
│ │ │ ├── wsfe/ WsfeCaeClient, WsfeCaeaClient, WsfeConsultaClient, WsfeDummyClient, ...
│ │ │ ├── common/ ArcaTlsContextFactory, HttpsSoapTransport
│ │ │ └── exceptions/ jerarquía de errores del cliente
│ │ ├── exceptions/ TrxNotFoundException, ParametroRequeridoException, ...
│ │ └── ws/ jerarquía @WebFault legacy (compila la cadena de errores AFIP)
│ ├── job/, quartz/ jobs Quartz
│ └── utils/
├── ws/endpoint/ endpoints SOAP CXF (TrxWsEndpoint, CaeaWsEndpoint, TfomWsEndpoint) + mappers gen<->modelo
├── web/ controllers REST Spring MVC (CaeaWsRestController, VersionController, ...) + dto/
├── cockpit/ panel de operación: controllers, métricas, ABM de SucPosPV
└── config/ configuración Spring (ver abajo)
Capas¶
El backend conserva la estratificación del legacy Seam, montada sobre el seam-compat.
| Capa | Paquete | Rol |
|---|---|---|
| Domain (entidades) | model/** |
Entidades JPA y enums-tabla AFIP. POJOs anotados jakarta.persistence.*. Ver Modelo de dominio. |
| Homes | action/home/** + action/parent/ParentEntityHome |
CRUD por entidad (extends EntityHome del shim). update() hace solo flush (invariante §5.2), sin merge. |
| Lists | action/list/** + action/parent/ParentEntityQuery |
Queries (extends EntityQuery). getTrx usa order by id desc + maxResults 1 (invariante §5.3). |
| Services | action/ws/** |
Negocio de facturación. ParentEntityManager orquesta idempotencia y persistencia en cascada de la Trx. FacturacionService, CaeaConsultaService, NotaCreditoReconciliacionService. |
| Clients | action/ws/client/** |
Clientes AFIP: WSAA (login CMS, token cache) y WSFE (CAE, CAEA, consulta, dummy, último comprobante). TLS armado en AfipClientConfig. Ver Cliente AFIP. |
| Endpoints SOAP | ws/endpoint/** |
SEI contract-first (CXF) que sirve los WSDL baseline de producción. Ver API SOAP. |
| Controllers REST | web/**, cockpit/** |
Spring MVC. CAEA por REST, versión, y el cockpit. Ver API REST y Cockpit. |
| Config | config/** |
Wiring Spring: seam-compat, CXF, AFIP, Quartz, seguridad, MVC, filtro de tráfico. |
Paquete config¶
| Clase | Rol |
|---|---|
SeamCompatConfig |
Bean entityManager (shared, FlushModeType.COMMIT) + reconocimiento de @Transactional de Seam. |
SeamComponentRegistrar, SeamBridgeInitializer, SeamComponentRegistrar |
Registra los @Name de Seam como beans Spring y cablea el puente Component.getInstance. |
SeamEventScope, SeamEventScopeFilter |
Scope EVENT de Seam por request HTTP. |
SeamTransactionAnnotationParser |
Traduce @Transactional de Seam a la semántica de Spring. |
AfipClientConfig |
Wiring de los clientes AFIP (SSLContext, transportes HTTPS, WSFE, WSAA, AfipCaeService). |
AfipBatchConfig |
Configuración de procesamiento batch AFIP. |
CxfSoapConfig |
Publica los 3 endpoints SOAP con el WSDL baseline. |
QuartzConfig, AutowiringSpringBeanJobFactory |
Scheduling Quartz con inyección Spring en los jobs. |
SecurityConfig |
Scaffold (HITO A): anyRequest().permitAll(), CSRF off. Seguridad real = SPEC-014. |
WebConfig |
View controllers del cockpit (/cockpit, /cockpit-test, /cockpit-prod → forward a cockpit.html). |
TrafficLoggingFilter |
Logea tráfico POS↔servicio al logger TRAFFIC (archivo traffic.log). |
Seguridad: scaffold abierto
SecurityConfig deja todo permitAll con CSRF deshabilitado. Es el scaffold de HITO A para poder levantar y testear; la seguridad real (login DB, roles) está diferida a SPEC-014. El único candado operativo hoy es el header X-Cockpit-Secret del ABM del cockpit (env COCKPIT_ADMIN_SECRET, fail-closed), que NO es autenticación.
Build¶
Maven, parent spring-boot-starter-parent 4.0.7. Requiere JDK 17 (el compilar-jar.bat apunta a Eclipse Adoptium jdk-17 y advierte que NO compila con el JDK 25 default del sistema).
JAR ejecutable¶
# Compila a target/tifactura-spring.jar (sin tests)
mvn clean package -DskipTests
# Con tests (6 tests núcleo verde sobre H2 + gates)
mvn clean package
# Correr
java -jar target/tifactura-spring.jar
# Elegir perfil
java -jar target/tifactura-spring.jar --spring.profiles.active=prod
En Windows está el wrapper compilar-jar.bat (fija JAVA_HOME a JDK 17, corre mvn clean package -DskipTests y deja el JAR en target\).
Generación de código SOAP¶
cxf-codegen-plugin 4.2.2 corre wsdl2java en generate-sources sobre los 3 WSDL de src/main/resources/wsdl/ (TrxWS.wsdl, CaeaWS.wsdl, TiFacturaOnlineManagerWS.wsdl). Como comparten targetNamespace, cada uno se genera a su propio paquete (...ws.gen.trx, ...ws.gen.caea, ...ws.gen.tfom) para no colisionar los wrappers comunes. La salida va a target/generated-sources/cxf.
Nativo (GraalVM)¶
Hay hints AOT pero el build nativo NO está cableado
src/main/resources/META-INF/native-image/com.tipre/tifactura-spring/ contiene reflect-config.json, proxy-config.json y resource-config.json (pistas para GraalVM). Sin embargo, el pom.xml no declara el native-maven-plugin ni un perfil native. El artefacto soportado hoy es el JAR ejecutable; una imagen nativa requeriría agregar el plugin/perfil de GraalVM antes de mvn -Pnative native:compile.
Por dónde seguir¶
- Modelo de dominio — entidades JPA y enums AFIP.
- Persistencia — Hibernate, dialecto, flush MANUAL, naming.
- Config y perfiles —
application*.yml, variables de entorno, AFIP. - Setup de desarrollo — levantar el backend en local.