The REST API architecture serves as the primary communication interface between client applications and the backend services. This document details the core controller setup, dependency injection patterns, and the standard implementation of system-level API endpoints.
Architecture Overview
The API layer is built using Spring Web, utilizing the @RestController pattern. The UtmStackResource acts as the primary entry point for core system operations, delegating business logic to specialized service classes while maintaining a strict boundary for HTTP request/response handling.
Controller Setup & Dependency Injection
The application strictly adheres to constructor-based dependency injection. This ensures that the controller cannot be instantiated without its required dependencies, making the code more robust and easier to test.
@RestController
@RequestMapping("/api")
public class UtmStackResource {
private final Logger log = LoggerFactory.getLogger(UtmStackResource.class);
private static final String CLASSNAME = "UtmStackResource";
// Dependencies declared as final
private final UtmStackService utmStackService;
private final ApplicationEventService applicationEventService;
private final UtmConfigurationParameterService utmConfigurationParameterService;
private final InfoEndpoint infoEndpoint;
// Constructor injection
public UtmStackResource(UtmStackService utmStackService,
ApplicationEventService applicationEventService,
UtmConfigurationParameterService utmConfigurationParameterService,
InfoEndpoint infoEndpoint) {
this.utmStackService = utmStackService;
this.applicationEventService = applicationEventService;
this.utmConfigurationParameterService = utmConfigurationParameterService;
this.infoEndpoint = infoEndpoint;
}
// ...
}Using final fields with constructor injection is the recommended Spring best practice. It prevents NullPointerException issues at runtime and clearly defines the component's dependencies.
Standard Request Flow
Every complex endpoint in the controller follows a standardized execution and error-handling flow. This ensures consistent logging, auditability, and client responses.
A context string is defined at the start of the method (e.g., final String ctx = CLASSNAME + ".methodName";) to trace errors back to their exact origin.
The business logic is executed within a try block, usually by delegating to an injected service.
If an exception occurs, it is caught and formatted using the context string.
The error is logged via SLF4J, and an application event (ApplicationEventType.ERROR) is persisted to the database via the ApplicationEventService.
A formatted error response is returned to the client using ResponseUtil.buildErrorResponse.
Core API Endpoints
The UtmStackResource exposes several utility and system-level endpoints under the /api base path.
Implementation Detail: The Encrypt Endpoint
The /api/encrypt endpoint demonstrates the standard pattern for handling POST requests, validating input, and interacting with environment variables.
@PostMapping("/encrypt")
public ResponseEntity<String> encrypt(@RequestBody String str) {
final String ctx = CLASSNAME + ".encrypt";
try {
// 1. Input Validation
if (!StringUtils.hasText(str))
throw new Exception("Content to encrypt is missing");
// 2. Execution using Environment Variables
String encryptedValue = CipherUtil.encrypt(str, System.getenv(Constants.ENV_ENCRYPTION_KEY));
return ResponseEntity.ok(encryptedValue);
} catch (Exception e) {
// 3. Standardized Error Handling
String msg = ctx + ": " + e.getLocalizedMessage();
log.error(msg);
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
return ResponseUtil.buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, msg);
}
}The /encrypt endpoint relies on the ENV_ENCRYPTION_KEY environment variable. If this variable is not set in the host environment, the CipherUtil.encrypt method will fail, resulting in an HTTP 500 response.
Frequently Asked Questions
While standard SLF4J logging writes to the console or file system, the ApplicationEventService persists critical system events directly to the database. This allows administrators to view system errors and audit trails directly through the application UI without needing server access.
The /ping endpoint is a simple HTTP 200 response used by load balancers to verify the application is responsive. The /healthcheck endpoint runs utmStackService.executeChecks(), which verifies connections to databases, message queues, and other critical infrastructure.
[Unknown component: br]