Running Hibernate Search with Elasticsearch on Pivotal CF
This post has been featured on This Week in Spring – September 20, 2016 and on the Hibernate Community Newsletter 19/2016.
Two weeks ago, I wrote a post on how to use Hibernate Search with Spring Boot. The post got featured on the Hibernate community newsletter as well as on Thorbens blog Thoughts on Java.
I ended the the post saying that a downside for a fully cloud based application is the fact, that the default index provider is directory based.
Well.
There’s a solution for that, too: In upcoming Hibernate Search 5.6 there’s an integration with Elasticsearch.
I didn’t try this out with my Tweet Archive, but with the site of my JUG, which runs happily on Pivotal CF.
Goal
- Use local, directory based Lucene index during development
- Use Elastic Search integration when deployed to Pivotal CF (“The cloud”)
Steps taken
First of all, you have to add the dependencies
with hibernate-search.version
being 5.6.0.Beta2 at the moment.
The annotations at entity level are exactly the same as in my previous post, but for your convince, here’s the post entity, which I wanted to make searchable:
Again, I have configured a language discriminator at entity level with @AnalyzerDiscriminator(impl = PostLanguageDiscriminator.class)
, but we come later to this.
To make Hibernate Search use the Elastic Search integration, you have to change the index manager. In a Spring Boot application this can be done by setting the following property:
spring.jpa.properties.hibernate.search.default.indexmanager = elasticsearch |
And that’s exactly all there is to switch from a directory based, local Lucene index to Elasticsearch. If you have a local instance running, for example in doctor, everything works as before, the indexing as well as the querying.
The default host is http://127.0.0.1:9200
, but we’re not gonna use that in the cloud. Pivotal IO offers Searchly at their marketplace, providing Elastic Search. If you add this to your application, you’ll get the credentials via an URL. The endpoint then can be configured like this in Spring application.properties:
spring.jpa.properties.hibernate.search.default.elasticsearch.host = ${vcap.services.search.credentials.sslUri} |
Here I am making use of the fact that environment variables are evaluated in properties. The vcap property is automatically added by the Pivotal infrastructure and contains the mentioned secure URL. And that’s it. I have added a simple search by keyword method to my Post repository, but that I had already covered in my other post:
The actual frontend accessible through http://www.euregjug.eu/archive is nothing special, you can just browse the sources or drop me a line if you have any questions.
More interesting is the language discriminator for the posts. It looks like this:
It returns the name of the posts language. Elasticsearch offers build-in language specific analyzers, “english” and “german” are both available.
What, if I want to use a local index for testing and Elasticsearch only on deployment? I would have to define those analyzers in that profile. The right way to do it is a Hibernate @Factory
like this:
and a application-default.properties containing
spring.jpa.properties.hibernate.search.model_mapping = eu.euregjug.site.config.DefaultSearchMapping |
Recap
To use Hibernate Search with your JPA entities, basically follow the steps described here.
If you want to use named Analyzers from Elastic Search, that aren’t available for locale Lucene, add analyzers with the same name (and maybe a similar functionality as well) through a Hibernate @Factory
and configure them in application-default.properties
. If you’re at it, you may want to configure the index path into a directory which is excluded from your repo:
Relevant part of application-default.properties
:
spring.jpa.properties.hibernate.search.default.indexBase = ${user.dir}/var/default/index/ spring.jpa.properties.hibernate.search.model_mapping = eu.euregjug.site.config.DefaultSearchMapping |
In your prod properties, or in my case, in application-cloud.properties
switch from the default index manager to “elasticsearch” and also configure the endpoint:
Relevant part of application-cloud.properties
:
spring.jpa.properties.hibernate.search.default.indexmanager = elasticsearch spring.jpa.properties.hibernate.search.default.elasticsearch.host = ${vcap.services.search.credentials.sslUri} spring.jpa.properties.hibernate.search.default.elasticsearch.index_schema_management_strategy = MERGE |
Happy searching and finding 🙂