Consider the following class:
public class ExpressionTokenClassifier {
private static final String PROMQL_KEYWORDS = "promql-keywords.json";
private static final List<String> KEYWORDS;
static {
List<PromQLKeyword> words = KeywordsExtractor.extractKeywords(PROMQL_KEYWORDS);
KEYWORDS = words.stream().map(PromQLKeyword::getName).collect(Collectors.toList());
}
public static void classifyTokens(List<ExpressionToken> tokens) {
... // KEYWORDS is used in here
}
}
Notice the hardwired file name (PROMQL_KEYWORDS) specified and used in the static initialization block. This works, but I would like to remove the hardcoded value and instead use dependency injection (Spring) to set the value from application.yaml. This class is intended to only be used statically.
My research indicates that the Spring framework does not allow setting a static field with the @Value annotation. I have seen some suggestions of a workaround, but do not understand how they would work. Here is an example where I attempted to do this:
@Component
public class ExpressionTokenClassifier2 {
private static final List<String> KEYWORDS;
private static String KEYWORDS_FILE;
@Value("${app.keywords-file}")
public void setKeywordsFileName(String name) {
KEYWORDS_FILE = name;
}
static {
List<PromQLKeyword> words = KeywordsExtractor.extractKeywords(KEYWORDS_FILE);
KEYWORDS = words.stream().map(PromQLKeyword::getName).collect(Collectors.toList());
}
public static void classifyTokens(List<ExpressionToken> tokens) {
... // KEYWORDS is used in here
}
}
When I tried it, the application fails to start because of NPE (KEYWORDS_FILE is null). My immediate question is: Where and when would the setKeywordsFileName() method be called? Nowhere, as far as I can tell - and the results agree. Am I missing some logic?
Does anyone know of a way to accomplish this? I could change this class so that it's instantiated instead of statically accessed, but the class that uses this class is also a statically accessed class. I really don't want to have to change a bunch of code to fix this.
UPDATE:
Upon further investigation, it appears that this is essentially not doable, at least not without a lot of extra work that probably defeats the purpose. This link, to me, describes the situation quite well.
How to assign a value from application.properties to a static variable?
Looks like I'm going to have to think about this for awhile.