Using ElasticSearch with Restlet

Having used Lucene and Solr for many years, I have been really impressed by the power and the facility to implement and use ElasticSearch ( for both indexing and search in concurrent environments.

ElasticSearch provides a REST interface to interact with him and use the JSON format for the exhanged data. The format of URL is very simple and follows this pattern http://host:port/[index]/[type]/[_action/id] and the tool leverages the HTTP methods for operations to execute.

In this post, we will describe how we can leverage Restlet facilities to interact with ElasticSearch. You can notice that ElasticSearch also provides a client Java API to interact with indexes and make searches.

We will use the last version of Restlet 2.1 and Jackson 2. We simply have to put in your classpath the following jar files:

Lets start with indexing.


One of the ElasticSearch characteristics consists in the fact that its schema-free. You dont need to configure the structure of documents we want to handle. It isnt the case for Solr where you have configure document structures and field types. The tool however allows to manually configure your field types and how they will be handle by the engine (not analyzed).

After having installing and running ElasticSearch, you can directly index data. We use a document structure that corresponds to an article with a title field and a list of tags field named tags.

To index an article, you simply have to execute a REST call with the POST method on the following URL: http://host:port/articles/article. In this case, the document identifier will be automatically generated. If you want to specify your own, you can add it at the end of the URL: http://host:port/articles/article/myid.

In the body, you simply specify the data corresponding to your article:

{ "title": "My title",
  "tags": [ "tag1", "tag2", "tag3" ] }

You can notice that the tool also supports inner structures. In this case, corresponding field names are the path to the element in the structure. For example,

For a successful request, the engine returns the following data describing the impacted index, the structure type, the identifier of the added element and its version:


Now we know how to index data using the REST interface of ElasticSearch, lets describe how Restlet can help us to execute the processing within a Java application.

Restlet provides a convenient API for REST for both server and client sides. We are here interested in the client side. Restlet has a low-level API where you have to create the representation by your self and execute HTTP methodsbut the tool goes further by integrating an abstraction upon this API. This abstraction consists in annotation-based support to generate invocation proxies and a conversion support to convert beans to representations and vice versa.

We will leverage this feature to make interact with ElasticSearch really simple. Regarding indexing, we have to create an annotated interface for the call and an object to bring the result.

This interface can be named IndexingService and only contain one method annotated with the Restlet Post annotation, as described below:

public interface IndexingService<T> {
    IndexingResultindex(T doc);

The IndexingResult class simply maps the result of the REST call, so its content is the following:

public class IndexingResult {
    private boolean ok;
    private String index;
    private String type;
    private String id;
    private String version;</code>


Basing on these two entities, indexing an article is quite simple, as described below:

ClientResource cr = new ClientResource(
IndexingService<Article> service = cr.wrap(IndexingService.class);

Article article = new Article();
article.setTags(new ArrayList<String>());

IndexingResult result = service.index(article);

System.out.println("result - ok = "+result.isOk());
System.out.println("result - index = "+result.getIndex());
System.out.println("result - type = "+result.getType());
System.out.println("result - id = "+result.getId());
System.out.println("result - version = "+result.getVersion());

You can notice that you can also wrap and hide the client resource within a dedicated class. Lets deal with now the search aspect.


Search can also be executed through REST calls. Whereas ElasticSearch supports advanced searches, we only describe here how to do simple ones based on the request parameter. For example, searching all articles contained the keyword in their title can be done with the following request: “http://host:port/articles/article/_search&#8221;.

This request returns a JSON response like the one described below:

    "took" : 216,
    "timed_out" : false,
    "_shards" : {
        "total" : 5,
        "successful" : 5,
        "failed" : 0
    "hits" : {
        "total" : 1,
        "max_score" : 0.30685282,
        "hits" : [ {
              "_index" : "articles",
              "_type" : "article",
              "_id" : "Tu-PrtmOS_OWbXGIYTsfxQ",
              "_score" : 0.30685282,
              "_source" : {"title" : "One",   "tags" : ["foo"]}
        } ]

As for indexing, we will create an annotated interface to map the search operation. This interface can be named IndexingService and only contain one method annotated with the Restlet Get annotation, as described below:

public interface SearchService<T> {
SearchResult<T> search();

The SearchResult class simply maps the result of the REST call, so its content is the following:

public class SearchResult {
    private long took;
    private boolean timedOut;
    private Shards shards;
    private SearchHits hits;


This class is based on other ones regarding shards and hit hints. The Shards class content is the following:

public class Shards {
    private int total;
    private int successful;
    private int failed;


The SearchHits class content is the following:

public class SearchHits<T> {
    private int total;
    private double maxScore;
    private List<SearchHit<T>> hits;


The SearchHits class content is the following:

public class SearchHit {
    private String index;
    private String type;
    private String id;
    private double score;
    private Article source;


In the latter class, you can see that you are tied to the Article class. A more generic should be considered using for example generics but this aspect is a tricky one since such use isnt compatible with Jackson deserialization. We can also choose to use an Object type but in the case, Jackson will build a map for the object.

Basing on these entities, searching articles based on a query is quite simple, as described below:

ClientResource cr = new ClientResource(
cr.addQueryParameter("q", "title:one");
cr.addQueryParameter("pretty", "true");
SearchService service = cr.wrap(SearchService.class);
SearchResult result =;

System.out.println("result = "+result.getTook());
System.out.println("result = "+result.isTimedOut());
System.out.println("result = "+result.getShards().getTotal());
System.out.println("result = "+result.getShards().getSuccessful());
System.out.println("result = "+result.getShards().getFailed());
SearchHits<Article> hits = result.getHits();
System.out.println("-- Hits");
System.out.println("result = "+hits.getMaxScore());
System.out.println("result = "+hits.getTotal());
for (SearchHit<Article> hit : hits.getHits()) {
    Article article = hit.getSource();
    System.out.println("-> "+article.getTitle());


As you can see, you can leverage Restlet to interact with ElasticSearch through its REST interface. Basing on automatic data conversion and Jackson, you simply work on beans without any knownledge of the underlying JSON format used.

We could go further by supporting queries and filters as input of REST calls and the configuring of the engine through REST interfaces.

This entry was posted in ElasticSearch, Restlet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s