Robust Hibernate Configuration

Hello guys,

is there a built-in way to configure the HibernateProperties with Enumeration like EngineSettings or Builders to construct the strings like hibernate.search.backends.%backendName%.index_defaults.lifecycle.strategy with the backend name as parameter ?

For example when i jumped from Alpha8 to Beta5 it took me a while to figure out the property name changed from hibernate.search.backends.%backendName%.index_defaults.lifecycle_strategy to hibernate.search.backends.%backendName%.index_defaults.lifecycle.strategy
(the underscore switched to a dot)

Thanks :wink:

Hello,

Yes.

For basic strings (default backends, backends prefix, index_defaults, etc.) and core settings (failure handler):

For settings related to the Hibernate ORM mapper (automatic indexing, …):

For settings related to the Elasticsearch backend:

For settings related to the Lucene backend:

Yeah, sorry about that… To my defense, it was mentioned in the release announcements :slight_smile: But that’s certainly annoying and, of course, we won’t do that anymore after the 6.0.0.Final release.

Thank you @yrodiere ! It’s perfectly ok for the change of property name :smiley:

In fact i was wondering if we could have builder to aggregate the fragments of the configuration (maybe i miss read something in the links you send me, sorry if it’s the case)

but if i’am right for now i have to do that

hibernateProperties.put(EngineSettings.BACKENDS + ".myBackendName." + ElasticsearchBackendSettings.VERSION_CHECK_ENABLED, "false");

wich is the equivalent to

hibernateProperties.put("hibernate.search.backends.myBackendName.version_check.enabled", "false");

maybe we could imagine something like that

ElasticsearchBackendSettings.VERSION_CHECK_ENABLED.build("myBackendName")

we know the ElasticSearch “context” so we can predict in this “enumeration” the PREFIX and filter the backend name with the parameter.

1 Like

So first, I can’t stress enough that these constants are strings, and must stay strings, because that’s the only thing that can be used from annotations.

You can’t call a method in an annotation, e.g. @TestPropertySource(properties = ElasticsearchBackendSettings.VERSION_CHECK_ENABLED.build("myBackendName") + "=false" ) simply would not compile, because the values can’t be computed.

That being said, yes, the tool you’re suggesting could be interesting. It would just have to live next to the existing constants.
I’d personally go with something that takes the strings as parameters, so as to keep things simple, e.g.:

hibernateProperties.put( BackendSettings.property( "myBackendName", ElasticsearchBackendSettings.VERSION_CHECK_ENABLED ), "false" );

I know @gsmet wanted such a tool at some point, but I don’t know if he had something specific in mind. He ended up implementing it as an internal tool in Quarkus: https://github.com/quarkusio/quarkus/blob/master/extensions/hibernate-search-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/elasticsearch/runtime/HibernateSearchConfigUtil.java

1 Like

Yeah !
Thanks for the information about the implementation for Quarkus, i was going for something like that at first and i asked myself if we could think about something inside the framework.

If you want i could work on something the way you suggest it, it sounds good to me.

That would be great! I opened https://hibernate.atlassian.net/browse/HSEARCH-3850.
@gsmet, can you confirm what’s described in this ticket matches your expectations?

Yeah, I confirm that would be useful for Quarkus and your description in the ticket looks sane.

It might be a good idea to also take into account BackendSettings.INDEX_DEFAULTS somehow.

I take the ticket then :wink: thank you guys

I have a small question about the implementation, for example in this case BackendSettings.backendKey( "myBackendName", ElasticsearchBackendSettings.VERSION ) i would like to verify if the second parameter is in of the ElasticsearchBackendSettings constant list, i think it could be nice to tell the user about a wrong configuration.

To do that with preserving the String constant way, i have two ideas

  1. Build a list of the constants Inside the ElasticsearchBackendSettings manually (some constant can be forgot in time) or with reflection in final code.
  2. An Enum with the value and the current constant pointing the correct enum Value.
class ElasticsearchBackendSettings {

   public enum ElasticsearchBackendSettingsEnum {
        TYPE_NAME("elasticsearch"),
        HOSTS("hosts"),
        PROTOCOL("protocol"),

       private String key;

      ElasticsearchBackendSettingsEnum (String key){
          this.key= key;
      }

      public String getKey() {
          return this.key;
      }  
   }
   public static final String TYPE_NAME = ElasticsearchBackendSettingsEnum .TYPE_NAME.getKey();
   public static final String HOSTS = ElasticsearchBackendSettingsEnum .HOSTS.getKey();
   public static final String PROTOCOL = ElasticsearchBackendSettingsEnum .PROTOCOL.getKey();

   public static String backendKey(String backendName, ElasticsearchBackendSettingsEnum setting) {
	// concatenate ... EngineSettings.PREFIX + backendName + setting;
   }
}

What do you think about this?

I think it goes beyond the scope of the problem as originally stated, so probably not something you’ll want to do in the same ticket.

Regarding the solutions:

  1. I agree that solution 1 is not good as we will forget a constant as some point, for sure
  2. Solution 2 prevents from using the constants as annotation values. String PROTOCOL = ElasticsearchBackendSettingsEnum .PROTOCOL.getKey(); calls some code. The compiler will detect that and will refuse to use the value of that constant in an annotation.

I’ve thought about this problem, and I personally couldn’t find a silver bullet. I suspect that any robust solution will have to rely on automatic pre-processing applied during the Hibernate Search build, and that seems a bit too much.

Back to your concern of properties being incorrect… did you know there’s a feature in Hibernate Search that warns you about properties that are set in your configuration, but are never used by Hibernate Search? This generally indicates a malformed property, or a typo. See here.

We could consider adding a strategy that fails the boot if Hibernate Search detects an unused property, instead of just logging a warning. Maybe that would solve your problem?

i didn’t knew that, i think it could be ok then :slight_smile: thanks man !

Solved here
https://hibernate.atlassian.net/browse/HSEARCH-3850

1 Like