I am currently using Spring batch for reading a file. There is a possibility that certain columns in my file may have empty values. For example, a row in my file may look like this :
110045,,,50000
Here, column 2 and 3 have empty values. Column 2 will be mapped to a double and column 3 will be mapped to a char in my domain object. The FieldSetMapper
will be implemented as follows :
public class MyFieldSetMapper implements FieldSetMapper<SomeDomain> {
public SomeDomain mapFieldSet(FieldSet fs) {
final SomeDomain someDomain = new SomeDomain();
someDomain.setAmount(fs.readDouble(1));
someDomain.setIndividualFlag(fs.readChar(2));
someDomain.setBalance(fs.readInt(3,0));
return someDomain;
}
}
The FieldSetMapper
implementation above will result in an exception at runtime because an empty String
cannot be convered to a double or a character.
While a FieldSet
has methods such as readBigDecimal(int,BigDecimal)
or readInt(int,int)
that allow you to specify a default value if a string can't be parsed to a particular type, it does not provide similar methods for char
or double
. I am not sure what was the motivation behind leaving the defaulting options out for char
and double
types.
What I need is a way to provide a default value for char
and double
datatypes in a FieldSetMapper
per field. That is, I don't want to define a global strategy for defaulting char
and double
datatypes but I want to be able to default these types just like I can default an int
or a BigDecimal
.
I thought of using a FieldSetFactory
to plugin a custom FieldSet
implementation that extends DefaultFieldSet
and provides two more methods namely readDouble(int,double)
and readChar(int,char)
public class CustomFieldSet extends DefaultFieldSet {
public CustomFieldSet(String[] tokens, String[] names) {
super(tokens, names);
}
public CustomFieldSet(String[] tokens) {
super(tokens);
}
public char readChar(int index, char defaultValue) {
String value = readAndTrim(index);
return StringUtils.hasLength(value) ? value.charAt(0) : defaultValue;
}
public int readChar(String name, char defaultValue) {
return readChar(indexOf(name), defaultValue);
}
}
I could then cast the FieldSet
argument that the mapFieldSet
method takes into a CustomFieldSet
implementation
public class MyFieldSetMapper implements FieldSetMapper<SomeDomain> {
public SomeDomain mapFieldSet(FieldSet fs) {
CustomFieldSet cs = (CustomFieldSet)fs;
final SomeDomain someDomain = new SomeDomain();
someDomain.setAmount(cs.readDouble(1));
someDomain.setIndividualFlag(cs.readChar(2,'\0'));
someDomain.setBalance(cs.readInt(3,0));
return someDomain;
}
}
This somehow doesn't feel like the right thing to do even though it integrates seamlessly with the spring batch FieldSet
API.,
What are my options if I want to default char
and double
types in an elegant way rather than reading them as String
, checking if they are not empty and converting them to the specific type manually.