This is an automated email from the ASF dual-hosted git repository.

terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 7a43b7fa4fa Fix insecure Bean Validation message templates (#40304)
7a43b7fa4fa is described below

commit 7a43b7fa4faebe14f49fa84e06a8c190daea4662
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Oct 20 22:08:21 2026 +0800

    Fix insecure Bean Validation message templates (#40304)
---
 .../EncryptTableRuleConfigurationValidator.java    |  8 +--
 .../config/EncryptRuleConfigurationTest.java       | 33 ++++++++---
 .../mask/config/MaskRuleConfigurationTest.java     |  9 ++-
 .../ReadwriteSplittingRuleConfigurationTest.java   |  3 +-
 .../ShadowRuleConfigurationValidator.java          | 14 ++---
 .../shadow/config/ShadowRuleConfigurationTest.java | 19 +++++++
 .../ShardingRuleConfigurationValidator.java        | 19 +++----
 .../ShardingTableRuleConfigurationValidator.java   |  3 +-
 .../api/config/ShardingRuleConfigurationTest.java  | 64 ++++++++++++++--------
 ...hardingTableRuleConfigurationValidatorTest.java |  4 +-
 .../reference/ConfigurationReferenceExists.java    |  4 +-
 .../ConfigurationReferenceExistsValidator.java     |  5 +-
 .../unique/UniqueTableNamesValidator.java          |  2 +-
 .../ConfigurationReferenceExistsValidatorTest.java | 16 ++++--
 .../unique/UniqueTableNamesValidatorTest.java      | 13 +++--
 ...YamlRuntimeDatabaseConfigurationsValidator.java | 46 ++++++++--------
 .../YamlMCPLaunchConfigurationSwapperTest.java     | 54 +++++++-----------
 17 files changed, 177 insertions(+), 139 deletions(-)

diff --git 
a/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/validator/EncryptTableRuleConfigurationValidator.java
 
b/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/validator/EncryptTableRuleConfigurationValidator.java
index ea8c69e2771..fbef3a83c83 100644
--- 
a/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/validator/EncryptTableRuleConfigurationValidator.java
+++ 
b/features/encrypt/api/src/main/java/org/apache/shardingsphere/encrypt/config/validator/EncryptTableRuleConfigurationValidator.java
@@ -44,18 +44,18 @@ public final class EncryptTableRuleConfigurationValidator 
implements ConstraintV
     private boolean isDerivedColumnValid(final EncryptColumnRuleConfiguration 
columnConfig, final Collection<String> logicColumnNames, final 
ConstraintValidatorContext context) {
         Optional<EncryptColumnItemRuleConfiguration> assistedQuery = 
columnConfig.getAssistedQuery();
         if (assistedQuery.isPresent() && 
logicColumnNames.contains(assistedQuery.get().getName())) {
-            return addConstraintViolation("assisted query", 
assistedQuery.get().getName(), context);
+            return addConstraintViolation("assisted query column conflicts 
with a logic column", context);
         }
         Optional<EncryptColumnItemRuleConfiguration> likeQuery = 
columnConfig.getLikeQuery();
         if (likeQuery.isPresent() && 
logicColumnNames.contains(likeQuery.get().getName())) {
-            return addConstraintViolation("like query", 
likeQuery.get().getName(), context);
+            return addConstraintViolation("like query column conflicts with a 
logic column", context);
         }
         return true;
     }
     
-    private boolean addConstraintViolation(final String columnType, final 
String columnName, final ConstraintValidatorContext context) {
+    private boolean addConstraintViolation(final String message, final 
ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
-        context.buildConstraintViolationWithTemplate(String.format("%s column 
`%s` conflicts with a logic column", columnType, 
columnName)).addPropertyNode("columns").addConstraintViolation();
+        
context.buildConstraintViolationWithTemplate(message).addPropertyNode("columns").addConstraintViolation();
         return false;
     }
 }
diff --git 
a/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
 
b/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
index 2d641e0811a..cdd35562421 100644
--- 
a/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
+++ 
b/features/encrypt/api/src/test/java/org/apache/shardingsphere/encrypt/config/EncryptRuleConfigurationTest.java
@@ -116,15 +116,15 @@ class EncryptRuleConfigurationTest {
         EncryptRuleConfiguration ruleConfig = createRuleConfiguration(new 
EncryptColumnRuleConfiguration(
                 "foo_col", new 
EncryptColumnItemRuleConfiguration("foo_cipher", "bar_encryptor")));
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables` references unconfigured encryptors 
`bar_encryptor`."));
+        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables` references unconfigured 
encryptors."));
     }
     
     @Test
     void assertDuplicateTableNamesViolation() {
-        EncryptRuleConfiguration ruleConfig = new 
EncryptRuleConfiguration(Arrays.asList(new 
EncryptTableRuleConfiguration("foo_tbl", Collections.emptyList()),
-                new EncryptTableRuleConfiguration("bar_tbl", 
Collections.emptyList()), new EncryptTableRuleConfiguration("foo_tbl", 
Collections.emptyList())), Collections.emptyMap());
+        EncryptRuleConfiguration ruleConfig = new 
EncryptRuleConfiguration(Arrays.asList(new 
EncryptTableRuleConfiguration("foo_{message}", Collections.emptyList()),
+                new EncryptTableRuleConfiguration("bar_tbl", 
Collections.emptyList()), new EncryptTableRuleConfiguration("foo_{message}", 
Collections.emptyList())), Collections.emptyMap());
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names `foo_tbl`."));
+        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names."));
         SQLException actualSQLException = actual.toSQLException();
         assertThat(actualSQLException.getMessage(), is(actual.getMessage()));
         assertThat(actualSQLException.getSQLState(), is("44000"));
@@ -194,13 +194,32 @@ class EncryptRuleConfigurationTest {
                 Arguments.of("Like query column conflicts with another logic 
column", 
createRuleConfiguration(Arrays.asList(crossColumnLikeQueryNameConflict, 
otherLogicColumn), encryptors)));
     }
     
+    @Test
+    void assertValidateAssistedQueryWithTemplateName() {
+        EncryptColumnRuleConfiguration columnConfig = new 
EncryptColumnRuleConfiguration("foo_{message}", new 
EncryptColumnItemRuleConfiguration("foo_cipher", "foo_encryptor"));
+        columnConfig.setAssistedQuery(new 
EncryptColumnItemRuleConfiguration("foo_{message}", "foo_encryptor"));
+        EncryptRuleConfiguration ruleConfig = 
createRuleConfiguration(columnConfig, Collections.singletonMap("foo_encryptor", 
new AlgorithmConfiguration("FIXTURE", new Properties())));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables[].columns` assisted query column 
conflicts with a logic column."));
+    }
+    
+    @Test
+    void assertValidateLikeQueryWithTemplateName() {
+        EncryptColumnRuleConfiguration columnConfig = new 
EncryptColumnRuleConfiguration("foo_{message}", new 
EncryptColumnItemRuleConfiguration("foo_cipher", "foo_encryptor"));
+        columnConfig.setLikeQuery(new 
EncryptColumnItemRuleConfiguration("foo_{message}", "foo_encryptor"));
+        EncryptRuleConfiguration ruleConfig = 
createRuleConfiguration(columnConfig, Collections.singletonMap("foo_encryptor", 
new AlgorithmConfiguration("FIXTURE", new Properties())));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `tables[].columns` like query column conflicts 
with a logic column."));
+    }
+    
     @Test
     void assertValidateInvalidRuleItemConfiguration() {
-        EncryptColumnRuleConfiguration columnConfig = 
createValidColumnConfiguration();
-        columnConfig.setAssistedQuery(new 
EncryptColumnItemRuleConfiguration("foo_col", "foo_encryptor"));
+        EncryptColumnRuleConfiguration columnConfig = new 
EncryptColumnRuleConfiguration("foo_{message}", new 
EncryptColumnItemRuleConfiguration("foo_cipher", "foo_encryptor"));
+        columnConfig.setAssistedQuery(new 
EncryptColumnItemRuleConfiguration("foo_{message}", "foo_encryptor"));
         EncryptTableRuleConfiguration tableConfig = new 
EncryptTableRuleConfiguration("foo_tbl", Collections.singleton(columnConfig));
         EncryptRuleConfiguration ruleConfig = new 
EncryptRuleConfiguration(Collections.emptyList(), Collections.emptyMap());
-        assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validateRuleItem(ruleConfig, tableConfig));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validateRuleItem(ruleConfig, tableConfig));
+        assertThat(actual.getMessage(), is("Invalid 'EncryptRuleConfiguration' 
rule, error message is: Property `columns` assisted query column conflicts with 
a logic column."));
     }
     
     private static EncryptColumnRuleConfiguration 
createValidColumnConfiguration() {
diff --git 
a/features/mask/api/src/test/java/org/apache/shardingsphere/mask/config/MaskRuleConfigurationTest.java
 
b/features/mask/api/src/test/java/org/apache/shardingsphere/mask/config/MaskRuleConfigurationTest.java
index 7ab22f97410..a441a81c126 100644
--- 
a/features/mask/api/src/test/java/org/apache/shardingsphere/mask/config/MaskRuleConfigurationTest.java
+++ 
b/features/mask/api/src/test/java/org/apache/shardingsphere/mask/config/MaskRuleConfigurationTest.java
@@ -35,7 +35,6 @@ import java.util.Properties;
 import java.util.stream.Stream;
 
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -98,7 +97,7 @@ class MaskRuleConfigurationTest {
     void assertUnconfiguredMaskAlgorithmViolation() {
         MaskRuleConfiguration ruleConfig = createRuleConfiguration(new 
MaskColumnRuleConfiguration("foo_col", "bar_mask"));
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), containsString("Property `tables` 
references unconfigured maskAlgorithms `bar_mask`."));
+        assertThat(actual.getMessage(), is("Invalid 'MaskRuleConfiguration' 
rule, error message is: Property `tables` references unconfigured 
maskAlgorithms."));
     }
     
     @Test
@@ -107,7 +106,7 @@ class MaskRuleConfigurationTest {
                 new MaskTableRuleConfiguration("bar_tbl", 
Collections.emptyList()), new MaskTableRuleConfiguration("foo_tbl", 
Collections.emptyList()),
                 new MaskTableRuleConfiguration("bar_tbl", 
Collections.emptyList()), new MaskTableRuleConfiguration("foo_tbl", 
Collections.emptyList())), Collections.emptyMap());
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), is("Invalid 'MaskRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names `foo_tbl, bar_tbl`."));
+        assertThat(actual.getMessage(), is("Invalid 'MaskRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names."));
         SQLException actualSQLException = actual.toSQLException();
         assertThat(actualSQLException.getMessage(), is(actual.getMessage()));
         assertThat(actualSQLException.getSQLState(), is("44000"));
@@ -120,8 +119,8 @@ class MaskRuleConfigurationTest {
                 new MaskTableRuleConfiguration("foo_tbl", 
Collections.singleton(new MaskColumnRuleConfiguration("foo_col", "bar_mask"))),
                 new MaskTableRuleConfiguration("foo_tbl", 
Collections.emptyList())), Collections.emptyMap());
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), is("Invalid 'MaskRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names `foo_tbl`.; "
-                + "Property `tables` references unconfigured maskAlgorithms 
`bar_mask`."));
+        assertThat(actual.getMessage(), is("Invalid 'MaskRuleConfiguration' 
rule, error message is: Property `tables` must not contain duplicate table 
names.; "
+                + "Property `tables` references unconfigured 
maskAlgorithms."));
     }
     
     private static Stream<Arguments> invalidRuleConfigurationArguments() {
diff --git 
a/features/readwrite-splitting/api/src/test/java/org/apache/shardingsphere/readwritesplitting/config/ReadwriteSplittingRuleConfigurationTest.java
 
b/features/readwrite-splitting/api/src/test/java/org/apache/shardingsphere/readwritesplitting/config/ReadwriteSplittingRuleConfigurationTest.java
index feb67831433..d68b98e298a 100644
--- 
a/features/readwrite-splitting/api/src/test/java/org/apache/shardingsphere/readwritesplitting/config/ReadwriteSplittingRuleConfigurationTest.java
+++ 
b/features/readwrite-splitting/api/src/test/java/org/apache/shardingsphere/readwritesplitting/config/ReadwriteSplittingRuleConfigurationTest.java
@@ -87,8 +87,7 @@ class ReadwriteSplittingRuleConfigurationTest {
         ReadwriteSplittingRuleConfiguration ruleConfig = 
createRuleConfiguration(new ReadwriteSplittingDataSourceGroupRuleConfiguration(
                 "foo_group", "foo_write", 
Collections.singletonList("foo_read"), "bar_load_balancer"));
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(),
-                is("Invalid 'ReadwriteSplittingRuleConfiguration' rule, error 
message is: Property `dataSourceGroups` references unconfigured loadBalancers 
`bar_load_balancer`."));
+        assertThat(actual.getMessage(), is("Invalid 
'ReadwriteSplittingRuleConfiguration' rule, error message is: Property 
`dataSourceGroups` references unconfigured loadBalancers."));
     }
     
     private static Stream<Arguments> invalidRuleConfigurationArguments() {
diff --git 
a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/config/validator/ShadowRuleConfigurationValidator.java
 
b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/config/validator/ShadowRuleConfigurationValidator.java
index a640e91b2ef..10dd94dc8d8 100644
--- 
a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/config/validator/ShadowRuleConfigurationValidator.java
+++ 
b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/config/validator/ShadowRuleConfigurationValidator.java
@@ -52,15 +52,14 @@ public final class ShadowRuleConfigurationValidator 
implements ConstraintValidat
     
     private boolean areTableDataSourcesValid(final ShadowRuleConfiguration 
ruleConfig, final ConstraintValidatorContext context) {
         Collection<String> dataSourceNames = 
ruleConfig.getDataSources().stream().map(ShadowDataSourceConfiguration::getName).collect(Collectors.toSet());
-        return ruleConfig.getTables().entrySet().stream().allMatch(entry -> 
areTableDataSourcesValid(entry.getKey(), entry.getValue(), dataSourceNames, 
context));
+        return ruleConfig.getTables().values().stream().allMatch(each -> 
areTableDataSourcesValid(each, dataSourceNames, context));
     }
     
-    private boolean areTableDataSourcesValid(final String tableName, final 
ShadowTableConfiguration tableConfig, final Collection<String> dataSourceNames, 
final ConstraintValidatorContext context) {
+    private boolean areTableDataSourcesValid(final ShadowTableConfiguration 
tableConfig, final Collection<String> dataSourceNames, final 
ConstraintValidatorContext context) {
         for (String each : tableConfig.getDataSourceNames()) {
             if (!dataSourceNames.contains(each)) {
                 context.disableDefaultConstraintViolation();
-                
context.buildConstraintViolationWithTemplate(String.format("table `%s` 
references unconfigured shadow data source `%s`", tableName, each))
-                        .addPropertyNode("tables").addConstraintViolation();
+                context.buildConstraintViolationWithTemplate("references an 
unconfigured shadow data 
source").addPropertyNode("tables").addConstraintViolation();
                 return false;
             }
         }
@@ -68,15 +67,14 @@ public final class ShadowRuleConfigurationValidator 
implements ConstraintValidat
     }
     
     private boolean areTableAlgorithmsValid(final ShadowRuleConfiguration 
ruleConfig, final ConstraintValidatorContext context) {
-        return ruleConfig.getTables().entrySet().stream().allMatch(entry -> 
areTableAlgorithmsValid(entry.getKey(), entry.getValue(), ruleConfig, context));
+        return ruleConfig.getTables().values().stream().allMatch(each -> 
areTableAlgorithmsValid(each, ruleConfig, context));
     }
     
-    private boolean areTableAlgorithmsValid(final String tableName, final 
ShadowTableConfiguration tableConfig, final ShadowRuleConfiguration ruleConfig, 
final ConstraintValidatorContext context) {
+    private boolean areTableAlgorithmsValid(final ShadowTableConfiguration 
tableConfig, final ShadowRuleConfiguration ruleConfig, final 
ConstraintValidatorContext context) {
         for (String each : tableConfig.getShadowAlgorithmNames()) {
             if (!ruleConfig.getShadowAlgorithms().containsKey(each)) {
                 context.disableDefaultConstraintViolation();
-                
context.buildConstraintViolationWithTemplate(String.format("table `%s` 
references unconfigured shadow algorithm `%s`", tableName, each))
-                        .addPropertyNode("tables").addConstraintViolation();
+                context.buildConstraintViolationWithTemplate("references an 
unconfigured shadow 
algorithm").addPropertyNode("tables").addConstraintViolation();
                 return false;
             }
         }
diff --git 
a/features/shadow/api/src/test/java/org/apache/shardingsphere/shadow/config/ShadowRuleConfigurationTest.java
 
b/features/shadow/api/src/test/java/org/apache/shardingsphere/shadow/config/ShadowRuleConfigurationTest.java
index 1fedec45649..948bd1662d9 100644
--- 
a/features/shadow/api/src/test/java/org/apache/shardingsphere/shadow/config/ShadowRuleConfigurationTest.java
+++ 
b/features/shadow/api/src/test/java/org/apache/shardingsphere/shadow/config/ShadowRuleConfigurationTest.java
@@ -22,6 +22,7 @@ import 
org.apache.shardingsphere.infra.config.rule.validator.RuleConfigurationVa
 import 
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
 import 
org.apache.shardingsphere.shadow.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.config.table.ShadowTableConfiguration;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -89,6 +90,24 @@ class ShadowRuleConfigurationTest {
                 Arguments.of("Whitespace shadow algorithm type reaches SPI", " 
", "Property `shadowAlgorithms` does not match an available SPI 
implementation."));
     }
     
+    @Test
+    void assertValidateUnconfiguredDataSourceWithTemplateNames() {
+        ShadowRuleConfiguration ruleConfig = 
createRuleConfiguration(Collections.singleton(new 
ShadowDataSourceConfiguration("foo_ds", "foo_primary", "foo_shadow")),
+                Collections.singletonMap("foo_{message}", new 
ShadowTableConfiguration(Collections.singleton("bar_{message}"), 
Collections.singleton("foo_shadow_algorithm"))),
+                Collections.singletonMap("foo_shadow_algorithm", new 
AlgorithmConfiguration("FIXTURE", new Properties())));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 'ShadowRuleConfiguration' 
rule, error message is: Property `tables` references an unconfigured shadow 
data source."));
+    }
+    
+    @Test
+    void assertValidateUnconfiguredAlgorithmWithTemplateNames() {
+        ShadowRuleConfiguration ruleConfig = 
createRuleConfiguration(Collections.singleton(new 
ShadowDataSourceConfiguration("foo_ds", "foo_primary", "foo_shadow")),
+                Collections.singletonMap("foo_{message}", new 
ShadowTableConfiguration(Collections.singleton("foo_ds"), 
Collections.singleton("bar_{message}"))),
+                Collections.singletonMap("foo_shadow_algorithm", new 
AlgorithmConfiguration("FIXTURE", new Properties())));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 'ShadowRuleConfiguration' 
rule, error message is: Property `tables` references an unconfigured shadow 
algorithm."));
+    }
+    
     @ParameterizedTest(name = "{0}")
     @MethodSource("invalidRuleConfigurationArguments")
     void assertValidateInvalidRuleConfiguration(final String name, final 
ShadowRuleConfiguration ruleConfig) {
diff --git 
a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingRuleConfigurationValidator.java
 
b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingRuleConfigurationValidator.java
index 11369ea92c7..9882ec99196 100644
--- 
a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingRuleConfigurationValidator.java
+++ 
b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingRuleConfigurationValidator.java
@@ -65,21 +65,19 @@ public final class ShardingRuleConfigurationValidator 
implements ConstraintValid
         if (null == strategyConfig || 
ruleConfig.getKeyGenerators().containsKey(strategyConfig.getKeyGeneratorName()))
 {
             return true;
         }
-        return addViolation(propertyName, String.format("references 
unconfigured key generator `%s`", strategyConfig.getKeyGeneratorName()), 
context);
+        return addViolation(propertyName, "references an unconfigured key 
generator", context);
     }
     
     private boolean areKeyGenerateStrategiesValid(final 
ShardingRuleConfiguration ruleConfig, final ConstraintValidatorContext context) 
{
-        return 
ruleConfig.getKeyGenerateStrategies().entrySet().stream().allMatch(entry -> 
isKeyGenerateStrategiesValid(entry.getKey(), entry.getValue(), ruleConfig, 
context));
+        return 
ruleConfig.getKeyGenerateStrategies().values().stream().allMatch(each -> 
isKeyGenerateStrategiesValid(each, ruleConfig, context));
     }
     
-    private boolean isKeyGenerateStrategiesValid(final String strategyName, 
final KeyGenerateStrategiesConfiguration strategyConfig,
-                                                 final 
ShardingRuleConfiguration ruleConfig, final ConstraintValidatorContext context) 
{
+    private boolean isKeyGenerateStrategiesValid(final 
KeyGenerateStrategiesConfiguration strategyConfig, final 
ShardingRuleConfiguration ruleConfig, final ConstraintValidatorContext context) 
{
         if (!(strategyConfig instanceof 
ColumnKeyGenerateStrategiesRuleConfiguration) && !(strategyConfig instanceof 
SequenceKeyGenerateStrategiesRuleConfiguration)) {
-            return addViolation("keyGenerateStrategies", 
String.format("strategy `%s` must use column or sequence key generation", 
strategyName), context);
+            return addViolation("keyGenerateStrategies", "must use column or 
sequence key generation", context);
         }
         if 
(!ruleConfig.getKeyGenerators().containsKey(strategyConfig.getKeyGeneratorName()))
 {
-            return addViolation("keyGenerateStrategies", 
String.format("strategy `%s` references unconfigured key generator `%s`",
-                    strategyName, strategyConfig.getKeyGeneratorName()), 
context);
+            return addViolation("keyGenerateStrategies", "references an 
unconfigured key generator", context);
         }
         return true;
     }
@@ -89,9 +87,8 @@ public final class ShardingRuleConfigurationValidator 
implements ConstraintValid
         if (null == strategyConfig) {
             return true;
         }
-        return strategyConfig.getAuditorNames().stream()
-                .filter(each -> 
!ruleConfig.getAuditors().containsKey(each)).findFirst()
-                .map(each -> addViolation(propertyName, 
String.format("references unconfigured auditor `%s`", each), 
context)).orElse(true);
+        return strategyConfig.getAuditorNames().stream().filter(each -> 
!ruleConfig.getAuditors().containsKey(each)).findFirst()
+                .map(optional -> addViolation(propertyName, "references an 
unconfigured auditor", context)).orElse(true);
     }
     
     private boolean isShardingStrategyValid(final 
ShardingStrategyConfiguration strategyConfig, final String propertyName,
@@ -99,7 +96,7 @@ public final class ShardingRuleConfigurationValidator 
implements ConstraintValid
         if (null == strategyConfig || strategyConfig instanceof 
NoneShardingStrategyConfiguration || 
ruleConfig.getShardingAlgorithms().containsKey(strategyConfig.getShardingAlgorithmName()))
 {
             return true;
         }
-        return addViolation(propertyName, String.format("references 
unconfigured sharding algorithm `%s`", 
strategyConfig.getShardingAlgorithmName()), context);
+        return addViolation(propertyName, "references an unconfigured sharding 
algorithm", context);
     }
     
     private boolean addViolation(final String propertyName, final String 
message, final ConstraintValidatorContext context) {
diff --git 
a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
 
b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
index 12740d73ab7..943f980f381 100644
--- 
a/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
+++ 
b/features/sharding/api/src/main/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidator.java
@@ -44,8 +44,7 @@ public final class ShardingTableRuleConfigurationValidator 
implements Constraint
             String configuredSchemaName = 
schemaNamesByDataSource.putIfAbsent(dataNode.getDataSourceName(), 
dataNode.getSchemaName());
             if (null != configuredSchemaName && 
!configuredSchemaName.equalsIgnoreCase(dataNode.getSchemaName())) {
                 context.disableDefaultConstraintViolation();
-                
context.buildConstraintViolationWithTemplate(String.format("contains multiple 
schemas for storage unit `%s` in sharding table `%s`",
-                        dataNode.getDataSourceName(), 
value.getLogicTable())).addPropertyNode("actualDataNodes").addConstraintViolation();
+                
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addPropertyNode("actualDataNodes").addConstraintViolation();
                 return false;
             }
         }
diff --git 
a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
 
b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
index 3cf2c7710b8..36e48ccc04f 100644
--- 
a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
+++ 
b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/ShardingRuleConfigurationTest.java
@@ -75,8 +75,7 @@ class ShardingRuleConfigurationTest {
     void assertValidateMultipleSchemasForSameDataSource() {
         ShardingRuleConfiguration ruleConfig = createRuleConfiguration(new 
ShardingTableRuleConfiguration("foo_tbl", 
"ds_0.foo_schema_${0..1}.foo_tbl_${0..1}"));
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
-        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: "
-                + "Property `tables[0].actualDataNodes` contains multiple 
schemas for storage unit `ds_0` in sharding table `foo_tbl`."));
+        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: Property 
`tables[0].actualDataNodes` contains multiple schemas for a storage unit."));
     }
     
     @Test
@@ -84,11 +83,26 @@ class ShardingRuleConfigurationTest {
         ShardingRuleConfiguration ruleConfig = new ShardingRuleConfiguration();
         ShardingTableRuleConfiguration tableConfig = new 
ShardingTableRuleConfiguration("foo_tbl", 
"ds_0.foo_schema_${0..1}.foo_tbl_${0..1}");
         InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validateRuleItem(ruleConfig, tableConfig));
-        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: "
-                + "Property `actualDataNodes` contains multiple schemas for 
storage unit `ds_0` in sharding table `foo_tbl`."));
+        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: Property `actualDataNodes` 
contains multiple schemas for a storage unit."));
         assertTrue(ruleConfig.getTables().isEmpty());
     }
     
+    @Test
+    void assertValidateWithTemplateNames() {
+        ShardingRuleConfiguration ruleConfig = createRuleConfiguration(
+                new ShardingTableRuleConfiguration("foo_{message}", 
"<LITERAL>ds_{message}.foo_schema.foo_tbl_0,ds_{message}.bar_schema.foo_tbl_1"));
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: Property 
`tables[0].actualDataNodes` contains multiple schemas for a storage unit."));
+    }
+    
+    @Test
+    void assertValidateRuleItemWithTemplateNames() {
+        ShardingTableRuleConfiguration tableConfig = new 
ShardingTableRuleConfiguration("foo_{message}", 
"<LITERAL>ds_{message}.foo_schema.foo_tbl_0,ds_{message}.bar_schema.foo_tbl_1");
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class,
+                () -> RuleConfigurationValidator.validateRuleItem(new 
ShardingRuleConfiguration(), tableConfig));
+        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: Property `actualDataNodes` 
contains multiple schemas for a storage unit."));
+    }
+    
     @ParameterizedTest(name = "{0}")
     @MethodSource("validSchemaDataNodesArguments")
     void assertValidateValidSchemaDataNodes(final String name, final 
ShardingTableRuleConfiguration tableConfig) {
@@ -332,14 +346,14 @@ class ShardingRuleConfigurationTest {
     
     @ParameterizedTest(name = "{0}")
     @MethodSource("invalidReferenceRuleConfigurationArguments")
-    void assertValidateInvalidReferenceRuleConfiguration(final String name, 
final ShardingRuleConfiguration ruleConfig) {
-        assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+    void assertValidateInvalidReferenceRuleConfiguration(final String name, 
final ShardingRuleConfiguration ruleConfig, final String expectedMessage) {
+        InvalidRuleConfigurationException actual = 
assertThrows(InvalidRuleConfigurationException.class, () -> 
RuleConfigurationValidator.validate(ruleConfig));
+        assertThat(actual.getMessage(), is("Invalid 
'ShardingRuleConfiguration' rule, error message is: " + expectedMessage));
     }
     
     private static Stream<Arguments> 
invalidReferenceRuleConfigurationArguments() {
         ShardingRuleConfiguration unconfiguredTableDatabaseShardingAlgorithm = 
createValidRuleConfiguration();
-        
unconfiguredTableDatabaseShardingAlgorithm.getTables().iterator().next()
-                .setDatabaseShardingStrategy(new 
StandardShardingStrategyConfiguration("user_id", "bar_standard"));
+        
unconfiguredTableDatabaseShardingAlgorithm.getTables().iterator().next().setDatabaseShardingStrategy(new
 StandardShardingStrategyConfiguration("user_id", "foo_{message}"));
         ShardingRuleConfiguration unconfiguredTableShardingAlgorithm = 
createValidRuleConfiguration();
         unconfiguredTableShardingAlgorithm.getTables().iterator().next()
                 .setTableShardingStrategy(new 
ComplexShardingStrategyConfiguration("order_id,user_id", "bar_complex"));
@@ -350,30 +364,32 @@ class ShardingRuleConfigurationTest {
         ShardingRuleConfiguration unconfiguredDefaultTableShardingAlgorithm = 
createValidRuleConfiguration();
         
unconfiguredDefaultTableShardingAlgorithm.setDefaultTableShardingStrategy(new 
ComplexShardingStrategyConfiguration("order_id,user_id", "bar_complex"));
         ShardingRuleConfiguration unconfiguredTableAuditor = 
createValidRuleConfiguration();
-        
unconfiguredTableAuditor.getTables().iterator().next().setAuditStrategy(new 
ShardingAuditStrategyConfiguration(Collections.singleton("bar_auditor"), 
false));
+        
unconfiguredTableAuditor.getTables().iterator().next().setAuditStrategy(new 
ShardingAuditStrategyConfiguration(Collections.singleton("foo_{message}"), 
false));
         ShardingRuleConfiguration unconfiguredAutoTableAuditor = 
createValidRuleConfiguration();
         
unconfiguredAutoTableAuditor.getAutoTables().iterator().next().setAuditStrategy(new
 ShardingAuditStrategyConfiguration(Collections.singleton("bar_auditor"), 
false));
         ShardingRuleConfiguration unconfiguredDefaultAuditor = 
createValidRuleConfiguration();
         unconfiguredDefaultAuditor.setDefaultAuditStrategy(new 
ShardingAuditStrategyConfiguration(Collections.singleton("bar_auditor"), 
false));
         ShardingRuleConfiguration unconfiguredDefaultKeyGenerator = 
createValidRuleConfiguration();
-        unconfiguredDefaultKeyGenerator.setDefaultKeyGenerateStrategy(new 
KeyGenerateStrategyConfiguration("order_id", "bar_key_generator"));
+        unconfiguredDefaultKeyGenerator.setDefaultKeyGenerateStrategy(new 
KeyGenerateStrategyConfiguration("order_id", "foo_{message}"));
         ShardingRuleConfiguration 
unconfiguredKeyGenerateStrategiesKeyGenerator = createValidRuleConfiguration();
-        
unconfiguredKeyGenerateStrategiesKeyGenerator.getKeyGenerateStrategies().put(
-                "bar_column", new 
ColumnKeyGenerateStrategiesRuleConfiguration("bar_key_generator", "foo_tbl", 
"order_id"));
+        
unconfiguredKeyGenerateStrategiesKeyGenerator.getKeyGenerateStrategies().put("foo_{message}",
 new ColumnKeyGenerateStrategiesRuleConfiguration("bar_{message}", "foo_tbl", 
"order_id"));
         ShardingRuleConfiguration unsupportedKeyGenerateStrategies = 
createValidRuleConfiguration();
-        
unsupportedKeyGenerateStrategies.getKeyGenerateStrategies().put("bar_strategy", 
new UnsupportedKeyGenerateStrategiesConfiguration());
+        
unsupportedKeyGenerateStrategies.getKeyGenerateStrategies().put("foo_{message}",
 new UnsupportedKeyGenerateStrategiesConfiguration());
         return Stream.of(
-                Arguments.of("Unconfigured table database sharding algorithm", 
unconfiguredTableDatabaseShardingAlgorithm),
-                Arguments.of("Unconfigured table sharding algorithm", 
unconfiguredTableShardingAlgorithm),
-                Arguments.of("Unconfigured auto table sharding algorithm", 
unconfiguredAutoTableShardingAlgorithm),
-                Arguments.of("Unconfigured default database sharding 
algorithm", unconfiguredDefaultDatabaseShardingAlgorithm),
-                Arguments.of("Unconfigured default table sharding algorithm", 
unconfiguredDefaultTableShardingAlgorithm),
-                Arguments.of("Unconfigured table auditor", 
unconfiguredTableAuditor),
-                Arguments.of("Unconfigured auto table auditor", 
unconfiguredAutoTableAuditor),
-                Arguments.of("Unconfigured default auditor", 
unconfiguredDefaultAuditor),
-                Arguments.of("Unconfigured default key generator", 
unconfiguredDefaultKeyGenerator),
-                Arguments.of("Unconfigured key generate strategies key 
generator", unconfiguredKeyGenerateStrategiesKeyGenerator),
-                Arguments.of("Unsupported key generate strategies type", 
unsupportedKeyGenerateStrategies));
+                Arguments.of("Unconfigured table database sharding algorithm", 
unconfiguredTableDatabaseShardingAlgorithm, "Property `tables` references an 
unconfigured sharding algorithm."),
+                Arguments.of("Unconfigured table sharding algorithm", 
unconfiguredTableShardingAlgorithm, "Property `tables` references an 
unconfigured sharding algorithm."),
+                Arguments.of("Unconfigured auto table sharding algorithm", 
unconfiguredAutoTableShardingAlgorithm, "Property `autoTables` references an 
unconfigured sharding algorithm."),
+                Arguments.of("Unconfigured default database sharding 
algorithm", unconfiguredDefaultDatabaseShardingAlgorithm,
+                        "Property `defaultDatabaseShardingStrategy` references 
an unconfigured sharding algorithm."),
+                Arguments.of("Unconfigured default table sharding algorithm", 
unconfiguredDefaultTableShardingAlgorithm,
+                        "Property `defaultTableShardingStrategy` references an 
unconfigured sharding algorithm."),
+                Arguments.of("Unconfigured table auditor", 
unconfiguredTableAuditor, "Property `tables` references an unconfigured 
auditor."),
+                Arguments.of("Unconfigured auto table auditor", 
unconfiguredAutoTableAuditor, "Property `autoTables` references an unconfigured 
auditor."),
+                Arguments.of("Unconfigured default auditor", 
unconfiguredDefaultAuditor, "Property `defaultAuditStrategy` references an 
unconfigured auditor."),
+                Arguments.of("Unconfigured default key generator", 
unconfiguredDefaultKeyGenerator, "Property `defaultKeyGenerateStrategy` 
references an unconfigured key generator."),
+                Arguments.of("Unconfigured key generate strategies key 
generator", unconfiguredKeyGenerateStrategiesKeyGenerator,
+                        "Property `keyGenerateStrategies` references an 
unconfigured key generator."),
+                Arguments.of("Unsupported key generate strategies type", 
unsupportedKeyGenerateStrategies, "Property `keyGenerateStrategies` must use 
column or sequence key generation."));
     }
     
     private static ShardingAutoTableRuleConfiguration 
createValidAutoTableRuleConfiguration() {
diff --git 
a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
 
b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
index ecdd2a71668..cdc90d2885e 100644
--- 
a/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
+++ 
b/features/sharding/api/src/test/java/org/apache/shardingsphere/sharding/api/config/validator/ShardingTableRuleConfigurationValidatorTest.java
@@ -82,10 +82,10 @@ class ShardingTableRuleConfigurationValidatorTest {
         try (MockedStatic<InlineExpressionParserFactory> mockedFactory = 
mockStatic(InlineExpressionParserFactory.class)) {
             mockedFactory.when(() -> 
InlineExpressionParserFactory.newInstance("data_nodes")).thenReturn(parser);
             
when(parser.splitAndEvaluate()).thenReturn(Arrays.asList("ds_0.foo_schema.foo_tbl_0",
 "ds_0.bar_schema.foo_tbl_1"));
+            
when(context.getDefaultConstraintMessageTemplate()).thenReturn("contains 
multiple schemas for a storage unit");
             assertFalse(validator.isValid(new 
ShardingTableRuleConfiguration("foo_tbl", "data_nodes"), context));
             verify(context).disableDefaultConstraintViolation();
-            verify(context.buildConstraintViolationWithTemplate("contains 
multiple schemas for storage unit `ds_0` in sharding table `foo_tbl`")
-                    
.addPropertyNode("actualDataNodes")).addConstraintViolation();
+            verify(context.buildConstraintViolationWithTemplate("contains 
multiple schemas for a storage 
unit").addPropertyNode("actualDataNodes")).addConstraintViolation();
         }
     }
 }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExists.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExists.java
index 82cd7bd5ca0..73a74c07802 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExists.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExists.java
@@ -57,11 +57,11 @@ public @interface ConfigurationReferenceExists {
     boolean allowEmpty() default false;
     
     /**
-     * Get the violation message. Use {pool} for the configuration pool 
property and {reference} for the missing name.
+     * Get the violation message. Use {pool} for the configuration pool 
property.
      *
      * @return violation message
      */
-    String message() default "references unconfigured {pool} `{reference}`";
+    String message() default "references unconfigured {pool}";
     
     /**
      * Get groups.
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidator.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidator.java
index 75c464e1567..ca6da035409 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidator.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidator.java
@@ -40,8 +40,6 @@ public final class ConfigurationReferenceExistsValidator 
implements ConstraintVa
     
     private boolean allowEmpty;
     
-    private String message;
-    
     @Override
     public void initialize(final ConfigurationReferenceExists 
constraintAnnotation) {
         ShardingSpherePreconditions.checkState(0 != 
constraintAnnotation.referencePaths().length, () -> new ValidationException("At 
least one configuration reference property is required."));
@@ -53,7 +51,6 @@ public final class ConfigurationReferenceExistsValidator 
implements ConstraintVa
         ShardingSpherePreconditions.checkState(!poolProperty.isEmpty() && 
!poolProperty.contains("."),
                 () -> new ValidationException("Configuration pool must be a 
property on the annotated object."));
         allowEmpty = constraintAnnotation.allowEmpty();
-        message = constraintAnnotation.message();
     }
     
     private String[] parseReferencePaths(final String referencePath) {
@@ -106,7 +103,7 @@ public final class ConfigurationReferenceExistsValidator 
implements ConstraintVa
             return true;
         }
         context.disableDefaultConstraintViolation();
-        context.buildConstraintViolationWithTemplate(message.replace("{pool}", 
poolProperty).replace("{reference}", (String) 
value)).addPropertyNode(rootProperty).addConstraintViolation();
+        
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addPropertyNode(rootProperty).addConstraintViolation();
         return false;
     }
     
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
index 283b1ff39d5..a29c888e2be 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidator.java
@@ -39,7 +39,7 @@ public final class UniqueTableNamesValidator implements 
ConstraintValidator<Uniq
             return true;
         }
         context.disableDefaultConstraintViolation();
-        context.buildConstraintViolationWithTemplate(String.format("must not 
contain duplicate table names `%s`", String.join(", ", 
duplicatedTableNames))).addConstraintViolation();
+        
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addConstraintViolation();
         return false;
     }
     
diff --git 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidatorTest.java
 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidatorTest.java
index 931bf608e94..29dd79c7438 100644
--- 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidatorTest.java
+++ 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/reference/ConfigurationReferenceExistsValidatorTest.java
@@ -52,14 +52,22 @@ class ConfigurationReferenceExistsValidatorTest {
         Set<ConstraintViolation<DirectConfiguration>> actual = 
VALIDATOR.validate(new DirectConfiguration("bar_provider", 
Collections.singletonMap("foo_provider", "configured")));
         assertThat(actual.size(), is(1));
         assertThat(actual.iterator().next().getPropertyPath().toString(), 
is("providerName"));
-        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured providers `bar_provider`"));
+        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured providers"));
+    }
+    
+    @Test
+    void assertUnconfiguredReferenceWithTemplateCharacters() {
+        Collection<ConstraintViolation<DirectConfiguration>> actual = 
VALIDATOR.validate(new DirectConfiguration("bar_{message}_${7*7}", 
Collections.singletonMap("foo_provider", "configured")));
+        assertThat(actual.size(), is(1));
+        assertThat(actual.iterator().next().getPropertyPath().toString(), 
is("providerName"));
+        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured providers"));
     }
     
     @Test
     void assertUnconfiguredReferenceWithMissingPool() {
         Set<ConstraintViolation<DirectConfiguration>> actual = 
VALIDATOR.validate(new DirectConfiguration("bar_provider", null));
         assertThat(actual.size(), is(1));
-        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured providers `bar_provider`"));
+        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured providers"));
     }
     
     @Test
@@ -76,7 +84,7 @@ class ConfigurationReferenceExistsValidatorTest {
         Set<ConstraintViolation<NestedConfiguration>> actual = 
VALIDATOR.validate(config);
         assertThat(actual.size(), is(1));
         assertThat(actual.iterator().next().getPropertyPath().toString(), 
is("groups"));
-        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured algorithms `bar_algorithm`"));
+        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured algorithms"));
     }
     
     @Test
@@ -87,7 +95,7 @@ class ConfigurationReferenceExistsValidatorTest {
                 Collections.singletonMap("foo_algorithm", "configured"));
         Set<ConstraintViolation<NestedConfiguration>> actual = 
VALIDATOR.validate(config);
         assertThat(actual.size(), is(1));
-        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured algorithms `first_missing`"));
+        assertThat(actual.iterator().next().getMessage(), is("references 
unconfigured algorithms"));
     }
     
     @Test
diff --git 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
index 09fdbf63435..9543c870e8a 100644
--- 
a/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
+++ 
b/infra/common/src/test/java/org/apache/shardingsphere/infra/config/rule/validator/constraint/unique/UniqueTableNamesValidatorTest.java
@@ -69,10 +69,11 @@ class UniqueTableNamesValidatorTest {
     
     @ParameterizedTest(name = "{0}")
     @MethodSource("duplicatedTablesArguments")
-    void assertIsValidWithDuplicatedNames(final String name, final 
Collection<?> tables, final String expectedMessage) {
+    void assertIsValidWithDuplicatedNames(final String name, final 
Collection<?> tables) {
         ConstraintValidatorContext context = 
mock(ConstraintValidatorContext.class);
         ConstraintViolationBuilder builder = 
mock(ConstraintViolationBuilder.class);
-        
when(context.buildConstraintViolationWithTemplate(expectedMessage)).thenReturn(builder);
+        when(context.getDefaultConstraintMessageTemplate()).thenReturn("must 
not contain duplicate table names");
+        when(context.buildConstraintViolationWithTemplate("must not contain 
duplicate table names")).thenReturn(builder);
         assertFalse(validator.isValid(tables, context));
         verify(context).disableDefaultConstraintViolation();
         verify(builder).addConstraintViolation();
@@ -80,10 +81,10 @@ class UniqueTableNamesValidatorTest {
     
     private static Stream<Arguments> duplicatedTablesArguments() {
         return Stream.of(
-                Arguments.of("Nonadjacent duplicated name", 
createTables("foo_tbl", "bar_tbl", "foo_tbl"), "must not contain duplicate 
table names `foo_tbl`"),
-                Arguments.of("All duplicated names retain encounter order", 
createTables("z_tbl", "a_tbl", "z_tbl", "a_tbl", "z_tbl"),
-                        "must not contain duplicate table names `z_tbl, 
a_tbl`"),
-                Arguments.of("Names read across different table types", 
Arrays.asList(new Table("foo_tbl"), new OtherTable("foo_tbl")), "must not 
contain duplicate table names `foo_tbl`"));
+                Arguments.of("Nonadjacent duplicated name", 
createTables("foo_tbl", "bar_tbl", "foo_tbl")),
+                Arguments.of("Multiple duplicated names", 
createTables("z_tbl", "a_tbl", "z_tbl", "a_tbl", "z_tbl")),
+                Arguments.of("Names read across different table types", 
Arrays.asList(new Table("foo_tbl"), new OtherTable("foo_tbl"))),
+                Arguments.of("Template characters in duplicated names", 
createTables("foo_{message}_${7*7}", "foo_{message}_${7*7}")));
     }
     
     @Test
diff --git 
a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/validator/YamlRuntimeDatabaseConfigurationsValidator.java
 
b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/validator/YamlRuntimeDatabaseConfigurationsValidator.java
index b2ecbf3e2af..e058eb6796a 100644
--- 
a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/validator/YamlRuntimeDatabaseConfigurationsValidator.java
+++ 
b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/validator/YamlRuntimeDatabaseConfigurationsValidator.java
@@ -43,52 +43,52 @@ public final class 
YamlRuntimeDatabaseConfigurationsValidator implements Constra
     
     private boolean validateRuntimeDatabase(final String databaseName, final 
YamlRuntimeDatabaseConfiguration config, final ConstraintValidatorContext 
context) {
         if (isPlaceholder(databaseName)) {
-            addViolation(context, String.format("contains placeholder database 
name `%s`", databaseName));
+            addViolation(context, "contains placeholder database name");
             return false;
         }
         if (null == config) {
-            addViolation(context, String.format("contains null configuration 
for database `%s`", databaseName));
+            addViolation(context, "contains null database configuration");
             return false;
         }
-        return validateNoPlaceholders(databaseName, config, context);
+        return validateNoPlaceholders(config, context);
     }
     
-    private boolean validateNoPlaceholders(final String databaseName, final 
YamlRuntimeDatabaseConfiguration config, final ConstraintValidatorContext 
context) {
-        boolean result = validateNoPlaceholder(databaseName, "jdbcUrl", 
config.getJdbcUrl(), context);
-        result = validateNoPlaceholder(databaseName, "username", 
config.getUsername(), context) && result;
-        result = validateNoPlaceholder(databaseName, "driverClassName", 
config.getDriverClassName(), context) && result;
-        return validateNoPasswordPlaceholder(databaseName, 
config.getPassword(), context) && result;
+    private boolean isPlaceholder(final String value) {
+        String actualValue = value.trim();
+        int startIndex = actualValue.indexOf('<');
+        return startIndex >= 0 && actualValue.indexOf('>', startIndex + 1) > 
startIndex + 1;
+    }
+    
+    private void addViolation(final ConstraintValidatorContext context, final 
String message) {
+        context.disableDefaultConstraintViolation();
+        
context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
+    }
+    
+    private boolean validateNoPlaceholders(final 
YamlRuntimeDatabaseConfiguration config, final ConstraintValidatorContext 
context) {
+        boolean result = validateNoPlaceholder("jdbcUrl", config.getJdbcUrl(), 
context);
+        result = validateNoPlaceholder("username", config.getUsername(), 
context) && result;
+        result = validateNoPlaceholder("driverClassName", 
config.getDriverClassName(), context) && result;
+        return validateNoPasswordPlaceholder(config.getPassword(), context) && 
result;
     }
     
-    private boolean validateNoPlaceholder(final String databaseName, final 
String propertyName, final String value, final ConstraintValidatorContext 
context) {
+    private boolean validateNoPlaceholder(final String propertyName, final 
String value, final ConstraintValidatorContext context) {
         if (null == value || !isPlaceholder(value)) {
             return true;
         }
-        addViolation(context, String.format("contains placeholder database 
`%s` property `%s`", databaseName, propertyName));
+        addViolation(context, String.format("contains placeholder database 
property `%s`", propertyName));
         return false;
     }
     
-    private boolean validateNoPasswordPlaceholder(final String databaseName, 
final String value, final ConstraintValidatorContext context) {
+    private boolean validateNoPasswordPlaceholder(final String value, final 
ConstraintValidatorContext context) {
         if (null == value || !isStandalonePlaceholder(value)) {
             return true;
         }
-        addViolation(context, String.format("contains placeholder database 
`%s` property `password`", databaseName));
+        addViolation(context, "contains placeholder database property 
`password`");
         return false;
     }
     
-    private boolean isPlaceholder(final String value) {
-        String actualValue = value.trim();
-        int startIndex = actualValue.indexOf('<');
-        return startIndex >= 0 && actualValue.indexOf('>', startIndex + 1) > 
startIndex + 1;
-    }
-    
     private boolean isStandalonePlaceholder(final String value) {
         String actualValue = value.trim();
         return actualValue.startsWith("<") && actualValue.endsWith(">") && 
actualValue.length() > 2;
     }
-    
-    private void addViolation(final ConstraintValidatorContext context, final 
String message) {
-        context.disableDefaultConstraintViolation();
-        
context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
-    }
 }
diff --git 
a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/swapper/YamlMCPLaunchConfigurationSwapperTest.java
 
b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/swapper/YamlMCPLaunchConfigurationSwapperTest.java
index 9a925f4a9be..e54cda6a4cc 100644
--- 
a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/swapper/YamlMCPLaunchConfigurationSwapperTest.java
+++ 
b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/config/yaml/swapper/YamlMCPLaunchConfigurationSwapperTest.java
@@ -24,6 +24,8 @@ import 
org.apache.shardingsphere.mcp.bootstrap.config.MCPLaunchConfiguration;
 import 
org.apache.shardingsphere.mcp.bootstrap.config.yaml.config.YamlMCPLaunchConfiguration;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.yaml.snakeyaml.constructor.ConstructorException;
 
 import java.util.Collections;
@@ -233,12 +235,9 @@ class YamlMCPLaunchConfigurationSwapperTest {
     
     @Test
     void assertSwapToObjectWithNullRuntimeDatabaseConfiguration() {
-        String yamlContent = "transport:\n"
-                + "  type: STDIO\n"
-                + "runtimeDatabases:\n"
-                + "  logic_db:\n";
+        String yamlContent = "transport:\n" + "  type: STDIO\n" + 
"runtimeDatabases:\n" + "  foo_{message}:\n";
         IllegalArgumentException actual = 
assertThrows(IllegalArgumentException.class, () -> 
swapper.swapToObject(YamlEngine.unmarshal(yamlContent, 
YamlMCPLaunchConfiguration.class)));
-        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains null configuration for database `logic_db`."));
+        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains null database configuration."));
     }
     
     @Test
@@ -258,44 +257,31 @@ class YamlMCPLaunchConfigurationSwapperTest {
     
     @Test
     void assertSwapToObjectWithPlaceholderRuntimeDatabaseName() {
-        String yamlContent = "transport:\n"
-                + "  type: STDIO\n"
-                + "runtimeDatabases:\n"
-                + "  <unresolved-database>:\n"
-                + "    jdbcUrl: jdbc:mysql://localhost:3306/logic_db\n"
-                + "    username: demo\n"
-                + "    password: ''\n"
-                + "    driverClassName: com.mysql.cj.jdbc.Driver\n";
+        String yamlContent = "transport:\n" + "  type: STDIO\n" + 
"runtimeDatabases:\n" + "  <foo_{message}>:\n" + "    jdbcUrl: 
jdbc:mysql://localhost:3306/logic_db\n" + "    username: demo\n"
+                + "    password: ''\n" + "    driverClassName: 
com.mysql.cj.jdbc.Driver\n";
         IllegalArgumentException actual = 
assertThrows(IllegalArgumentException.class, () -> 
swapper.swapToObject(YamlEngine.unmarshal(yamlContent, 
YamlMCPLaunchConfiguration.class)));
-        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains placeholder database name 
`<unresolved-database>`."));
+        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains placeholder database name."));
     }
     
-    @Test
-    void assertSwapToObjectWithPlaceholderJdbcUrl() {
-        String yamlContent = "transport:\n"
-                + "  type: STDIO\n"
-                + "runtimeDatabases:\n"
-                + "  logic_db:\n"
-                + "    jdbcUrl: jdbc:mysql://<unresolved-host>:3306/logic_db\n"
-                + "    username: demo\n"
-                + "    password: ''\n"
-                + "    driverClassName: com.mysql.cj.jdbc.Driver\n";
+    @ParameterizedTest(name = "{0}")
+    @CsvSource({
+            "JDBC URL, jdbc:mysql://<unresolved-host>:3306/logic_db, demo, 
com.mysql.cj.jdbc.Driver, jdbcUrl",
+            "username, jdbc:mysql://localhost:3306/logic_db, 
<unresolved-username>, com.mysql.cj.jdbc.Driver, username",
+            "driver class name, jdbc:mysql://localhost:3306/logic_db, demo, 
<unresolved-driver>, driverClassName"
+    })
+    void assertSwapToObjectWithPlaceholderRuntimeDatabaseProperty(final String 
name, final String jdbcUrl, final String username, final String 
driverClassName, final String propertyName) {
+        String yamlContent = "transport:\n" + "  type: STDIO\n" + 
"runtimeDatabases:\n" + "  foo_{message}:\n" + "    jdbcUrl: " + jdbcUrl + "\n" 
+ "    username: " + username + "\n"
+                + "    password: ''\n" + "    driverClassName: " + 
driverClassName + "\n";
         IllegalArgumentException actual = 
assertThrows(IllegalArgumentException.class, () -> 
swapper.swapToObject(YamlEngine.unmarshal(yamlContent, 
YamlMCPLaunchConfiguration.class)));
-        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains placeholder database `logic_db` property 
`jdbcUrl`."));
+        assertThat(actual.getMessage(), is(String.format("MCP launch 
configuration property `runtimeDatabases` contains placeholder database 
property `%s`.", propertyName)));
     }
     
     @Test
     void assertSwapToObjectWithPlaceholderPassword() {
-        String yamlContent = "transport:\n"
-                + "  type: STDIO\n"
-                + "runtimeDatabases:\n"
-                + "  logic_db:\n"
-                + "    jdbcUrl: jdbc:mysql://localhost:3306/logic_db\n"
-                + "    username: demo\n"
-                + "    password: <unresolved-password>\n"
-                + "    driverClassName: com.mysql.cj.jdbc.Driver\n";
+        String yamlContent = "transport:\n" + "  type: STDIO\n" + 
"runtimeDatabases:\n" + "  foo_{message}:\n" + "    jdbcUrl: 
jdbc:mysql://localhost:3306/logic_db\n" + "    username: demo\n"
+                + "    password: <unresolved-password>\n" + "    
driverClassName: com.mysql.cj.jdbc.Driver\n";
         IllegalArgumentException actual = 
assertThrows(IllegalArgumentException.class, () -> 
swapper.swapToObject(YamlEngine.unmarshal(yamlContent, 
YamlMCPLaunchConfiguration.class)));
-        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains placeholder database `logic_db` property 
`password`."));
+        assertThat(actual.getMessage(), is("MCP launch configuration property 
`runtimeDatabases` contains placeholder database property `password`."));
     }
     
     @Test

Reply via email to