This is an automated email from the ASF dual-hosted git repository.
dybyte pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git
The following commit(s) were added to refs/heads/dev by this push:
new 18b6cd876c [Fix][API] Preserve extension exception context in
conditional validation (#11228)
18b6cd876c is described below
commit 18b6cd876ca23d8298c0b0926a094a67eab0f8f1
Author: zhiwei.niu <[email protected]>
AuthorDate: Wed Jul 1 16:41:58 2026 +0800
[Fix][API] Preserve extension exception context in conditional validation
(#11228)
---
.../configuration/util/ConditionEvaluators.java | 13 ++----
.../api/configuration/util/ConfigValidator.java | 13 +++++-
.../configuration/util/ConfigValidatorTest.java | 54 ++++++++++++++++++++++
3 files changed, 69 insertions(+), 11 deletions(-)
diff --git
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConditionEvaluators.java
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConditionEvaluators.java
index eacb9566e6..68db4568a0 100644
---
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConditionEvaluators.java
+++
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConditionEvaluators.java
@@ -46,15 +46,10 @@ public final class ConditionEvaluators {
throw new OptionValidationException(
"Condition for option '%s' has a null operator",
condition.getOption().key());
}
- try {
- Object value = config.get(condition.getOption());
- Evaluator evaluator = REGISTRY.get(operator);
- return evaluator.evaluate(value, condition, config);
- } catch (OptionValidationException e) {
- throw new OptionValidationException(
- "Failed to evaluate constraint '%s' on option '%s': %s",
- condition.toString(), condition.getOption().key(),
e.getRawMessage());
- }
+
+ Object value = config.get(condition.getOption());
+ Evaluator evaluator = REGISTRY.get(operator);
+ return evaluator.evaluate(value, condition, config);
}
@SuppressWarnings({"rawtypes"})
diff --git
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigValidator.java
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigValidator.java
index 42d1b1c7b9..ed5a2b356f 100644
---
a/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigValidator.java
+++
b/seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/ConfigValidator.java
@@ -213,8 +213,17 @@ public class ConfigValidator {
}
for (ConditionRule conditionRule : rule.getConditionRules()) {
- if (validate(conditionRule.getExpression())) {
- collectErrors(conditionRule.getOptionRule(),
conditionRule.getExpression(), errors);
+ try {
+ if (validate(conditionRule.getExpression())) {
+ collectErrors(
+ conditionRule.getOptionRule(),
conditionRule.getExpression(), errors);
+ }
+ } catch (OptionValidationException e) {
+ errors.add(
+ formatError(
+ conditionRule.getExpression().toString(),
+ TYPE_CONDITIONAL,
+ e.getRawMessage()));
}
}
diff --git
a/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigValidatorTest.java
b/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigValidatorTest.java
index a0bcd46ff1..4e1f409010 100644
---
a/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigValidatorTest.java
+++
b/seatunnel-api/src/test/java/org/apache/seatunnel/api/configuration/util/ConfigValidatorTest.java
@@ -3598,4 +3598,58 @@ public class ConfigValidatorTest {
msg.contains("port value -1 is not positive"),
"extension exception message should be preserved: " + msg);
}
+
+ @Test
+ public void testConditionalExpressionExceptionUsesWholeExpressionContext()
{
+ ConditionExtension<Integer> throwingExtension =
+ new ConditionExtension<Integer>() {
+ @Override
+ public String description() {
+ return "must be positive";
+ }
+
+ @Override
+ public boolean evaluate(ReadonlyConfig config, Integer
value)
+ throws OptionValidationException {
+ if (value != null && value <= 0) {
+ throw new OptionValidationException(
+ "port value %d is not positive", value);
+ }
+ return true;
+ }
+ };
+
+ Expression expression =
+ Expression.of(
+ Condition.of(MODE, "stream")
+ .and(Conditions.extension(PORT,
throwingExtension)));
+ OptionRule rule =
+ new OptionRule(
+ Arrays.asList(MODE, PORT),
+ Collections.emptyList(),
+ Collections.singletonList(
+ new ConditionRule(
+ expression,
+ new OptionRule(
+ Collections.emptyList(),
+ Collections.emptyList(),
+ Collections.emptyList(),
+ Collections.emptyList()))),
+ Collections.emptyList());
+
+ Map<String, Object> config = new HashMap<>();
+ config.put(MODE.key(), "stream");
+ config.put(PORT.key(), -1);
+
+ OptionValidationException ex =
+ Assertions.assertThrows(
+ OptionValidationException.class,
+ () ->
ConfigValidator.of(ReadonlyConfig.fromMap(config)).validate(rule));
+ String msg = ex.getMessage();
+ Assertions.assertTrue(msg.contains("Option validation failed (1
error):"), msg);
+ Assertions.assertTrue(
+ msg.contains("[1] option: ('mode' == stream && 'port' must be
positive)"), msg);
+ Assertions.assertTrue(msg.contains("type: conditional"), msg);
+ Assertions.assertTrue(msg.contains("constraint: port value -1 is not
positive"), msg);
+ }
}