简体   繁体   中英

spring batch - how to reference bean properties in XML

I'm developing several Spring Batch applications that create flat files from mapped result set objects with large numbers of columns.

Coding the the Field Extactor's "names" property and the Line Aggregators's "format" property in xml is cumbersome and error prone, so I've built a component that hold a list of fields and has a public method to return a String array of field names and another public method to return the all the format specifiers as a string. Here are simplified examples:

public class Field {
    private String fieldName;   // e.g., "firstName"
    private String format;      // e.g., "%-16s"
    // getters/setters omitted here
}

@component
public abstract class FieldList extends ArrayList {
    public FieldList () {
    }
    public String[] getFieldNameArray() {
        ArrayList<String> names = new ArrayList<String>();
        for (int i = 0; i < this.size(); i++) {
            names.add(this.get(i).getFieldName());
        }
        return (String[]) names.toArray(); 
    }
    public String getFormatStrings() {
        StringBuffer sb = new StringBuffer ();
        for (int i = 0; i < this.size(); i++) {
            sb.appeng(this.get(i).getFormat());
        }
        return (String[]) names.toArray(); 
    }
}

@Component
public class EmployeeFieldList extends FieldList {
    public EmployeeFieldList () {
        super();
        this.add(new Field("empId",    "%-8s"));
        this.add(new Field("firstName","%-16s"));
        // etc., etc. Some classes have 50+ fields 
    }
}

In the XML configuration I have:

<bean id="employeeFieldList" class="com.stuff.EmployeeFieldList" />

<bean id="employeeFileItemWriter" 
    class="o.s.b.item.file.FlatFileItemWriter" >
    <property  name="resource" value="file:${strRunFileName}" /> 
    <property  name="lineAggregator">
        <bean class="o.s.b.item.file.transform.FormatterLineAggregator" 
            <property name="fieldExtractor">
                <bean  
            class="o.s.b.item.file.transform.BeanWrapperFieldExtractor"
                    <property name="names" ref="fieldNameArray" />
                </bean>
            </property >
            <property name="format" ref="formatStrings" />
        </bean>                             
    </property >
</bean>

The component conforms to the javabean api, so once I define the component in xml I should be able to reference its public members as well, right?

However this doesn't work. In the log I see this:

Error creating bean with name 
'o.s.b.item.file.transform.BeanWrapperFieldExtractor#60cbf9bd' 

defined in class path resource [spring/module-context.xml]: 

Cannot resolve reference to bean 'fieldNameArray' while setting bean 
property 'names'; 

nested exception is o.s.b.factory.NoSuchBeanDefinitionException: 

**No bean named 'fieldNameArray' is defined**

I've tried applying several notational conventions but still get the error, so it appears references may only be made to beans, not their public properties. Or am I missing something?

Correct. Spring's ref attribute refers to a bean id .

That being said, I'd actually recommend a slightly different approach. Instead of creating a component that returns a String of names, I'd recommend creating a FactoryBean for your FieldExtractor . That can be used to encapsulate the creation of the BeanWrapperFieldExtractor configured as you want.

An example would look something like this:

public class ComplexBeanWrapperFieldExtractorFactory implements FactoryBean<FieldExtractor> {
  public FieldExtractor getObject() {
    // put logic here to generate your string
    // put your logic here to actually create an instance of a BeanWrapperFieldExtractor configured as you need
    // return the instance you just created.
  }
}

With the above code, you can configure your reader as follows:

<bean id="fieldExtractorFactory" class="ComplexBeanWrapperFieldExtractorFactory/>

<bean id="employeeFileItemWriter" 
    class="o.s.b.item.file.FlatFileItemWriter" >
    <property  name="resource" value="file:${strRunFileName}" /> 
    <property  name="lineAggregator">
        <bean class="o.s.b.item.file.transform.FormatterLineAggregator" 
            <property name="fieldExtractor" ref="fieldExtractorFactory"/>
            <property name="format" ref="formatStrings" />
        </bean>                             
    </property >
</bean>

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