Задание чтения Spring Batch Stax XML не заканчивается, когда отсутствует ввод - PullRequest
2 голосов
/ 16 октября 2011

Я использую Spring Batch для настройки задания, которое будет обрабатывать потенциально очень большой XML-файл.Я думаю, что настроил его соответствующим образом, но во время выполнения я обнаружил, что задание запускается, обрабатывает его ввод, а затем просто зависает в состоянии выполнения (я могу подтвердить это, просматривая состояние JobExecution в JobRepository).

Я прочитал документацию Batch несколько раз, но я не вижу какой-либо очевидной конфигурации "заставьте работу остановиться, когда нет ввода", которую я пропускаю.

Вот соответствующая часть контекста моего приложения:

<batch:job id="processPartnerUploads" restartable="true">
    <batch:step id="processStuffHoldings">
        <batch:tasklet>
            <batch:chunk reader="stuffReader" writer="stuffWriter" commit-interval="1"/>
        </batch:tasklet>        
    </batch:step>
</batch:job>

<bean id="stuffReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
  <property name="fragmentRootElementName" value="stuff" />
  <property name="resource" value="file:///path/to/file.xml" />
  <property name="unmarshaller" ref="stuffUnmarshaller" />
</bean>

<bean id="stuffUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="contextPath" value="com.company.project.xmlcontext"/>
</bean>

<bean id="stuffWriter" class="com.company.project.batch.StuffWriter" />

В случае, если это имеет значение, StuffWriter - это просто класс, который регистрирует элементы, которые будут записаны.

Пожалуйста, дайте мне знать, если я пропустил какой-то важный нюанс, связанный с Batch и / или Stax.

1 Ответ

2 голосов
/ 19 октября 2011

Я решил эту проблему для себя, хотя я удивлен тем, что мне пришлось сделать.Отлаживая через StaxEventItemReader, я заметил, что внутренний цикл в методе moveCursorToNextFragment () станет бесконечным, когда будет достигнут конец моего документа.Вот соответствующий код:

while (true) {
    while (reader.peek() != null && !reader.peek().isStartElement()) {
        reader.nextEvent();
    }
    if (reader.peek() == null) {
        return false;
    }
    QName startElementName = ((StartElement) reader.peek()).getName();
    if (startElementName.getLocalPart().equals(fragmentRootElementName)) {
        if (fragmentRootElementNameSpace == null
    || startElementName.getNamespaceURI().equals(fragmentRootElementNameSpace)) {
           return true;
        }
     }
    reader.nextEvent();
 }

reader.peek () никогда не возвращал ноль.Мне показалось, что этот код должен проверять, находится ли XMLEvent, обнаруженный во время peek (), в конце документа, но это было не так просто из-за зависимости StaxEventItemReader от DefaultFragmentEventReader, обертывающего стандартный XMLEventReader.

В итоге я развернул свой собственный ItemReader, основанный на StaxEventItemReader, но без использования FragmentEventReader, а затем настроил код внутреннего цикла так, чтобы он читался так:

        if (reader.peek().getEventType() == XMLStreamConstants.END_DOCUMENT) {
            return false;
        }
        reader.nextEvent();

Это прекрасно работает ипозволяет моей пакетной работе перейти в ЗАВЕРШЕНО в конце ввода.

Я действительно удивлен тем, что мне пришлось это сделать.Мне было интересно, виновата ли базовая реализация потоковых XML-библиотек, которые я использовал, но я использую stax2-api-3.0.1.jar, как указано в списке зависимостей Spring Batch.

Я также нашелчто я не одинок .

...