Issue
Source code that reproduces the problem: link.
Suppose I have this kind of structure of configuration properties:
@Data
@ConfigurationProperties(prefix = "props")
public class ConfigProperties {
private String testString;
private Map<String, InnerConfigProperties> testMap;
}
@Data
public class InnerConfigProperties {
private String innerString;
private Integer innerInt;
}
In application.yml
I set them in this way:
props:
testString: asdadasd
somWrongProperty: asdasd
testMap:
key1:
innerString: value1
innerInt: 1
someInnerWrongProperty: wrongvalue
key2:
innerString: value2
innerInt: 2
After launching annotation processing only the simple properties work correctly (you can navigate to their declaration by clicking with ctrl
, also autocomplete for them works). Also, IDEA detects if the property is incorrect and highlights it.
For nested structures (which are map values) both of these features don't seem to work properly. You still can click on them but IDEA will navigate to the map declaration. Also, code completion for map values and highlighting of the wrong fields don't work.
Screenshot from IDEA:
Does anybody know how to make it work correctly? Feel free to use the attached example code.
Thanks in advance.
UPDATE
Seems to be fixed in Intellij IDEA 2022.1. Related issues: IDEA-151708 and IDEA-159276.
Nice bugfix productivity though.
Solution
I believe you're asking about the added
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
This is basically an annotation processor - a special hook into compilation process that can detect classes annotated with some annotation during compile time and generate some resources based on that definition.
Some annotation processor generate other source files, this one however introspects the classes annotated with @ConfigurationProperties
by reflection and based on the field names and types found in this classes it generates a special json file (META-INF/spring-configuration-metadata.json in the target
build directory).
You can open it up and see how does it look like.
Now a couple of notes on this process:
- Since it happens during the compilation - it doesn't look at
application.yaml
- The generated JSON in general is not used by spring boot itself during the runtime but intended for IDEs so that they could build some nifty integrations. That's what IntelliJ basically does.
Now, IntelliJ (Only Ultimate Edition, since community edition doesn't include any integration with spring) can indeed read this file, and provide some autocompletion features.
But Based on the information provided in the configuration properties that include Maps an annotation processor (that again runs during the compilation and has an access to the class only) merely cannot generate correct values of keys for example. So IntelliJ won't offer you to chose from key1
, key2
, since they do not exist in the configuration properties java files. That's why it doesn't work.
Bottom Line, IntelliJ is not guilty, it does the best it can :)
In terms of resolution:
There are two paths you can try:
Instead of using Strings as keys, use an enum. Since it will have a finite and well defined set of values, probably the annotation processor will generate a better json (if it doesn't - its a bug or, rather a request for enhancement, in the annotation processor)
Assuming, that the annotation processor does its best job, but not always succeeds, you can define the json manually as described in Spring Boot Documentation
Answered By - Mark Bramnik
Answer Checked By - Terry (JavaFixing Volunteer)