27

I've been searching but cannot find these steps. I hope I'm missing something obvious.

I have a properties file with the following contents:

machines=A,B

I have another file like that but having a different number of members in the machines element like this:

machines=B,C,D

My question is how do I load this variable-length machines variable into a bean in my spring config in a generic way?

something like this:

<property name="machines" value="${machines}"/>

where machines is an array or list in my java code. I can define it however I want if I can figure out how to do this.

Basically I'd rather have spring do the parsing and stick each value into a list element instead of me having to write something that reads in the full machines string and do the parsing myself (with the comma delimiter) to put each value into an array or list. Is there an easy way to do this that I'm missing?

skaffman
  • 398,947
  • 96
  • 818
  • 769
bob
  • 273
  • 1
  • 3
  • 4
  • It's really not hard to do `"B,C,D".split(",")`, is it? – skaffman Mar 11 '11 at 14:52
  • 2
    Its not hard, but for maintenance, Busines analysts can change a configuration property betten than code if it requires to ever be changed. – will824 Mar 15 '12 at 02:14

5 Answers5

31

You may want to take a look at Spring's StringUtils class. It has a number of useful methods to convert a comma separated list to a Set or a String array. You can use any of these utility methods, using Spring's factory-method framework, to inject a parsed value into your bean. Here is an example:

<property name="machines">
    <bean class="org.springframework.util.StringUtils" factory-method="commaDelimitedListToSet">
        <constructor-arg type="java.lang.String" value="${machines}"/>
    </bean>
</property>

In this example, the value for 'machines' is loaded from the properties file.

If an existing utility method does not meet your needs, it is pretty straightforward to create your own. This technique allows you to execute any static utility method.

Kris Babic
  • 6,254
  • 1
  • 29
  • 18
19

Spring EL makes easier. Java:

List <String> machines;

Context:

<property name="machines" value="#{T(java.util.Arrays).asList('${machines}')}"/>
Jingyang Peng
  • 191
  • 1
  • 2
  • Very interesting. DId not know Spring allowed this Kind of things. I am not a fan of Spring, but the more I use it the more powerful I realize it is. – will824 Mar 15 '12 at 02:13
  • is there a way to do this through annotations? and also, how can we provide defaults? – verma Sep 09 '13 at 20:10
16

If you make the property "machines" a String array, then spring will do it automatically for you

machines=B,C,D

<property name="machines" value="${machines}"/>

public void setMachines(String[] test) {
Simon Gibbs
  • 4,737
  • 6
  • 50
  • 80
  • This was definitely my preffered and the easiest method. Thanks @Simon – will824 Mar 15 '12 at 02:12
  • This works great if setMachines() is declared to take a collection of Strings, but doesn't work with spring's built-in PropertyEditors. That is, it wont work for setMachines(URL) or setMachines(File) (Which does work for single values). – James Scriven Jan 27 '14 at 15:07
4

Since Spring 3.0, it is also possible to read in the list of values using the @Value annotation.

Property file:

machines=B,C,D

Java code:

import org.springframework.beans.factory.annotation.Value;

@Value("#{'${machines}'.split(',')}")
private List<String> machines;
DAMungra
  • 71
  • 4
0

You can inject the values to the list directly without boilerplate code.(Spring 3.1+)

@Value("${machines}")
private List<String> machines;

for the key "machines=B,C,D" in the properties file by creating following two instance in your configuration.

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean 
public ConversionService conversionService() {
    return new DefaultConversionService();
}

Those will cover all the separate based split and whitespace trim as well.

wonhee
  • 1,581
  • 1
  • 14
  • 24