# Configuration Architecture

## Overview

Configuration in this codebase is intentionally split between application wiring, runtime environment properties, and test-specific overrides. The production configuration focuses on two main concerns: web locale handling and caching. Test code then exercises those same mechanisms under controlled property sets so the application can be verified with different runtime environments.

The result is a configuration model that is simple but cross-cutting: a small number of `@Configuration` classes establish the runtime behavior, while integration tests demonstrate how Spring Boot properties, active profiles, and environment-specific defaults shape the application.

## Implementation Patterns

### Spring configuration classes define application behavior

The primary configuration lives in Spring `@Configuration` classes under `src/main/java/org/springframework/samples/petclinic/system`:

- [`CacheConfiguration`](../src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java) enables Spring caching and creates the application cache used by the vet repository.
- [`WebConfiguration`](../src/main/java/org/springframework/samples/petclinic/system/WebConfiguration.java) configures locale resolution and language switching.

This follows a clear pattern: framework concerns are encapsulated in focused configuration classes rather than scattered through controllers or repositories.

### Properties and environment settings are used at startup and in tests

Runtime configuration is often supplied through Spring Boot properties instead of hard-coded values. The test suite shows this most clearly:

- [`CrashControllerIntegrationTests`](../src/test/java/org/springframework/samples/petclinic/system/CrashControllerIntegrationTests.java) sets `spring.web.error.include-message=ALWAYS` and `management.endpoints.access.default=none` to shape error responses and disable management endpoints for the test.
- [`PostgresIntegrationTests`](../src/test/java/org/springframework/samples/petclinic/PostgresIntegrationTests.java) activates the `postgres` profile and supplies `spring.docker.compose.*` properties to drive container startup.

This makes configuration explicit and testable: the tests demonstrate how the application behaves when different property sources are active.

### Configuration is validated indirectly through integration tests

The project uses integration tests as configuration checks:

- [`CrashControllerIntegrationTests`](../src/test/java/org/springframework/samples/petclinic/system/CrashControllerIntegrationTests.java) verifies that error handling responds correctly to the injected error-related properties.
- [`PostgresIntegrationTests`](../src/test/java/org/springframework/samples/petclinic/PostgresIntegrationTests.java) includes an embedded `PropertiesLogger` that logs resolved environment values and detects overrides between property sources.
- [`I18nPropertiesSyncTest`](../src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java) ensures that localization properties remain synchronized across locales, which is effectively a configuration integrity check for the i18n subsystem.

### Internationalization is configuration-driven

The locale system uses a conventional Spring MVC approach:

- A `LocaleResolver` stores the current locale in the session.
- A `LocaleChangeInterceptor` listens for the `lang` request parameter.
- The interceptor is registered through `WebMvcConfigurer` so it applies to every request.

This means language selection is controlled by request input and message bundles rather than custom application state.

## Key Classes

### [`CacheConfiguration`](../src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java)

This class enables application caching and creates the `vets` cache through a `JCacheManagerCustomizer` bean. It also enables JCache statistics, which makes cache behavior observable through JMX.

Architecturally, this class establishes the caching boundary for the application. The cache definition is centralized, and the rest of the code can rely on caching being available without knowing the underlying JCache implementation.

### [`WebConfiguration`](../src/main/java/org/springframework/samples/petclinic/system/WebConfiguration.java)

This class configures internationalization support for the web layer. It defines:

- a session-based `LocaleResolver`
- a `LocaleChangeInterceptor` bound to the `lang` query parameter
- interceptor registration for request-wide locale changes

This is the primary place where user-facing language behavior is wired into the MVC stack.

### [`PropertiesLogger`](../src/test/java/org/springframework/samples/petclinic/PostgresIntegrationTests.java)

`PropertiesLogger` is an inner helper class used by the PostgreSQL integration test. It walks the Spring `Environment`, prints enumerable property sources, and compares source values with resolved values.

Its purpose is diagnostic rather than functional, but it is valuable because it exposes how property precedence and overrides behave in a real application startup.

### [`TestConfiguration`](../src/test/java/org/springframework/samples/petclinic/system/CrashControllerIntegrationTests.java)

This nested `@SpringBootApplication` exists only for the crash controller test. It excludes data-related auto-configuration so the test can focus on error handling instead of persistence startup.

This is a common configuration pattern in Spring tests: create a minimal application context that contains only what the test needs.

### [`I18nPropertiesSyncTest`](../src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java)

This test class enforces consistency across localization resource bundles. It checks for untranslated or missing keys so that the configuration supporting i18n remains complete.

In architectural terms, it acts as a guardrail around message-property configuration rather than a runtime feature.

## How It Fits Together

```mermaid
flowchart TD
App["Spring Boot Application"]
App --> CacheConfig["CacheConfiguration"]
App --> WebConfig["WebConfiguration"]
App --> Environment["Spring Environment and properties"]
Environment --> CrashTest["CrashControllerIntegrationTests"]
Environment --> PostgresTest["PostgresIntegrationTests"]
Environment --> I18nTest["I18nPropertiesSyncTest"]
CacheConfig --> Cache["JCache vets cache"]
WebConfig --> LocaleResolver["Session locale resolver"]
WebConfig --> LocaleInterceptor["lang parameter interceptor"]
CrashTest --> ErrorHandling["Configured error responses"]
PostgresTest --> Profiles["postgres profile and compose settings"]
PostgresTest --> PropertiesLogger["PropertiesLogger"]
I18nTest --> MessageBundles["messages*.properties"]
```

The diagram shows the main configuration paths:

- the application initializes cache and web configuration at startup
- runtime properties shape the environment
- integration tests verify the resulting behavior
- i18n resource bundles are treated as configuration data and kept in sync by tests

## Notes for Developers

- Keep framework configuration in dedicated `@Configuration` classes. That keeps behavior discoverable and reduces coupling.
- Prefer properties and profiles for environment-specific behavior instead of hard-coded branching.
- When adding a new cache, define it centrally in the cache configuration so cache names and statistics are easy to audit.
- When changing locale behavior, update both `WebConfiguration` and the i18n property files, then make sure the synchronization test still passes.
- If a test needs a narrower application context, use a test-specific `@SpringBootApplication` or nested configuration class instead of reusing the full production startup path.
- Treat localization files as part of configuration, not just content. Missing keys are build-time problems, not runtime surprises.

