0

I am trying to apply @ConfigurationProperties annotation to get a map from application.yml file to places in code where I need it.

Here is the code I have so far:

application.yml

repository:
    type:
      big: big
      small: small
      medium: medium
    to:
     database:
      something: "STRING"

configuration.java

@Configuration
@EnableConfigurationProperties
public class SnowflakeRepositoryConfig {

        @Bean
        @ConfigurationProperties(prefix = "repository.type")
        public DatabaseTypeMapping databaseTypeMapping() {
            return new DatabaseTypeMapping();
        }
    
        public static class DatabaseTypeMapping {
            public Map<Type, Type> typeMappingMigration;
    
            public void setMapping(Map<Type, Type> typeMappingMigration) {
                this.typeMappingMigration = typeMappingMigration; }
        }

@Bean
@ConfigurationProperties(prefix = "repository.to.database")
public BrandToDatabaseProperties brandToDatabaseProperties() {
    return new BrandToDatabaseProperties();
}

public static class BrandToDatabaseProperties {
    public Map<Brand, String> mapping;

    public void setMapping(Map<Brand, String> mapping) {
        this.mapping = mapping;
    }
}

And in config file I am applying it to serviceImpl class like this:

    @Bean
    public UserDataService getUserData(BrandToDatabaseProperties brandToDatabaseProperties, DatabaseTypeMapping databaseTypeMapping){
       return new UserDataServiceImpl(brandToDatabaseProperties.mapping, databaseTypeMapping.typeMappingMigration);
    }

In serviceImpl.java class, I include it like this:

    public class UserDataServiceImpl implements UserDataService {
    
        private final Map<Type, Type> typeMappingMigration;
        private final Map<Brand, String> brandToDatabaseMapping;
    
        public UserDataServiceImpl(Map<Brand, String> brandToDatabaseMapping, Map<Type, Type> typeMappingMigration) {
this.brandToDatabaseMapping = Collections.unmodifiableMap(brandToDatabaseMapping);    
            this.typeMappingMigration = Collections.unmodifiableMap(typeMappingMigration);    
        }

When I try to start my application, I am getting the following error:

Failed to instantiate [service.UserDataService]: Factory method 'getUserData' threw exception; nested exception is java.lang.NullPointerException

What am I missing here?

user9347049
  • 1,927
  • 3
  • 27
  • 66
  • you are missing `@EnableConfigurationProperties` – Eugene Nov 03 '21 at 15:41
  • I have it on configuration class. I updated my question with it – user9347049 Nov 03 '21 at 15:42
  • 2
    `@EnableConfigurationProperties(DatabaseTypeMapping.class)`, I guess – Eugene Nov 03 '21 at 15:44
  • I added it, and now I have the following error: `No ConfigurationProperties annotation found on 'repository.SnowflakeRepositoryConfig$DatabaseTypeMapping'.` – user9347049 Nov 03 '21 at 15:47
  • 1
    `@ConfigurationProperties` is supposed to go on the class declaration. – Eugene Nov 03 '21 at 15:50
  • I updated my question. I have two configuration properties, `BrandToDatabaseProperties` was working that's why I didn't put it in my first question, but maybe there is problem because its two? They are very similar and `BrandToDatabaseProperties` is working and other `DatabaseTypeMapping` is throwing exception – user9347049 Nov 03 '21 at 16:44

1 Answers1

1

You don’t need to declare a bean of type DatabaseTypeMapping. Move the ConfigurationProperties annotation to the class, and let component scan pick it up. Alternatively, you can specify the class name in the EnableConfigurationProperties annotation.

I can’t be sure but I think ConfigurationProperties isn’t supposed to be declared on a method, it doesn’t make sense logically.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • `@ConfigurationProperties` does not get activated by component-scanning; it needs `@ECP`. It _can_ be declared on an `@Bean` if you need to map in multiple copies of the property structure. – chrylis -cautiouslyoptimistic- Nov 03 '21 at 16:17
  • @chrylis-cautiouslyoptimistic- I didn't say that `ConfigurationProperties` gets activated by component scan. On the contrary, my answer specifically mentions `EnableConfigurationProperties`. I also clearly said I wasn't sure about the usage on a method; I'm not sure what did you mean by "_multiple copies of the property structure_", but the only usage I can see if for mapping the same properties to multiple prefixes, which is somewhat contrived. – Abhijit Sarkar Nov 03 '21 at 16:28
  • I updated my question. I have two configuration properties, `BrandToDatabaseProperties` was working that's why I didn't put it in my first question, but maybe there is problem because its two? – user9347049 Nov 03 '21 at 16:45
  • You can see they are very similar and `BrandToDatabaseProperties` is working and other `DatabaseTypeMapping` is throwing exception – user9347049 Nov 03 '21 at 16:47