U
UTMStack
Backend Initialization

The UTMStack backend is built on Spring Boot, utilizing a robust initialization sequence that ensures proper environment configuration, optimized database connections, and dynamic module loading. This document outlines the core application entry point, configuration properties, and the module factory design that powers the UTMStack API.

Application Entry Point

The application bootstraps through the UtmstackApp class, which serves as the primary Spring Boot entry point. It is annotated with @SpringBootApplication and explicitly enables configuration properties for Liquibase and custom application settings.

Profile Validation

During the @PostConstruct phase, the application performs strict validation on the active Spring profiles to prevent conflicting environments from running simultaneously.

The application will log a severe error if it detects mutually exclusive profiles. Specifically, you cannot run dev and prod together, nor can you run dev and cloud together.

Spring Boot loads the environment variables and active profiles passed via command-line arguments (e.g., --spring.profiles.active=dev).

The initApplication() method checks for conflicting profile combinations using JHipsterConstants.

SpringApplication.run() executes, initializing the IoC container, beans, and embedded web server.

The logApplicationStartup() method determines the protocol (HTTP/HTTPS based on SSL keystore presence), port, and context path, then logs the local and external access URLs.

Spring Profiles in JHipster

UTMStack utilizes JHipster's profile management system. Understanding these profiles is critical for proper environment configuration.

Configuration Settings

The core backend configuration is defined in application.yml. It establishes the baseline behavior for the application, including monitoring, database interactions, and async task execution.

Management and Metrics

UTMStack exposes comprehensive health and metric data via Spring Boot Actuator, mapped to the /management base path.

  • Health Probes: Liveness and readiness probes are enabled (/management/health/liveness and /management/health/readiness), which are essential for Kubernetes deployments.

  • Prometheus Integration: Metrics are exported to Prometheus with a 60-second step interval. Percentile histograms are enabled across all metrics (0.5, 0.75, 0.95, 0.99) to provide accurate latency tracking.

  • Security: The health endpoint details are restricted (show-details: when_authorized) to users with ROLE_ADMIN or ROLE_USER.

JPA and Hibernate Optimization

The data access layer is heavily optimized for performance and consistency.

hibernate.ddl-auto is explicitly set to none. UTMStack relies entirely on Liquibase for database schema management and migrations, preventing Hibernate from making unintended schema changes during startup.

UTMStack configures dedicated thread pools to isolate background tasks from standard HTTP request processing:

spring:
  task:
    execution:
      thread-name-prefix: utm-stack-cloud-backend-task-
      pool:
        core-size: 2
        max-size: 1000
        queue-capacity: 10000
    scheduling:
      thread-name-prefix: utmstack-api-scheduling-
      pool:
        size: 2

This ensures that scheduled jobs and @Async executions do not exhaust the Tomcat worker threads.

Module Factory Architecture

To maintain a clean, decoupled architecture, UTMStack utilizes a Factory Pattern for its application modules. This allows the system to dynamically resolve and instantiate specific business modules at runtime without hardcoding dependencies.

Implementation Details

The ModuleFactory relies on Spring's dependency injection to automatically discover all beans implementing the IModule interface.

@Component
@RequiredArgsConstructor
public class ModuleFactory {
    // Spring automatically injects all beans implementing IModule
    private final Map<String, IModule> moduleBeans;

    private Map<ModuleName, IModule> moduleMap;

    @PostConstruct
    void init() {
        // Remap the injected beans using their specific ModuleName enum as the key
        moduleMap = moduleBeans.values().stream()
                .collect(Collectors.toMap(IModule::getName, Function.identity()));
    }

    public IModule getInstance(ModuleName nameShort) {
        IModule module = moduleMap.get(nameShort);
        if (module == null) {
            throw new IllegalArgumentException("Unrecognized module: " + nameShort.name());
        }
        return module;
    }
}

Adding a new module: To register a new module in the system, simply create a class that implements IModule, annotate it with @Component (or @Service), and ensure its getName() method returns a valid ModuleName enum. The ModuleFactory will automatically wire it during the @PostConstruct phase.

UTMStack
UTMStack © 2026 All rights reserved