Runtime Behavior

Request Lifecycle (REST)

Typical REST path for UI-driven operations:

  1. HTTP request enters Spring MVC controller under the servlet context path /configs-service.

  2. SecurityConfig enforces authentication/authorization:

    • JWT is read from HTTP-only cookie (ACCESS_TOKEN) with Authorization: Bearer … fallback (JwtAuthenticationFilter).

    • CSRF protection uses cookie-based token repository (CookieCsrfTokenRepository).

  3. Controller delegates to a @Service method.

  4. The service executes a transaction (@Transactional) and persists changes via Spring Data repositories.

  5. Domain-specific cache services publish derived snapshots into Hazelcast (see Caching Strategy).

  6. Exceptions are converted into a stable error contract by GlobalExceptionHandler (Error Handling).

Transaction Boundaries

  • Write paths are generally annotated with @Transactional at the service level (for example AuthService, TabService, NorthboundConfigService).

  • Read paths use @Transactional(readOnly = true) where implemented.

  • Open-session-in-view is disabled (spring.jpa.open-in-view=false in profile YAMLs), so lazy loading must happen inside service transactions.

Post-commit behavior (important)

  • Auditing is explicitly post-commit: AuditEventListener listens with @TransactionalEventListener(phase = AFTER_COMMIT) and persists audit in a separate transaction (AuditLogWriter uses REQUIRES_NEW).

  • Cache publication is not consistently post-commit today: many domain services call cache refresh methods inside the same @Transactional method. This means Hazelcast may observe changes before the DB transaction commits (or even if the transaction later rolls back).

    This is a known correctness risk for consumers that read Hazelcast directly (ACS, northbound-api, provisionportal, serviceapi, angular backend).

Threading Model

  • Virtual threads are enabled for request handling (spring.threads.virtual.enabled=true in src/main/resources/application.yml).

  • Audit persistence is asynchronous and uses a bounded executor (AuditConfig#auditExecutor) to avoid blocking request threads and to protect the database from unbounded concurrency.

Background/Startup Work

Liquibase

Liquibase runs on application startup when liquibase-core is present and db/changelog/db.changelog-master.yaml exists at the default Spring Boot location (src/main/resources/db/changelog/db.changelog-master.yaml).

Bootstrap operations

  • Bootstrap administrator provisioning: AdminBootstrap (runs once at startup if no ADMIN exists and ft-configs.bootstrap.admin.* is set).

  • TabView bootstrap import: TabViewBootstrapRunner imports XML resources into empty TabView tables on first install only (it checks tabRepository.count() and namespaceRepository.count()).

  • Cube DSL warm-up: CubeDslCacheService warms cache on ApplicationReadyEvent under a read-only transaction.

Scheduling

Scheduling is enabled (@EnableScheduling on FtConfigsServiceApplication), but no @Scheduled jobs are present in this repository at the time of writing.