странное поведение в весеннем пакете о реализации политики пропуска

У меня есть весенняя пакетная программа.

Предел пропуска установлен на 5, а размер блока - 1000.

У меня есть работа, состоящая из двух этапов, как показано ниже:

    <step id="myFileGenerator" next="myReportGenerator">
        <tasklet transaction-manager="jobRepository-transactionManager">
            <chunk reader="myItemReader" processor="myItemProcessor" writer="myItemWriter"  commit-interval="1000" skip-policy="skipPolicy"/>
        </tasklet>
        <listeners>
            <listener ref="mySkipListener"/>
        </listeners>
    </step>

    <step id="myReportGenerator">
        <tasklet ref="myReportTasklet" transaction-manager="jobRepository-transactionManager"/>
    </step> 

Политика пропуска приведена ниже:

<beans:bean id="skipPolicy" class="com.myPackage.util.Skip_Policy">
    <beans:property name="skipLimit" value="5"/>
</beans:bean>

Класс SkipPolicy выглядит следующим образом:

public class Skip_Policy implements SkipPolicy {

private int skipLimit;

public void setSkipLimit(final int skipLimit) {
    this.skipLimit = skipLimit;
}

public boolean shouldSkip(final Throwable t, final int skipCount) throws SkipLimitExceededException {

    if (skipCount < this.skipLimit) {
        return true;
    }
    return false;
}
}

Таким образом, для любой ошибки, возникающей до того, как будет достигнут предел пропуска, политика пропуска проигнорирует ошибку (вернет истину). Задание завершится ошибкой из-за любой ошибки после достижения предела пропусков.

Класс mySkipListener выглядит следующим образом:

public class mySkipListener implements SkipListener<MyItem, MyItem> {

public void onSkipInProcess(final MyItem item, final Throwable t) {
    // TODO Auto-generated method stub
    System.out.println("Skipped details during PROCESS is: " + t.getMessage());
}

public void onSkipInRead(final Throwable t) {

    System.out.println("Skipped details during READ is: " + t.getMessage());
}

public void onSkipInWrite(final MyItem item, final Throwable t) {
    // TODO Auto-generated method stub
    System.out.println("Skipped details during WRITE is: " + t.getMessage());
}
}

Теперь в myItemProcessor у меня есть блок кода ниже:

if (item.getTheNumber().charAt(4) == '-') {
        item.setProductNumber(item.getTheNumber().substring(0, 3));
    } else {
        item.setProductNumber("55");
    }

Для некоторых элементов полеNumber имеет значение NULL, поэтому приведенный выше блок кода вызывает исключение StringIndexOutofBounds.

Но я наблюдаю странное поведение и не понимаю, почему это происходит.

Всего есть 6 элементов, у которых есть ошибка, то есть поле Number имеет значение NULL.

Если предел пропуска превышает количество ошибок (т. Е.> 6), вызываются системные выходы в классе прослушивателя пропуска, и сообщается о пропущенных ошибках.

Однако, если предел пропуска меньше (скажем, 5, как в моем примере), системные выходы в классе пропуска слушателя вообще не вызываются, и я напрямую получаю следующий дамп исключения на консоли:

org.springframework.batch.retry.RetryException: Non-skippable exception in recoverer while processing; nested exception is java.lang.StringIndexOutOfBoundsException
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$2.recover(FaultTolerantChunkProcessor.java:282)
at org.springframework.batch.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:416)
at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:285)
at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:187)

В чем причина такого поведения? Что мне делать, чтобы решить эту проблему?

Спасибо за прочтение!


person Vicky    schedule 07.02.2012    source источник


Ответы (1)


SkipListener используется только в конце блока, если тасклет, который его содержит, завершается нормально. Когда у вас есть больше ошибок, чем предел пропуска, это сообщается через исключение, которое вы видите, и тасклет прерывается.

Если количество ошибок меньше, чем предел пропуска, то тасклет завершается нормально, и SkipListener вызывается один раз для каждой пропущенной строки или элемента - Spring Batch создает их список внутри по ходу выполнения, но сообщает только в конце.

Идея заключается в том, что если задача не удалась, вы, вероятно, попытаетесь ее повторить, поэтому знание того, что было пропущено во время неполного запуска, бесполезно, каждый раз, когда вы повторяете попытку, вы будете получать одно и то же уведомление. Только если все остальное будет успешным, вы сможете увидеть, что было пропущено. Представляя, что вы регистрируете пропущенные элементы, вы не хотите, чтобы они регистрировались как пропущенные снова и снова.

Как вы видели, простое решение - сделать предел пропусков достаточно большим. Опять же, идея состоит в том, что если вам нужно пропустить много элементов, вероятно, существует более серьезная проблема.

person Paul    schedule 09.02.2012