37

I have a Spring @Configuration annotated class, MappingsClientConfig, with a boolean field as:

 @Value("${mappings.enabled:true}")
 private boolean mappingsEnabled;

This class is imported into another Spring annotated class like so :

@Configuration
@Import(MappingsClientConfig.class)
public class LookupManagerConfig {

When instantiating the class via Spring context in a test-case, the container is unable to parse the string into the boolean field mappingsEnabled and I get:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private boolean com.barcap.tcw.mappings.economic.client.config.EconomicMappingsClientConfig.economicMappingsEnabled; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'boolean'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [${mappings.enabled:true}]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
    ... 138 more
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'boolean'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [${mappings.enabled:true}]
    at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:61)
    at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:43)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:718)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
    ... 140 more
Caused by: java.lang.IllegalArgumentException: Invalid boolean value [${mappings.enabled:true}]
    at org.springframework.beans.propertyeditors.CustomBooleanEditor.setAsText(CustomBooleanEditor.java:124)
    at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:416)
    at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:388)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:157)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:93)
    at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:49)
    ... 144 more

Any leads as to what am I missing?

t0r0X
  • 4,212
  • 1
  • 38
  • 34
212
  • 915
  • 3
  • 9
  • 19
  • I think the problem is caused by the fact that you are not loading the properties file where you defined `mappings.enabled`, but i can't be sure without more details. – AxxA Osiris Nov 27 '12 at 13:54

4 Answers4

70

Its an old thread but if you still want to inject Non-String values using @Value Spring annotation, do this:

@Value("#{new Boolean('${item.priceFactor}')}")
private Boolean itemFactorBoolean;

@Value("#{new Integer('${item.priceFactor}')}")
private Integer itemFactorInteger;

Works for me on Spring boot 1.5.9 with Java 8.

realPK
  • 2,630
  • 29
  • 22
7

Looks like you're missing the PropertyPlaceholderConfigurer. You need to register it as a bean factory post processor. Theoretically this could be done like this:

public class PostProcessorConfig {

    @Bean
    public BeanFactoryPostProcessor getPP() {
       PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
       configurer.setLocations(new Resource[]{new ClassPathResource("/my.properties")});
       return configurer;
    }
}

However, there seems to be a bug that causes other issues doing this from a java based configuration. See ticket for workarounds.

Stefan Podkowinski
  • 5,206
  • 1
  • 20
  • 25
  • 1
    Adding the PropertyPlaceholderConfigurer did the trick. But initially when I tried to define a new PropertyPlaceholderConfigurer, I was getting errors for missing placeholders that worked fine before. As if defining the new PropertyPlaceholderConfigurer was overriding some existing behaviour. So for now, I have defined a new PPC and added all my properties to a single propeties file loaded by it. But the question remains where were those properties being loaded from before ? – 212 Nov 28 '12 at 05:15
2

This is how it was solved in our project, as the other answers didn't work for us. We were using spring batch, also.

main job config:

@Configuration
@EnableBatchProcessing
@PropertySource("classpath:application.properties")
public class MainJobConfiguration {
    @Autowired
    PipelineConfig config;

    @Bean
    public PipelineConfig pipelineConfig(){
        return new PipelineConfig();
    }

    // To resolve ${} in @Value
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    // job stuff ...
}

properties config loader:

public class PipelineConfig {
    @Value("${option}")
    private boolean option;
}

Note how the @Value is in the PipelineConfig, but the actual properties from which the option is loaded, is specified in the job class.

jmmut
  • 884
  • 9
  • 19
1

You even do not need a properties file, e.g.:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
  • 1
    Could you clarify where goes that line? In the xml of LookupManagerConfig? If I understood well, should it be equivalent to add `@Autowired PropertyPlaceholderConfigurer configurer;` in LookupManagerConfig to use java config? – jmmut Oct 15 '15 at 09:45
  • @jmmut obviously it would be applicationContext.xml ! – positivecrux Aug 26 '16 at 07:21