3.7 KiB
title, source_type, status, created, tags
| title | source_type | status | created | tags | ||||
|---|---|---|---|---|---|---|---|---|
| Spring Boot record @ConfigurationProperties — 보조 생성자 추가 시 No default constructor found | error-note | raw | 2026-06-12 |
|
Spring Boot record @ConfigurationProperties — 보조 생성자 추가 시 No default constructor found
Parent
raw/branch-notes/feature-domain-event-outbox-contract
증상
OutboundHttpSettings record 에 보조 6-arg 생성자를 추가한 뒤 ApplicationContextRunner 로 @ConfigurationProperties 바인딩 테스트를 실행하면:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'app.outbound.http-dev.caskeleton.adapter.outbound.httpclient.OutboundHttpSettings':
Failed to instantiate [...OutboundHttpSettings]: No default constructor found
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate [...OutboundHttpSettings]: No default constructor found
Caused by: java.lang.NoSuchMethodException: ...OutboundHttpSettings.<init>()
기존 6-arg 단일 생성자 record 에서는 동일 테스트가 통과했음.
원인
Spring Boot 3.x 는 @ConfigurationProperties record 에 생성자가 정확히 하나일 때만 canonical constructor binding 을 자동 감지한다. 생성자가 2개 이상(canonical + 보조)이면 Spring 은 단일 생성자 record 특수 경로를 포기하고 일반 JavaBean 경로로 fallback — JavaBean 경로는 no-arg 생성자를 찾다 실패.
핵심 규칙: record 에 생성자가 여러 개이면 바인딩 대상 생성자를 명시해야 한다.
해결
바인딩에 사용할 canonical compact constructor 에 @ConstructorBinding 어노테이션을 추가한다.
import org.springframework.boot.context.properties.bind.ConstructorBinding;
@ConfigurationProperties(prefix = "app.outbound.http")
public record OutboundHttpSettings(
Duration connectTimeout, ...,
Retry retry, CircuitBreaker circuitBreaker) {
@ConstructorBinding // ← 다중 생성자 record 에서 바인딩 대상 명시
public OutboundHttpSettings {
// compact constructor body (validation)
}
/** 보조 생성자 — 기존 6-arg 호출부 무변경 유지 */
public OutboundHttpSettings(Duration connectTimeout, ..., DataSize responseSizeLimit) {
this(connectTimeout, ..., responseSizeLimit, null, null);
}
}
import 주의: org.springframework.boot.context.properties.bind.ConstructorBinding (Spring Boot 3.x). Spring Boot 2.x 의 org.springframework.boot.context.properties.ConstructorBinding 은 deprecated.
재현 조건
- Spring Boot 3.x
@ConfigurationPropertiesrecord - record 에 canonical constructor 외에 보조 생성자가 1개 이상 존재
ApplicationContextRunner또는@SpringBootTest로@EnableConfigurationProperties바인딩
단일 생성자 record 에서는 @ConstructorBinding 없이도 동작.
검증 방법
cd src && ./gradlew :adapter-outbound:test --tests '*OutboundHttpSettingsTest' --console=plain
nested_settings_bind_from_application_context_runner() + settings_bind_from_application_context_runner() 모두 PASS.
Claims To Verify
| Claim | Why uncertain | Status |
|---|---|---|
Spring Boot 3.4 에서 단일 생성자 record 는 @ConstructorBinding 없이 바인딩됨 |
실측 확인(단일 → 보조 추가 시 실패) | locally-verified |
org.springframework.boot.context.properties.bind.ConstructorBinding 이 3.x SSOT import |
Spring Boot 3.4 릴리즈 노트 미확인 — 기존 code 에 해당 어노테이션 미사용 | needs-confirmation |