I am trying to validate some fields of User
with Validator
. I am not able to catch the error in ItemProcessListener
.
My validator is like so.
public class UserValidator implements Validator<User> {
@Override
public void validate(User user) throws ValidationException {
if (user.getName().length() > 3) {
throw new ValidationException("User name cannot have more than 3 alphabets");
}
}
}
I have Skiplistener
like so..
public class UserValidationListener implements SkipListener<User, User> {
@Override
public void onSkipInRead(Throwable throwable) {
System.out.println(throwable.getMessage());
}
@Override
public void onSkipInWrite(User user, Throwable throwable) {
System.out.println(user.toString());
System.out.println(throwable.getMessage());
}
@Override
public void onSkipInProcess(User user, Throwable throwable) {
System.out.println(user.toString());
System.out.println(throwable.getMessage());
// No error message comes here
// 1. get the error message thrown by Validation exception
// 2. Save it db logic
}
}
In the batch job config I have created a bean to filter out the faulty user data.
@Bean
public ValidatingItemProcessor<User> validatingItemProcessor() {
ValidatingItemProcessor<User> itemProcessor = new ValidatingItemProcessor<>(new UserValidator());
itemProcessor.setFilter(true);
return itemProcessor;
}
And finally here is my batch job config.
Step step = stepBuilderFactory.get("ETL-file-load")
.<User, User>chunk(100)
.reader(itemReader)
.processor(validatingItemProcessor())
.writer(itemWriter)
.faultTolerant()
.skip(ValidationException.class)
.listener(userValidationListener())
.build();
return jobBuilderFactory.get("ETL-Load")
.incrementer(new RunIdIncrementer())
.start(step)
.build();
I have created a bean for listener like so:
@Bean
public UserValidationListener userValidationListener() {
return new UserValidationListener();
}
I am not able to catch the error message thrown by the UserValidator
with ValidationException
. How do I do that?
CodePudding user response:
Here's an example that skips odd numbers and writes even numbers, hopefully this will help you
import org.springframework.batch.core.Job;
import org.springframework.batch.core.SkipListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.step.skip.SkipPolicy;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.item.validator.ValidatingItemProcessor;
import org.springframework.batch.item.validator.ValidationException;
import org.springframework.batch.item.validator.Validator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
@Configuration
@EnableBatchProcessing
public class SimpleJobConfig {
@Bean
public Job simpleJob(JobBuilderFactory jobBuilderFactory) {
return jobBuilderFactory.get("SimpleJob")
.start(simpleJobStep(null))
.build();
}
@Bean
public Step simpleJobStep(StepBuilderFactory stepBuilderFactory) {
return stepBuilderFactory.get("simpleJobStep")
.<Integer, Integer>chunk(1)
.reader(integerReader())
.processor(validatingItemProcessor())
.writer(integerWriter())
.faultTolerant()
.skipPolicy(skipPolicy())
.listener(skipListener())
.build();
}
@Bean
public ItemReader<Integer> integerReader() {
return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
@Bean
public ValidatingItemProcessor<Integer> validatingItemProcessor() {
return new ValidatingItemProcessor<>(evenNumberValidator());
}
@Bean
public ItemWriter<Integer> integerWriter() {
return items -> items.forEach(item -> System.out.println("Writing " item));
}
public Validator<Integer> evenNumberValidator() {
return value -> {
if (value % 2 != 0) {
throw new ValidationException("Odd number invalid");
}
};
}
public SkipPolicy skipPolicy() {
return (t, skipCount) -> t instanceof ValidationException;
}
public SkipListener<Integer, Integer> skipListener() {
return new SkipListener<Integer, Integer>() {
@Override
public void onSkipInRead(Throwable t) {}
@Override
public void onSkipInWrite(Integer item, Throwable t) {}
@Override
public void onSkipInProcess(Integer item, Throwable t) {
System.out.println("Skipped " item " - " t.getMessage());
}
};
}
}
Output from job is
Skipped 1 - Odd number invalid
Writing 2
Skipped 3 - Odd number invalid
Writing 4
Skipped 5 - Odd number invalid
Writing 6
Skipped 7 - Odd number invalid
Writing 8
Skipped 9 - Odd number invalid
Writing 10
CodePudding user response:
Items that fail validation will be skipped so you need to add a SkipListener and declare ValidationException as skippable in your step