当我们的 Elasticsearch(es) client 升级到一定版本之后,原有的代码在使用 stored scripts 时,可能会报 java.lang.IllegalArgumentException: lang cannot be specified for stored scripts
异常。
异常原因
原因是升级之后的 es 客户端包的 Script
类实例化源代码有变更导致;在 elasticsearch client 6.0.0 及之后,初始化 Script
类时,在指定加载 stored script 时,脚本语言参数 lang
应该传 null
,不能传 painless
等指定的语言,具体看如下源码片段:
public Script(ScriptType type, String lang, String idOrCode, Map<String, String> options, Map<String, Object> params) {
this.type = (ScriptType)Objects.requireNonNull(type);
this.idOrCode = (String)Objects.requireNonNull(idOrCode);
this.params = Collections.unmodifiableMap((Map)Objects.requireNonNull(params));
if (type == ScriptType.INLINE) {
this.lang = (String)Objects.requireNonNull(lang);
this.options = Collections.unmodifiableMap((Map)Objects.requireNonNull(options));
} else {
if (type != ScriptType.STORED) {
throw new IllegalStateException("unknown script type [" + type.getName() + "]");
}
if (lang != null) {// 变更之处,指定脚本语言反而出错,可能存储脚本里已经指定的缘故
throw new IllegalArgumentException("lang cannot be specified for stored scripts");
}
this.lang = null;
if (options != null) {
throw new IllegalStateException("options cannot be specified for stored scripts");
}
this.options = null;
}
}
解决方法
脚本语言对应的参数 lang
改为 null
即可,具体如下:
错误示例:
new Script(ScriptType.STORED, Script.DEFAULT_SCRIPT_LANG, scriptId, scriptParamsMap);
正确示例:
new Script(ScriptType.STORED, null, scriptId, scriptParamsMap);