Creating an Elasticsearch Plugin
Elasticsearch is a great search engine built on top of Apache Lucene. We came across the need to add new functionality and did not want to fork Elasticsearch for this. Luckily Elasticsearch comes with a plugin framework. We all ready leverage this framework to use the Apache Thrift transport. There was no documentation on how to create a plugin so after digging around in the code a little we where able to to create our own plugin.
Here is a tutorial on creating a plugin and installing it into Elasticsearch.
- Setup the maven project
mvn archetype:generate -B -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=org.elasticsearch.plugin.awesomeplugin -DartifactId=AwesomePlugin -DpackageName=org.elasticsearch.plugin.awesomeplugin.AwesomePlugin -Dversion=1.0
- Create the elasticsearch plugin properties file in src/main/resources/es-plugin.properties
plugin=${project.groupId}.${project.artifactId}
- Modify the pom.xml to build the plugin and package it correctly
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.elasticsearch.plugin.awesomeplugin</groupId> <artifactId>AwesomePlugin</artifactId> <packaging>jar</packaging> <version>1.0</version> <name>AwesomePlugin</name> <url>http://maven.apache.org</url> <build> <plugins> <!-- Add/Edit items in META-INF/MANIFEST.MF --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.3</version> <configuration> <finalName>elasticsearch-${project.name}-${elasticsearch.version}</finalName> </configuration> </plugin> <!-- Copy dependencies into lib folder --> <!-- To see full classpath use mvn dependency:build-classpath --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.2</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> </configuration> </execution> </executions> </plugin> <!-- Skip Surefire tests --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.8</version> <configuration> <skipTests>true</skipTests> <additionalClasspathElements> <additionalClasspathElement>${project.build.directory}/classes/conf</additionalClasspathElement> <additionalClasspathElement>${project.build.directory}/lib</additionalClasspathElement> </additionalClasspathElements> </configuration> </plugin> <!-- Generate the release zip file (run during package step) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2.1</version> <configuration> <finalName>elasticsearch-${project.name}-${elasticsearch.version}</finalName> <appendAssemblyId>false</appendAssemblyId> <outputDirectory>${project.build.directory}/release/</outputDirectory> <descriptors> <descriptor>assembly/release.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>generate-release-plugin</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*.properties</include> </includes> </resource> </resources> </build> <properties> <elasticsearch.version>0.17.1</elasticsearch.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>${elasticsearch.version}</version> </dependency> </dependencies> <repositories> <repository> <id>sonatype</id> <name>Sonatype Groups</name> <url>https://oss.sonatype.org/content/groups/public/</url> </repository> </repositories> </project>
- Create the release assembly file in assembly/release.xml
<?xml version="1.0"?> <assembly> <id>bin</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <unpack>false</unpack> <outputDirectory>/</outputDirectory> <useProjectArtifact>false</useProjectArtifact> <useTransitiveFiltering>true</useTransitiveFiltering> <excludes> <exclude>org.elasticsearch:elasticsearch</exclude> <exclude>junit:junit</exclude> </excludes> </dependencySet> </dependencySets> <fileSets> <fileSet> <directory>${project.build.directory}/</directory> <outputDirectory>/</outputDirectory> <includes> <include>elasticsearch-${project.name}-${elasticsearch.version}.jar</include> </includes> </fileSet> </fileSets> </assembly>
- Add the projects elasticsearch Module definition class
package org.elasticsearch.awesomeplugin;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
public class AwesomePluginModule extends AbstractModule {
private final Settings settings;
public AwesomePluginModule(Settings settings) {
this.settings = settings;
}
@Override
protected void configure() {
bind(AwesomePluginService.class).asEagerSingleton();
}
}
- Add the projects elasticsearch service entry point
package org.elasticsearch.awesomeplugin;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
public class AwesomePluginService extends AbstractLifecycleComponent<AwesomePluginService>
{
@Inject
public AwesomePluginService(Settings settings, SettingsFilter settingsFilter) {
super(settings);
}
@Override
protected void doClose() throws ElasticSearchException {
}
@Override
protected void doStart() throws ElasticSearchException {
// read some settings
String host = componentSettings.get("host", "localhost");
int port = componentSettings.getAsInt("port", 12345);
}
@Override
protected void doStop() throws ElasticSearchException {
}
}
- You project should now look like this
AwesomePlugin └── assembly | └── release.xml ├── pom.xml └── src ├── main │ ├── java │ │ └── org │ │ └── elasticsearch │ │ ├── awesomeplugin │ │ │ ├── AwesomePluginModule.java │ │ │ ├── AwesomePluginService.java │ │ │ └── Your Files Here │ │ └── plugin │ │ └── awesomeplugin │ │ └── AwesomePlugin.java │ └── resources │ └── es-plugin.properties └── test └── java └── org └── elasticsearch └── plugin └── awesomeplugin └── AwesomePluginTest.java
- Invoking the maven package command will generate the plugin in the target/release folder in a zip file bundled with any dependencies you may have. To install the plugin run the elasticsearch plugin application
mvn clean package elaseticsearch-0.17.1/bin/plugin -url file:./target/release/elasticsearch-awesome-plugin-0.17.1.zip -install awesome-plugin