ElasticSearch: How to Enable Scripting on the Embedded Server
Learn the required steps in order to enable scripting on an embedded elasticsearch server.
Join the DZone community and get the full member experience.
Join For FreeIn this article, I will present all the required steps in order to enable the scripting on an embedded elasticsearch server. I will not explain how to create and use an embedded server but if you need more info you can read this ticket Embedded Elasticsearch Server for Tests.
If you execute a script within the embedded server the following exception will be thrown;
Caused by: java.lang.IllegalArgumentException: script_lang not supported [xxxxx]
at org.elasticsearch.script.ScriptService.getScriptEngineServiceForLang(ScriptService.java:211)
Code Changes
The easiest way to create an embedded server is the following one:
Node node = NodeBuilder.nodeBuilder()
.local (true)
.settings(
//add settings here
)
.node ();
The problem with this approach is that the NodeBuilder.node() method it will create a node class with an empty list of plug-ins; see the NodeBuilder.node code:
/*
* Builds the node without starting it.
*/
public Node build() {
return new Node(settings.build());
}
//Node(Settings) constructor
/**
* Constructs a node with the given settings.
*
* @param preparedSettings Base settings to configure the node with
*/
public Node(Settings preparedSettings) {
this(InternalSettingsPreparer
.prepareEnvironment(preparedSettings, null),
Version.CURRENT,
Collections.<Class<? extends Plugin>>emptyList());
}
In order to create a node having a list of desired plug-ins the second constructor of the Node class should be used:
protected Node(
Environment tmpEnv,
Version version,
Collection<Class<? extends Plugin>> classpathPlugins)
The problem with this (second) constructor is that it is protected so we will need to extend the Node class to be able to use the protected constructor and we will need to extend also the NodeBuilder class in order to use the new Node class.
And here is the code:
//PluginNode class
private static class PluginNode extends Node {
public PluginNode(Settings preparedSettings, List<Class<? extends Plugin>> plugins) {
super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null), Version.CURRENT, plugins);
}
}
//PluginNodeBuilder class
public class PluginNodeBuilder extends NodeBuilder {
private List<Class<? extends Plugin>> plugins = new ArrayList<>();
public PluginNodeBuilder() {
super();
}
//new method to add plug-ins
public PluginNodeBuilder addPlugin(Class<? extends Plugin> plugin) {
plugins.add(plugin);
return this;
}
@Override
//use the new PluginNode to build a node
public Node build() {
return new PluginNode(settings().build(), plugins);
}
};
And how to use the new node builder:
Node node = new PluginNodeBuilder()
.addPlugin(ExpressionPlugin.class)
.addPlugin(GroovyPlugin.class)
.local (true)
.settings(
//add settings here
)
.node ();
Enable Scripting Feature
Using the previous Java code it will not be sufficient to execute the scripts; you must also use the right settings at the server creation and add the (Maven) dependencies to your classpath.
Server Settings
Node node = new PluginNodeBuilder()
.addPlugin(ExpressionPlugin.class)
.addPlugin(GroovyPlugin.class)
.local (true)
.settings (Settings.settingsBuilder ()
...
//this is common for all languages
.put ("script.inline", true)
//this are the settings for the groovy language
.put ("script.engine.groovy.inline.mapping", true)
.put ("script.engine.groovy.inline.search", true)
.put ("script.engine.groovy.inline.update", true)
.put ("script.engine.groovy.inline.plugin", true)
.put ("script.engine.groovy.inline.aggs", true)
//this are the settings for the expression language
.put ("script.engine.expression.inline.mapping", true)
.put ("script.engine.expression.inline.search", true)
.put ("script.engine.expression.inline.update", true)
.put ("script.engine.expression.inline.plugin", true)
.put ("script.engine.expression.inline.aggs", true)
If you need more details about all the possible settings options you can look to the ElasticSearch Scripting documentation.
Maven Dependencies
For the expression language:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-expressions</artifactId>
<version>5.5.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.module</groupId>
<artifactId>lang-expression</artifactId>
<version>2.2.0</version>
<scope>compile</scope>
</dependency>
For the groovy language:
<dependency>
<groupId>org.elasticsearch.module</groupId>
<artifactId>lang-groovy</artifactId>
<version>2.3.2</version>
</dependency>
Published at DZone with permission of Adrian CITU, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments