Hi,
in an application wie use a ConfigurationProperties class wich contains an HashMap. If this application runs as "normal" java application everything works find. But as soon as this application is build as native executable, the Hashmap is not filled anymore.
I created a test application
We used this properties class:
@Validated
@Data
@Component
@ConfigurationProperties(prefix = "test-props")
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TestProperties {
@NotEmpty
HashMap<String, PermissionsConfig> datagroups;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class PermissionsConfig {
// fields
}
}
With this application.yml
test-props:
datagroups:
data:
read:
code: READ_DATA
urlPattern:
- /some/pattern/
I added an extra hint for the native image build. Without this hint the validation does not work.
Comment From: wilkinsona
Thanks for the sample. I've reproduced the problem but exactly why it is occurring is not clear to me. I have added some map-based tests to our configuration properties smoke test and they succeed in a native image.
There is quite a lot of complexity in the sample that doesn't appear to be needed. For example, you have used Lombok which hides the details of the specific methods that each class will have. You're also using @Data, @Builder, @AllArgsConstructor, and @NoArgsConstructor. This creates confusion as it's not clear how you expect the classes to be created and the properties bound to them. For example, do you want them to be constructor bound or to use Java Bean-style binding via the setter methods? The application also has numerous dependencies that don't appear to be relevant to the problem. These unneeded dependencies add to the time to build a native image which further slows down problem diagnosis.
If you would like us to spend some more time investigating, please minimise your sample as much as possible by removing Lombok (unless the problem only occurs with Lombok and not with hand-written code) and all other unnecessary dependencies.
Comment From: sogmemu
Hi,
I solved the issue for me. It is not Lombok or all the annotations. I removed it (but testet it also with all the annotations). In my example the AOT Compiler can not detect the subclasses used within the Map. Adding all of these sub classes as hints make it work.
In your map-based test the Class used within the Map is also used within that property class directly:
private Map<String, Nested> nestedMap = new LinkedHashMap<>();
private Nested nested = new Nested();
This helps the AOT compiler. I check it with my source, too. If I would just add the Sub classes also as properties directly it would work. I'm not sure if there is any possibility to enhance that part of the native compile.
Comment From: wilkinsona
Thanks for simplifying things. I can see what's happening now.
Permission isn't nested within PermissionConfig. This means that it isn't automatically detected as a nested configuration property and that the read and history fields must be annotated with @NestedConfigurationProperty. This is described in the reference documentation. Alternatively, you could restructure your code and nest Permission within PermissionConfig.