Friday, December 21, 2012

Elastic Search plugin to add custom REST http handlers

This post demonstrates how to extend elastic search via its plugin model by taking an example of building a simple REST plugin which adds new functionality and can be invoked via POSTing some data to an URL.

Lets start with the folder structure of an elastic search plugin, the picture below demonstrates the same.

Its a simple maven module with sources and resources. - When elastic search instance starts it loads all the inbuilt modules and plugin module being the first one. Plugin module's job is to load and initialize the plugins available in the plugins directory. And this property file specifies the custom plugin class that has to be loaded which does rest of the job like creating new modules, extending existing modules by adding new components etc.

In this example content looks like
CustomRestHandlerPlugin - This class extends the AbstractPlugin of elastic search and is the place where any new modules or components of the custom plugin has to be initialized. Here goes the code for this example.
Override the methods name( ) and description( ) with appropriate details which suits the plugins role. The name should be unique amongst the other plugins in the elastic search server.

The important piece of this class is the onModule(...) method which will be invoked by the plugin module on loading custom plugins. This is the place any existing module can be extended.

This example is to add new REST http handler and to do this we have to extend a REST module which is why the onModule( ) method takes in the parameter as RestModule. The parameter type can be of any class which is of type Module and while invoking this method the plugin module takes care of passing the right module's instance for you to extend.

In this case we are registering a new REST action via a REST module. We will get in to what that REST action looks like in a bit.

RestRegisterAction - Extends the BaseRestHandler whose job is to add new handlers to serve a given http URL.
Notice the constructor annotated with @Inject annotation, elastic search will take care of injecting the required types in to your class, as long as they are bound in to the IOC container by either the elastic search server or any other modules during its initialization. Most of the elastic search components will be bound in IOC container by the time plugins are loaded though (or I think).

Once you have got the reference to the required components via constructor you could do any operations on it based on your need.

In our example all we need is a RestController to which we are adding a new handler for a new URL and in this case the URL is /register and the handler is the same class which expects you to implement handleRequest(RestRequest request, RestChannel channel) method.

When a client makes a HTTP POST request to elastic search server @ /register path this method will be invoked by the RestController. And as you would have guessed you will get access to all the HTTP request attributes and will also give you a way to respond to the client via RestChannel to write response content and headers. Once you get access to the Client instance you can interact with the elastic search for all sort of operations like indexing, searching or even administration tasks.

plugin.xml - Is a plugin descriptor for maven assembly plugin which packages this plugin for deployment on to the elastic search server. The contents of this plugin file and the maven configuration for assembly plugin are shown below.
And this instructs the maven via assembly plugin how to package, and here goes the maven configuration for the same.
Once this is configured packaging a plugin is as simple as running a maven package command.

And the plugin is created as a zip artifact in {project.dir}/target/releases directory.

To install the plugin on to your elastic search server just run the plugin command by specifying the plugin artifact as shown below. Replace the {project.dir} with root directory path of your plugin codebase.

After installing the plugin, restart the elastic search server to load your new plugin and test your plugin using any http command line tools like curl by posting data to the URL http://:9200/register  and verify the response and the servers log.

Hope this helps, I had to post this as there is hardly any documentation around creating custom plugins for elastic search. Watch out this space for posts on building river plugin and more..