ymal解析问题:Configuration property name ‘-index’ is not valid
问题由来
启动canal adapter项目,配置好了同步mysql 到elasticseach的同步配置文件,如下所示,发现一直报错
dataSourceKey: defaultDS
destination: pay_parent_0
groupId: g1
esMapping:
_index: pay_parent_0
_id: id
sql: select id, user_id, status, creator, create_time, updater, update_time, deleted, tenant_id from pay_parent_0 as a
etlCondition: where a.id={}
commitBatch: 3000
报错内容如下
Caused by: org.springframework.boot.context.properties.source.InvalidConfigurationPropertyNameException: Configuration property name '-index' is not valid
at org.springframework.boot.context.properties.source.InvalidConfigurationPropertyNameException.throwIfHasInvalidChars(InvalidConfigurationPropertyNameException.java:51) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.source.ConfigurationPropertyName.append(ConfigurationPropertyName.java:189) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.lambda$bindBean$4(Binder.java:335) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:73) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.lambda$null$5(Binder.java:342) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1631) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502) ~[na:na]
问题分析
报错内容为-index 的属性key不合法,找到报错的位置校验代码,org.springframework.boot.context.properties.source.ConfigurationPropertyName.ElementValidator#isValidChar这里不允许以’-'开头的key值。
public static boolean isValidChar(char ch, int index) {
return isAlpha(ch) || isNumeric(ch) || index != 0 && ch == '-';
}
但是我配置文件配置的是 _index,明显对不上,所以应该是yaml解析时做了转换。于是开始debug跟踪,发现yaml解析bean时有这么一段方法,该方法会将所有的key中的下划线转成横杠,那应该是这个问题。
BeanProperty(String name, ResolvableType declaringClassType) {
this.name = BeanPropertyName.toDashedForm(name);
this.declaringClassType = declaringClassType;
}
public static String toDashedForm(String name, int start) {
StringBuilder result = new StringBuilder();
char[] chars = name.replace("_", "-").toCharArray(); // 下环线转化
for(int i = start; i < chars.length; ++i) {
char ch = chars[i];
if (Character.isUpperCase(ch) && result.length() > 0 && result.charAt(result.length() - 1) != '-') {
result.append("-");
}
result.append(Character.toLowerCase(ch));
}
return result.toString();
}
问题解决
解决方式有两种思路,一个是修改配置类,去掉下划线开头的key,这样就不会转换成“-”,所以这个得需要修改代码。修改配置类的get方案,因为yaml的bean解析是从get set方法解析处属性的值,例如get_index会解析处_index属性,这里需要将get_index方法名修改成getIndex _index 修改成index属性。如下的修改
另外一种思路是修改springboot 和spring core 版本,因为高版本是兼容这种下划线开头的key,找到相同的高本本解析bean位置代码,发现已经去掉了对下环线的替代, char[] chars = name.replace(“_”, “-”).toCharArray(); 这行方法已经去掉了。这个是spring2.5版本,具体升级到哪个版本,根据实际项目来操作。
public static String toDashedForm(String name) {
StringBuilder result = new StringBuilder(name.length());
boolean inIndex = false;
for(int i = 0; i < name.length(); ++i) {
char ch = name.charAt(i);
if (inIndex) {
result.append(ch);
if (ch == ']') {
inIndex = false;
}
} else if (ch == '[') {
inIndex = true;
result.append(ch);
} else {
ch = ch != '_' ? ch : 45;
if (Character.isUpperCase(ch) && result.length() > 0 && result.charAt(result.length() - 1) != '-') {
result.append('-');
}
result.append(Character.toLowerCase(ch));
}
}
return result.toString();
}