Lightbend Activator

Play Framework with Elasticsearch

Activator will be EOL-ed on May 24, 2017.

We’re making it easier and simpler for developers to get started with Lightbend technologies. This unfortunately means that future releases of Play, Akka and Scala will no longer include Activator support, and Lightbend’s Activator server will be decommissioned by the end of 2017. Instead of supporting Activator to create and set up development projects, we'll be supporting standard Giter8 templates for sbt users and Maven archetypes for Maven users. So going forward,

To create new Lightbend projects

Instead of using the Activator command, make sure you have sbt 0.13.13 (or higher), and use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. You can find a list of templates here.

Also, as a convenience, the Lightbend Project Starter allows you to quickly create a variety of example projects that you just unzip and run.

To create new templates

If you want to create new templates, you can now do that in Giter8.

To migrate templates from Activator to Giter8

If you created Activator templates in the past, please consider migrating them to Giter8 with this simple process.

Play Framework with Elasticsearch

evojam
Source
May 5, 2016
playframework scala elasticsearch

An example Play app that connects to Elasticsearch 2.3.X using play-elastic4s.

How to get "Play Framework with Elasticsearch" on your computer

There are several ways to get this template.

Option 1: Choose play-scala-rest-elasticsearch in the Lightbend Activator UI.

Already have Lightbend Activator (get it here)? Launch the UI then search for play-scala-rest-elasticsearch in the list of templates.

Option 2: Download the play-scala-rest-elasticsearch project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for play-scala-rest-elasticsearch.

  1. Download the Template Bundle for "Play Framework with Elasticsearch"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Lightbend Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\play-scala-rest-elasticsearch> activator ui 
    This will start Lightbend Activator and open this template in your browser.

Option 3: Create a play-scala-rest-elasticsearch project from the command line

If you have Lightbend Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME play-scala-rest-elasticsearch on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/evojam/play-elastic-template#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Before You Start

Hello, you have just created a small Play Framework application with Elasticsearch integration.

Before it gets functional, you need an Elasticsearch instance up and running. Note that this template assumes ES version 2.3.X and will not work with others. Consult Elasticsearch setup documentation for information on running a local instance or use a 2.3 docker image. We would also suggest installing kopf plugin as it gives a nice and human-friendly way of inspecting your ES cluster.

Verify if your ES installation is correct by running curl $ES_HOST:9200 (replace $ES_HOST with the proper host, e.g. curl localhost:9200 if you're running a local ES instance). You should get output similar to the following:

{
  "name" : "Isaac Christians",
  "cluster_name" : "es",
  "version" : {
    "number" : "2.3.0",
    "build_hash" : "8371be8d5fe5df7fb9c0516c474d77b9feddd888",
    "build_timestamp" : "2016-03-29T07:54:48Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}

If version.number is 2.3.X, you're good to go. If you get no response, there is a problem with your ES setup and you need to troubleshoot it before going further.

If you have no previous experience with ElasticSearch, it's high time you did something about it. Definitely install the kopf plugin (if you're running the ES on your local machine, ./elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf/2.0 will do just fine), visit the kopf dashboard and spend some time learning the basic concepts behind Elasticsearch. Further tutorial assumes you have the basic understanding of ES indices, documents and indexing.

Setting up

All app configuration is managed via your application.conf. As a minimum, you need to set one cluster in clusters node, providing uri and cluster.name. After setting it up you're ready to run the application using the run tab or the buttons under the template name. Then go visit localhost:9000/es/stats to check if the ES connection is working. You should see output similar to curl $ES_HOST:9200.

Okay, you've got ES running and your app can talk to it. Now it's time to create ES indices. Your application should not be responsible for administrating the ES cluster. As an exception, though, we added an action for creating example index in the app. Simply make a POST request at localhost:9000/es/index to have the index created: curl -X POST -v localhost:9000/es/index. Now inspect your indices, either by visiting kopf dashboard or by running curl -v localhost:9200/_cat/indices. You should see a new empty index called "library".

Everything that happend during this step is controller by ElasticController.scala. It uses elastic4s DSL to specify ES queries and play-elastic4s to handle configuration and injection.

The Model

It's a common practice to describe domain objects using simple case classes. Take a look at Book.scala for an example. It defines a few fields and an implicit JSON formatter on a companion object. Note that this file has nothing to do with Elasticsearch yet, and the only connection to Play is the Play JSON formatter.

The JSON formatter doesn't have to be defined on the companion object. We find it useful, because this way it's always in implicit scope when required, but feel free to define it elsewhere, e.g. in a BookJsonSupport trait that you would mix in whenever necessary.

Having such case class is enough to build a REST API with Play. Inspect the action getHardcoded in BookController.scala. It simply creates a Book instance, converts it to JSON using Play JSON helper and returns a 200 OK response. Check the results by running a curl at localhost:9000/books/hardcoded.

Integrating with Elasticsearch

The application reads and writes books to Elasticsearch using a separate class, BookDao. Its constructor has three parameters, all of which get injected (if you are new to constructor dependency injection, it's a good time to read on dependency injection in Play). This is quite standard signature when using play-elastic4s module: the ClusterSetup represents the cluster configuration specified in application.conf; the PlayElasticFactory is used to obtain ES clients, and the IndexAndType provides configuration of ES index and type.

The specific methods are implemented using ElasticDsl mixin from elastic4s DSL. Next, the PlayElasticJsonSupport mixin provides elastic4s Indexable and HitAs instances to provide automatic JSON conversions based on already defined Play JSON formatter. This way we can use the formatter defined in Book.scala to talk to Elasticsearch. Refer to play-elastic4s module page for more information on that.

Check the methods in BookController.scala to see the full life of a request in the app (the appropriate URLs for the endpoints are defined in routes file). Note how the BookDao transparently handles Elasticsearch connection: all the public methods expose only domain objects. The controller is unaware of what kind of search engine is actually backing your app - and that's a Good Thing.

For starters, populate the elasticsaerch index with a few books: curl -XPOST -v localhost:9000/books/populate. This will call the action populate() in BookController.scala, which will result in adding three books to the index. Then you can execute a search: curl -v "localhost:9000/books?q=life", which will return the two of the books that match the query "life".

Tip: say curl localhost:9000/books?q=life | json_pp to have the JSON results formatted in a human-friendly fashion.

Next

Congratulations, you now know the basics of play-elastic4s integration. As a small hands-on excercise, you could try and split the BookDao into two files to separate the interface from its implementation, and then bind the implementation using the beforementioned dependency injection in Play. As the next step we would highly recommend thinking your architecture over and preparing a data model, alongside with appropriate mappings. Elasticsearch Guide will be unvaluable in providing information on data modelling in ES, administrating the ES cluster and running queries. Then you're ready to dive deeper into the implementation. Definitely check out the elastic4s DSL homepage to learn how to express appropriate queries with the Scala DSL. Consult play-elastic4s module page for nuances regarding Play-Elasticsearch integration.

Good luck with your application!