简体   繁体   中英

Micronaut: How do I map all the properties values in HashMap?

I have been learning micronaut for sake of learning and for a small scale project and I have been stuck on a problem.

So assume I have this data in application.yml file

output:
    -file:
        name: PDF
        size: 50000
    -file:
        name: DOCX
        size: 35000

So my goal was to map this exact data in HashMap which I can use further. I want my code to have all the data independent of any condition. If I add another file type it should automatically map data for that too. So in a nutshell at the end I want to have a Map<name, path> with all the values available in yaml. I tried with EachProperty.

https://guides.micronaut.io/micronaut-configuration/guide/index.html#eachProperty but I'd have to pass 'name' as argument.

Any help is much appreciated.

The micronaut @EachProperty allows to drive Bean (s) creation out of application properties, thus it will create beans ( Singleton POJOs) with properties derived from the nested configuration key / values.

An important note to take into consideration when using @EachProperty configuration is that it only binds to a top level configuration key ie and that the created beans will be named after the nested top higher property which then should be unique.

Your configuration then won't work unless changed to the following:

output:
  # Below config will drive a bean named "pdf", more details below
  pdf:
    size: 50000
  # Below config will drive a bean named "docx"
  docx:
    size: 35000

Note that in above configuration, the name attribute is omitted as it can be derived from the bean configured name itself:

@EachProperty(value = "output")
public class FileType {

    private String name;

    private int size;

    public FileType(@Parameter("name") String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        return "FileType{" +
                "name='" + name + '\'' +
                ", size=" + size +
                '}';
    }
}

The FileType constructor will have the configured bean name (derived from the configuration key) injected and the above type will produce two bean at application runtime:

FileType{name='pdf', size=50000} FileType{name='docx', size=35000}

As those beans are already handled by the micronaut core container, you can have them injected into any other bean.

Otherwise, if you wish to have your beans mapped to a particular configuration format such as a Map [NAME -> SIZE] , you can:

  1. Create another Singleton bean as a configuration wrapper
  2. Inject the FileType beans
  3. Map the injected FileType beans to your custom format
  4. Make this custom format accessible your configuration wrapper

Here down a sample configuration wrapper:

@Singleton
public class FileTypeConfiguration {

    private final Map<String, Integer> fileTypes;

    @Inject
    public FileTypeConfiguration(List<FileType> fileTypes) {
        this.fileTypes = fileTypes.stream()
                .collect(
                        Collectors.toMap(FileType::getName, FileType::getSize)
                );
    }

    public Map<String, Integer> getFileTypes() {
        return fileTypes;
    }
}

where you have your configuration accessed through FileTypeConfiguration#getFileTypes ( FileTypeConfiguration must be @Inject ed or accessed through ApplicationContext ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM