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.