Skip to content

Default the name-validation.enabled placeholder in NameValidator - #1529

Open
rq-jwhitlock wants to merge 1 commit into
conductor-oss:mainfrom
rq-jwhitlock:jwhitlock/fix-namevalidator-placeholder-default
Open

Default the name-validation.enabled placeholder in NameValidator#1529
rq-jwhitlock wants to merge 1 commit into
conductor-oss:mainfrom
rq-jwhitlock:jwhitlock/fix-namevalidator-placeholder-default

Conversation

@rq-jwhitlock

Copy link
Copy Markdown

Default the name-validation.enabled placeholder in NameValidator

Problem

ValidNameConstraint.NameValidator reads its configuration through a bare @Value with no default:

@Value("${conductor.app.workflow.name-validation.enabled}")
private boolean nameValidationEnabled;

NameValidator lives in conductor-common, so Hibernate Validator instantiates it inside every consuming application's context — not only conductor-server's. conductor-server defines the property in its own application.properties, but an application that embeds conductor-common (or conductor-core / conductor-rest) and supplies its own configuration has no reason to know the key exists. When it doesn't, bean creation fails:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'com.netflix.conductor.common.constraints.ValidNameConstraint$NameValidator':
Injection of autowired dependencies failed
Caused by: org.springframework.util.PlaceholderResolutionException: Could not resolve
placeholder 'conductor.app.workflow.name-validation.enabled'

The failure is lazy, which is what makes it unpleasant to diagnose. Hibernate Validator creates the validator on first use, so nothing fails at startup — the application boots cleanly and reports healthy. The error appears only on the first request carrying a @ValidNameConstraint field, i.e. as a 500 on POST /api/metadata/workflow (or the task-definition equivalent). Because the response is a generic 500 on a registration call, it reads as a malformed payload rather than a configuration problem.

This is the only bare @Value without a default in Conductor's main source.

Fix

@Value("${conductor.app.workflow.name-validation.enabled:false}")

false is the value conductor-server already ships in its application.properties, so behaviour is unchanged for anyone who sets the property, and consumers that don't set it now inherit conductor-server's own default instead of a crash.

Tests

Adds NameValidatorPlaceholderTest with two cases:

  • validatorIsConstructableWhenPropertyIsUndefined — builds a context that omits the property and asserts the bean is created, with validation defaulting to off.
  • explicitPropertyStillTakesEffect — sets the property to true and asserts an invalid name is still rejected, so the default cannot mask a configured value.

The existing NameValidatorTest cannot catch this: it assigns the field via ReflectionTestUtils.setField, which bypasses placeholder resolution entirely.

I verified the new test is load-bearing by reverting the default — NameValidatorPlaceholderTest.validatorIsConstructableWhenPropertyIsUndefined then fails with the original BeanCreationException, while all three pre-existing NameValidatorTest cases stay green.

Verified on main @ 1bad2c88d: conductor-common 109 tests / 0 failures, ./gradlew :conductor-common:build successful, spotlessCheck clean.

Notes

Found while running a Spring Boot application at ReliaQuest that embeds conductor-common with its own configuration; a 500 on workflow registration was the only symptom. No API change, and no behavioural change for existing deployments.

NameValidator reads conductor.app.workflow.name-validation.enabled through a
bare @value with no default. Because the validator lives in conductor-common,
Hibernate Validator instantiates it inside every consuming application's
context, not only conductor-server's, so any consumer that does not define the
property fails bean creation with a PlaceholderResolutionException.

The failure is lazy: it happens on the first request that triggers bean
validation rather than at startup, so it presents as a 500 on workflow or task
registration in an application that started cleanly and reports healthy. That
makes it easy to misattribute to the caller's payload.

Defaults to false, matching the value conductor-server already ships in its
application.properties, so behaviour is unchanged for anyone setting it
explicitly.

Adds NameValidatorPlaceholderTest, which builds a context that omits the
property. The existing NameValidatorTest cannot cover this because it assigns
the field via ReflectionTestUtils and so never resolves the placeholder;
reverting the default leaves those tests green while the new one fails with the
original BeanCreationException.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant