I wanted to know if there is a way to check and validate a field when using the CsvRoutines package. Basically I want to process a row if the first column has only numbers and skip/possibly throw an exception otherwise. I'm guessing @Validate annotation released in 2.7.0 can be used to achieve this. But I would like to know if there is any other way to achieve the same with earlier versions like 2.5.9?
1 Answers
Author of the library here. There's no other way other than updating to the latest version. Is there any reason in particular why you can't upgrade?
Update: you can put the @Parsed
annotations on the class' getters or setters and perform the validations in them. That is probably the cleanest way to go about it. For example:
class Test {
private Integer number;
//accepts a String here... so this is straight from the parser before it tries to convert anything into an integer - which lets you validate or throw a custom exception
@Parsed
void setNumber(String number){
try{
this.number = Integer.valueOf(number);
} catch(NumberFormatException e){
throw new IllegalArgumentException(number + " is not a valid integer");
}
}
}
Another alternative is to use a custom conversion class. Copy the code of class ValidatedConversion, used in the newest version, then create subclass like:
public static class RangeLimiter extends ValidatedConversion {
int min;
int max;
public RangeLimiter(String[] args) {
super(false, false); //not null, not blank
min = Integer.parseInt(args[0]);
max = Integer.parseInt(args[1]);
}
protected void validate(Object value) {
super.validate(value); //runs the existing validations for not null and not blank
int v = ((Number) value).intValue();
if (v < min || v > max) {
throw new DataValidationException("out of range: " + min + " >= " + value + " <=" + max);
}
}
}
Now on your code, use this:
@Parsed(field = "number")
@Convert(conversionClass = RangeLimiter.class, args = {"1", "10"}) //min = 1, max = 10
public int number;
I didn't test this against an old version. I think you may need to set flag applyDefaultConversion=false
in the @Parsed
annotation, and make your conversion class convert a String
into an int
in addition to run the validations.
All in all, that's quite a bit of work that can easily be avoided just by upgrading to the latest version.

- 6,141
- 2
- 25
- 29
-
Thanks for the response. Need to use it for prod environments in my company. I'm kind of in time crunch here. Typically these upgrades to third party tools need to go through some reviews. I currently have managed to achieve something similar by creating a custom row processor and doing the validations in rowProcessed. Are there any pitfalls to look out for in this approach? The only pain in this approach was to check the context headers to make sure I get the right indices for the columns I am looking for. – user2220232 Sep 21 '18 at 22:15
-
Turns out the custom processor does not work. We use CsvRoutines which internally creates its own BeanProcessor. So setting the processor in CsvParserSettings is useless. I guess I will have to use @Parsed like you suggested. Could you let me know the arguments to pass in the Annotation to check if the field has just numeric values? – user2220232 Sep 22 '18 at 00:30
-
I added examples, hope it helps. – Jeronimo Backes Sep 26 '18 at 04:29