Skip to content

refactor: migrate @ConfigurationProperties classes from @Component to @EnableConfigurationProperties pattern #263

Description

@devondragon

Summary

DevLoginConfigProperties and WebAuthnConfigProperties both use @Component directly on the @ConfigurationProperties class to register the bean. The Spring Boot convention is for @ConfigurationProperties classes to be passive data holders, registered via @EnableConfigurationProperties from a dedicated @Configuration class.

This was identified during PR #262 review but deferred because both classes use the same pattern — fixing only one would be inconsistent, and addressing both was outside that PR's scope.

Current Pattern

Both classes use @Component with lifecycle guards directly on the properties class:

@Component@PropertySource("classpath:config/dsspringuserconfig.properties")
@ConfigurationProperties(prefix = "user.dev")
@Profile("local")
@ConditionalOnProperty(name = "user.dev.auto-login-enabled", havingValue = "true", matchIfMissing = false)
publicclassDevLoginConfigProperties {
privatebooleanautoLoginEnabled = false;
privateStringloginRedirectUrl = "/";
}
@Component@PropertySource("classpath:config/dsspringuserconfig.properties")
@ConfigurationProperties(prefix = "user.webauthn")
publicclassWebAuthnConfigProperties {
// ...
}

Desired Pattern

Properties classes should be passive data holders. A @Configuration class owns the activation logic and registers the properties via @EnableConfigurationProperties:

// Pure data holder — no @Component, no activation guards@ConfigurationProperties(prefix = "user.dev")
publicclassDevLoginConfigProperties {
privatebooleanautoLoginEnabled = false;
privateStringloginRedirectUrl = "/";
}
// Configuration class owns the lifecycle@Configuration@Profile("local")
@ConditionalOnProperty(name = "user.dev.auto-login-enabled", havingValue = "true", matchIfMissing = false)
@EnableConfigurationProperties(DevLoginConfigProperties.class)
publicclassDevLoginAutoConfiguration {
// Can also consolidate related @Bean definitions here if needed
}

Files to Change

FileAction
DevLoginConfigProperties.javaRemove @Component, @Profile, @ConditionalOnProperty
WebAuthnConfigProperties.javaRemove @Component
DevLoginAutoConfiguration.javaCreate — @Configuration with @EnableConfigurationProperties(DevLoginConfigProperties.class), owns @Profile("local") and @ConditionalOnProperty guards
WebAuthnAutoConfiguration.javaCreate — @Configuration with @EnableConfigurationProperties(WebAuthnConfigProperties.class)

Why This Matters

  • Spring Boot convention: @ConfigurationProperties classes are meant to be passive. Activation logic belongs in @Configuration classes.
  • Consistency: All config properties in the project should follow the same registration pattern.
  • Testability: Easier to test properties classes in isolation without component scanning side effects.
  • Auto-configuration alignment: If the library ever moves to formal spring.factories/AutoConfiguration.imports per-feature auto-configuration, the @EnableConfigurationProperties pattern is required.

Practical Impact

Low urgency. The current @Component approach works correctly — the guards still prevent beans from loading in the wrong environment. This is a code quality / convention alignment improvement.

Acceptance Criteria

  • DevLoginConfigProperties no longer has @Component
  • WebAuthnConfigProperties no longer has @Component
  • New @Configuration classes register properties via @EnableConfigurationProperties
  • Activation guards (@Profile, @ConditionalOnProperty) live on the @Configuration classes
  • All existing tests pass without modification (or with minimal adjustment)
  • No behavioral change — features activate under the same conditions as before

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions