У меня есть требование ежедневно обрабатывать список большого количества пользователей, чтобы отправлять им уведомления по электронной почте и SMS на основе некоторого сценария. Для этого я использую модель пакетной обработки Java EE. Моя работа xml выглядит следующим образом:
<step id="sendNotification">
<chunk item-count="10" retry-limit="3">
<reader ref="myItemReader"></reader>
<processor ref="myItemProcessor"></processor>
<writer ref="myItemWriter"></writer>
<retryable-exception-classes>
<include class="java.lang.IllegalArgumentException"/>
</retryable-exception-classes>
</chunk>
</step>
Метод MyItemReader onOpen считывает всех пользователей из базы данных, а readItem() считывает по одному пользователю за раз, используя итератор списка. В myItemProcessor фактическое уведомление по электронной почте отправляется пользователю, а затем пользователи сохраняются в базе данных в классе myItemWriter для этого фрагмента.
@Named
public class MyItemReader extends AbstractItemReader {
private Iterator<User> iterator = null;
private User lastUser;
@Inject
private MyService service;
@Override
public void open(Serializable checkpoint) throws Exception {
super.open(checkpoint);
List<User> users = service.getUsers();
iterator = users.iterator();
if(checkpoint != null) {
User checkpointUser = (User) checkpoint;
System.out.println("Checkpoint Found: " + checkpointUser.getUserId());
while(iterator.hasNext() && !iterator.next().getUserId().equals(checkpointUser.getUserId())) {
System.out.println("skipping already read users ... ");
}
}
}
@Override
public Object readItem() throws Exception {
User user=null;
if(iterator.hasNext()) {
user = iterator.next();
lastUser = user;
}
return user;
}
@Override
public Serializable checkpointInfo() throws Exception {
return lastUser;
}
}
Моя проблема в том, что контрольная точка хранит последнюю запись, которая была выполнена в предыдущем фрагменте. Если у меня есть чанк со следующими 10 пользователями, и в myItemProcessor 5-го пользователя возникает исключение, то при повторной попытке будет выполнен весь чанк, и все 10 пользователей будут обработаны снова. Я не хочу, чтобы уведомление снова отправлялось уже обработанным пользователям.
Есть ли способ справиться с этим? Как это должно быть сделано эффективно?
Любая помощь будет высоко оценен. Спасибо.