10

Is it possible to specify dynamically (at runtime) the indexName for each @Document, for example, via a configuration file? Or is it possible to make @Document Spring environment (dev, prod) dependant?

Thank you!

David Marko
  • 2,477
  • 3
  • 27
  • 58
Dorian
  • 143
  • 1
  • 1
  • 6
  • Also need some environment / profile based solution. Index name hardwired into annotation is not best option ... – David Marko Oct 13 '15 at 07:09
  • I was trying to do the same using something similar to when you use @Value, but no luck yet. See [this question](http://stackoverflow.com/questions/31829456/inject-spel-parameter-on-annotation-parameter-like-what-is-done-with-value-on) for more info. – Victor Oct 15 '15 at 07:18
  • You cant use @Value in this way because its not a bean managed/created by Spring but by you using new MyBean() . I still cant get idea behind this annotation settings. Everybody must deal with this for example when using diffent indexName for dev and prod. How do you do this? – David Marko Oct 15 '15 at 18:05
  • @DavidMarko, at this point I am wondering if anybody reached production with spring-data-elasticsearch... Does anyone know an example? – Dorian Oct 19 '15 at 18:53

4 Answers4

25

The @Document annotation does not permit to pass the indexname in parameter directly. However I found a work around.

In my configuration class I created a Bean returning a string. In this string I injected the name of the index with @Value :

@Value("${etrali.indexname}")
private String indexName;

@Bean
public String indexName(){
    return indexName;
}

Afterward it is possible to inject the index into the @Documentation annotation like this :

@Document(indexName="#{@indexName}",type = "syslog_watcher")

It works for me, I hope it will help you.

Best regards

Bruno
  • 266
  • 3
  • 2
  • Thanks, in fact, it's the [SpEL](https://docs.spring.io/spring/docs/3.0.x/reference/expressions.html) solution – Xuanyu Apr 17 '20 at 06:04
  • Where did you register you `Bean`? I did so in the `@Configuration` annotated `ElasticsearchConfig` class. Apparently I still get an `java.lang.NoClassDefFoundError`. Any suggestions? – nonNumericalFloat Jan 25 '22 at 14:13
4

The solution from Bruno probably works but the "I created a Bean returning a string" part is a bit confusing.

Here is how I do it :

  • Have the "index.name" key valued in an application.properties file loaded by "<context:property-placeholder location="classpath:application.properties" />"

  • Create a bean named ConfigBean annotated with @Named or @Component


    @Named
    public class ConfigBean {

      @Value("${index.name}")
      private String indexName;

      public String getIndexName() {
        return indexName;
      }

      public void setIndexName(String indexName) {
        this.indexName = indexName;
      }      

    }
  • Inject the value of configBean.getIndexName() into the "@Document" annotation using Spring EL : @Document(indexName = "#{ configBean.indexName }", type = "myType")

P.S. : You may achieve the same result directly using the implicit bean "systemProperties" (something like #{ systemProperties['index.name'] }) but it didn't work for me and it's pretty hard to debug since u can't resolve systemProperties in a programmatic context (https://jira.spring.io/browse/SPR-6651)

Tristan
  • 8,733
  • 7
  • 48
  • 96
1

The Bruno's solution works but there is no need to create a new Bean in this way. What I do is:

  • create a bean annotated with @org.springframework.stereotype.Service where the index name is loaded from the database:
@Service
public class ElasticsearchIndexConfigService {

    private String elasticsearchIndexName;

    // some code to update the elasticsearchIndexName variable

    public String getIndexName() {
        return elasticsearchIndexName;
    }
}
  • call the getIndexName() method from the bean in the @Document annotation using the SpEL:
@Document(indexName = "#{@elasticsearchIndexConfigService.getIndexName()}", createIndex = false)
public class MyEntity {

}

The crucial part is to use @ - #{elasticsearchIndexConfigService.getIndexName()} won't work. I lost some time to figure this out.

Chris Ociepa
  • 694
  • 6
  • 12
0

This Worked for me
application.properties

index.prefix=test

then use this code

@Document(indexName = "#{@environment.getProperty('index.prefix')}")