7

Ok, so i have a config.properties ..:

market.curpairs[0].name=EuroDollar
market.curpairs[0].symbol=EURUSD
market.curpairs[0].minamount=0.1
market.curpairs[1].name=EuroFranken
market.curpairs[1].symbol=EURCHF
market.curpairs[1].minamount=0.1
market.currs[0].name=Euro
market.currs[0].symbol=EUR
market.currs[0].minamount=1.0
market.currs[0].withfee=0.1
market.currs[1].name=Dollar
market.currs[1].symbol=USD
market.currs[1].minamount=1.0
market.currs[1].withfee=0.1
market.currs[2].name=Franken
market.currs[2].symbol=CHF
market.currs[2].minamount=1.0
market.currs[2].withfee=0.1

which i then attempt to inject into MarketConfig.java like this:

@PropertySource("classpath:config.properties")
@ConfigurationProperties(prefix = "market")
@Validated
public class MarketConfig {

    // the configured currencies
    private List<MarketCurrency> currs;

    // the configured currencypairs
    private List<MarketCurrencypair> curpairs;

  /* static classes */
  public static class MarketCurrency {
    String name;
    String symbol;
    double minamount;
    // getter and setter ommitted
  }
  public static class MarketCurrencypair {
    String name;
    String symbol;
    double minamount;
    double withfee;
    // getter and setter ommitted
  }
  // getter and setter ommitted
}

..which then is used in MarketService.java:

 @Service
    public class MarketService implements IMarketService {

        private final MarketConfig config;

        // ....

         public MarketService(MarketConfig config) {
            this.config = config;
         }
        // ....
        public void printConfig() {
           System.out.println("________________ CONFIGURATION: ");
           this.config.getCurpairs().forEach(System.out::println);
           this.config.getCurrs().forEach(System.out::println);
        }
    }

...which is called by the Applicationmain:

@SpringBootApplication
@EnableSwagger2
@ComponentScan
@EnableConfigurationProperties({MarketConfig.class})
public class MarketApplication implements CommandLineRunner {

    private final MarketService service;

    /**
     * Constructor
     * @param service  ..the Service
     */
    public MarketApplication(MarketService service) {
        this.service = service;
    }

    public static void main(String[] args) {
        SpringApplication.run(MarketApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        this.service.printConfig();
    }
}

...yielding me NullPointerException

Caused by: java.lang.NullPointerException: null
    at forex.market.service.MarketService.printConfig(MarketService.java:67) ~[classes/:na]

Q1: Am i doing it right, basically?

Q2: I couldn't find any help on the internet how to handle arrays of primitive-tuples in properties files, is it even possible to inject that into a spring-boot configuration - or do i need to rewrite my config to strings, using split() to acquire the individual values (which i really don't want to for the sake of maintainability and readability) ?

Thanks in advance - if you miss out some information/source, please comment, i will supply it shortly.

Gewure
  • 1,208
  • 18
  • 31

1 Answers1

3

you need to set your property-prefix don't need @Configuration and @Component and use embedded public static class to wrap properties of the currency

 @PropertySource("classpath:config.properties")
 @ConfigurationProperties(prefix = "market")
 @Validated
 public class MarketConfig {
      List<MarketCurrency> currs;
      //getters setters

      public static class MarketCurrency {

          String name;
          String symbol;
        ....
//getters setters

add MarketConfig.class to @EnableConfigurationProperties

 @SpringBootApplication
 @EnableSwagger2
 @EnableConfigurationProperties({MarketConfig.class})
 public class MarketApplication implements CommandLineRunner {

    private final MarketService service;
    private final MarketConfig config;

    public MarketApplication(MarketService service, MarketConfig config) {
       this.service = service;
       this.config = config;
    }
Gewure
  • 1,208
  • 18
  • 31
Dirk Deyne
  • 6,048
  • 1
  • 15
  • 32
  • Hm... this brings me to: BeanCreationException: Error creating bean with name 'marketConfig': Could not bind properties to MarketConfig (prefix=market, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE] – Gewure May 04 '18 at 17:21
  • good points @DirkDeyne, updated the source & question, but still it points to null. – Gewure May 04 '18 at 17:46
  • 1
    updated answer List should be something like List – Dirk Deyne May 04 '18 at 17:52
  • Still NullPointerException. Seems like i cannot inject from config.properties, my IDE also shows me the file content as not used. Did i miss out something about application.config? do i need to declare additional config files somewhere? – Gewure May 04 '18 at 18:05
  • 1
    is config.properties in _/src/main/resources/_ ? – Dirk Deyne May 04 '18 at 18:09
  • yes, all .properties (application.properties, config.properties) are in /src/main/resources – Gewure May 04 '18 at 18:12
  • 1
    edited answer: MarketConfig should be in MarketApplication – Dirk Deyne May 04 '18 at 18:19
  • you mean inside, as inner class? – Gewure May 04 '18 at 18:21
  • it still NullPoints... Thanks for all that hints and time though. Made me understand the matter alot better! – Gewure May 04 '18 at 18:42
  • MarketConfig in MarketService does not cause nullpointer... I guess one off you properties in MarketConfig is null – Dirk Deyne May 04 '18 at 19:01
  • No, definitely no null-vslue in the config. Did i miss out some @Bean annotation anywhere? – Gewure May 05 '18 at 17:12
  • 2
    have a look here [demo](https://github.com/dirkdeyne/properties) Don't get a nullpoiter here... – Dirk Deyne May 05 '18 at 18:20