Ways to set hibernate search credentials in helidon

Technical Jun 06, 2022
hibernate search and Helidon

Problem

To configure the hibernate search in Helidon we have to use persistence.xml or hibernate.properties but none of which supports setting/reading from environment variables.
And unlike Spring and Quarkus, Helidon does not support hibernate search as of now (version 2.5.1), which means we can’t use the application.yml and other Helidon configuration options to set the configs for hibernate search.

As you probably know we can use JVM properties to set the hibernate configuration in persistence.xml in following format:

1<property name="hibernate.search.backend.hosts" value="${SEARCH_BACKEND_URL}" /> 

At first I’ve tried to use JVM properties to pass the values from environment variables to persistence.xml:

1java -jar -DSEARCH_BACKEND_URL=$ENV_VAR_NAME MyApp.jar

Or when using Jlink image:

1ENTRYPOINT /bin/bash MyApp/bin/start --jvm -DSEARCH_BACKEND_URL=$BACKEND_SEARCH_URL

We can pass the Hibernate config directly (using JVM properties) instead of setting them in persistence.xml but that’s essentially the same approach.

Solution

But surly there must be a cleaner solution, no?
What if we read the environment variables into JVM properties and then call the main method of Helidon’s main class, this way before CDI container starts the JVM properties are already set.

Example

If we have our hibernate config (persistence.xml) in following format then we can proceed

1<property name="hibernate.search.backend.hosts" value="${SEARCH_BACKEND_URL}" /> 

Creating a configuration class (Optional)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package space.dastyar.myapp;

public class Configuration {

    public void setup() {
        hibernateSearch();
    }

    private void hibernateSearch() {

        var host = Optional.ofNullable(System.getenv("SEARCH_BACKEND_URL"));
        var protocol = Optional.ofNullable(System.getenv("APP_SEARCH_PROTOCOL"));
        var user = Optional.ofNullable(System.getenv("SEARCH_USER"));
        var password = Optional.ofNullable(System.getenv("SEARCH_PASSWORD"));

        System.setProperty("SEARCH_BACKEND_URL", host.orElse("localhost:9200"));
        System.setProperty("SEARCH_BACKEND_PROTOCOL", protocol.orElse("http"));
        System.setProperty("SEARCH_USER", user.orElse("elastic"));
        System.setProperty("SEARCH_PASSWORD", password.orElse("search_password"));
    }
}

Creating the main

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package space.dastyar.myapp;

import io.helidon.microprofile.cdi.Main;

public class App{
    
    public static void main(String[] args) {
        new Configuration().setup();
        Main.main(args);
    }
}

Note that before starting the server we don’t have dependency injection hence we have to create an instance of configuration class manually.

Adding the main class in maven’s pom.xml properties:

1
2
3
4
<properties>
    <mainClass>space.dastyar.myapp.App</mainClass>
    ....
</properties>

and that’s it.

End

Let me know what you think.