简体   繁体   中英

Set default value to null in Spring @Value on a java.util.Set variable

Having an interesting issue with the Spring @Value annotation using SpEL. Setting default value of null works for a String variable. However, for a Set variable it doesn't.

So, this works (varStr is null):

@Value("${var.string:#{NULL}}")
private String varStr;

while this doesn't (varSet now contains one element with "#{NULL}"):

@Value("#{'${var.set:#{NULL}}'.split(',')}")
private Set<String> varSet;

The question is how to make this work with a Set variable as well so it would be set to null by default.

Your help will be greatly appreciated.

You could try injecting the @Value into an array instead of a Set. Then in a @PostConstruct init block convert that into the desired Set instance. Spring appears to be injecting an empty array (not null) when no such property exists (note the empty default value in the @Value string). When it does exist it splits on comma by default.

Like this:

@Value("${some.prop:}")
private String[] propsArr;
private Set<String> props;

@PostConstruct
private void init() throws Exception {
    props = (propsArr.length == 0) ? null : Sets.newHashSet(propsArr);
}

I will just make one other suggestion. I recommend that you don't use null at all, but rather an empty Set instead. Null tends to be error-prone and typically doesn't convey any more info than an empty collection. Your case may well be different - this is just a general recommendation.

BTW - that Sets.newHashSet(...) call is from Google's Guava library . Highly recommended.

You can create a PropertySourcesPlaceholderConfigurer. This bean will intercept the property source values and allow you to configure them.

@Configuration
@ComponentScan
class ApplicationConfig {

@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
  PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
  c.setNullValue("");
  return c;
}

Reference: http://blog.codeleak.pl/2015/09/placeholders-support-in-value.html

Which will default an empty string to null.

Unless you can find an elegant solution to get around this, you can inject the property into your contructor as a String and then Split() it yourself or default to null .

class Foo {

    private Set<String> varSet;

    public Foo(@Value("${var.string:#{NULL}}") String varString) {
        varSet = (varString == null) ? null : new HashSet<>(Arrays.asList(varString.split(",")));
    }
}

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