protected void registerItemListeners(SimpleStepBuilder<I, O> builder) { for (ItemReadListener<I> listener : readListeners) { builder.listener(listener); } for (ItemWriteListener<O> listener : writeListeners) { builder.listener(listener); } for (ItemProcessListener<I, O> listener : processListeners) { builder.listener(listener); } }
@SuppressWarnings("unchecked") private void checkAndAddItemListener(StepListener stepListener) { if (stepListener instanceof ItemReadListener){ listener((ItemReadListener<I>)stepListener); } if (stepListener instanceof ItemProcessListener){ listener((ItemProcessListener<I,O>)stepListener); } if (stepListener instanceof ItemWriteListener){ listener((ItemWriteListener<O>)stepListener); } }
@Override public FaultTolerantStepBuilder<I, O> listener(ChunkListener listener) { super.listener(new TerminateOnExceptionChunkListenerDelegate(listener)); return this; }
protected void registerAsStreamsAndListeners(ItemReader<? extends I> itemReader, ItemProcessor<? super I, ? extends O> itemProcessor, ItemWriter<? super O> itemWriter) { for (Object itemHandler : new Object[] { itemReader, itemWriter, itemProcessor }) { if (itemHandler instanceof ItemStream) { stream((ItemStream) itemHandler); } if (StepListenerFactoryBean.isListener(itemHandler)) { StepListener listener = StepListenerFactoryBean.getListener(itemHandler); if (listener instanceof StepExecutionListener) { listener((StepExecutionListener) listener); } if (listener instanceof ChunkListener) { listener((ChunkListener) listener); } if (listener instanceof ItemReadListener<?> || listener instanceof ItemProcessListener<?, ?> || listener instanceof ItemWriteListener<?>) { itemListeners.add(listener); } } } }
/** * Registers objects using the annotation based listener configuration. * * @param listener the object that has a method configured with listener annotation * @return this for fluent chaining */ @Override @SuppressWarnings("unchecked") public SimpleStepBuilder<I, O> listener(Object listener) { super.listener(listener); Set<Method> skipListenerMethods = new HashSet<>(); skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInRead.class)); skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInProcess.class)); skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInWrite.class)); if(skipListenerMethods.size() > 0) { StepListenerFactoryBean factory = new StepListenerFactoryBean(); factory.setDelegate(listener); skipListeners.add((SkipListener) factory.getObject()); } @SuppressWarnings("unchecked") SimpleStepBuilder<I, O> result = this; return result; }
@Bean public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader<String> fakeItemReader, ItemProcessor<String, String> fakeProcessor, ItemWriter<String> fakeItemWriter, ItemProcessListener<String, String> itemProcessListener) { return stepBuilderFactory.get("testStep").<String, String>chunk(10) .reader(fakeItemReader) .processor(fakeProcessor) .writer(fakeItemWriter) .listener(itemProcessListener) .faultTolerant().skipLimit(50).skip(RuntimeException.class) .build(); }
@Test public void testNoInputNoListeners() throws Exception{ reader = new FailingListItemReader(new ArrayList<>()); Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(0, processor.count); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(0, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); }
@Test public void testNoInputNoListeners() throws Exception{ reader = new FailingListItemReader(new ArrayList<>()); Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(0, processor.count); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(0, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); }
@Test public void testProcessError() throws Exception{ processor.failCount = 10; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertEquals(10, processor.count); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(10, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals("expected at process index 10", stepExecution.getFailureExceptions().get(0).getCause().getMessage()); assertEquals(9, listener.afterProcess); assertEquals(10, listener.afterRead); assertEquals(0, listener.afterWrite); assertEquals(10, listener.beforeProcess); assertEquals(10, listener.beforeRead); assertEquals(0, listener.beforeWriteCount); assertEquals(1, listener.onProcessError); assertEquals(0, listener.onReadError); assertEquals(0, listener.onWriteError); }
@Test public void testReadError() throws Exception{ reader.failCount = 10; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(9, processor.count); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(9, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(1, stepExecution.getFailureExceptions().size()); assertEquals("expected at read index 10", stepExecution.getFailureExceptions().get(0).getMessage()); assertEquals(9, readListener.afterProcess); assertEquals(9, readListener.afterRead); assertEquals(0, readListener.afterWrite); assertEquals(9, readListener.beforeProcess); assertEquals(10, readListener.beforeRead); assertEquals(0, readListener.beforeWriteCount); assertEquals(0, readListener.onProcessError); assertEquals(1, readListener.onReadError); assertEquals(0, readListener.onWriteError); }
@Test public void testProcessError() throws Exception{ processor.failCount = 10; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(10, processor.count); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(10, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals("expected at process index 10", stepExecution.getFailureExceptions().get(0).getMessage()); assertEquals(9, readListener.afterProcess); assertEquals(10, readListener.afterRead); assertEquals(0, readListener.afterWrite); assertEquals(10, readListener.beforeProcess); assertEquals(10, readListener.beforeRead); assertEquals(0, readListener.beforeWriteCount); assertEquals(1, readListener.onProcessError); assertEquals(0, readListener.onReadError); assertEquals(0, readListener.onWriteError); }
@Test public void testWriteError() throws Exception{ writer.fail = true; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(25, processor.count); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals("expected in write", stepExecution.getFailureExceptions().get(0).getMessage()); assertEquals(25, readListener.afterProcess); assertEquals(25, readListener.afterRead); assertEquals(0, readListener.afterWrite); assertEquals(25, readListener.beforeProcess); assertEquals(25, readListener.beforeRead); assertEquals(1, readListener.beforeWriteCount); assertEquals(0, readListener.onProcessError); assertEquals(0, readListener.onReadError); assertEquals(1, readListener.onWriteError); }
@Test public void testAnnotationBasedChunkListenerForSimpleTaskletStep() throws Exception { JobRepository jobRepository = new MapJobRepositoryFactoryBean().getObject(); StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); SimpleStepBuilder<Object, Object> builder = new StepBuilder("step") .repository(jobRepository) .transactionManager(transactionManager) .chunk(5) .reader(new DummyItemReader()) .writer(new DummyItemWriter()) .listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, AnnotationBasedChunkListener.beforeChunkCount); assertEquals(1, AnnotationBasedChunkListener.afterChunkCount); }
@Test public void testRetryProcessError() throws Exception{ processor.failCount = 10; Step step = builder.faultTolerant().retry(RuntimeException.class).retryLimit(20).chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertNotNull(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(26, processor.count); assertEquals(25, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(25, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(0, stepExecution.getFailureExceptions().size()); assertEquals(25, listener.afterProcess); assertEquals(25, listener.afterRead); assertEquals(1, listener.afterWrite); assertEquals(26, listener.beforeProcess); assertEquals(26, listener.beforeRead); assertEquals(1, listener.beforeWriteCount); assertEquals(1, listener.onProcessError); assertEquals(0, listener.onReadError); assertEquals(0, listener.onWriteError); }
@Test public void testMultipleChunks() throws Exception{ Step step = builder.chunk(10).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(25, processor.count); assertEquals(25, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(25, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, readListener.afterProcess); assertEquals(25, readListener.afterRead); assertEquals(3, readListener.afterWrite); assertEquals(25, readListener.beforeProcess); assertEquals(26, readListener.beforeRead); assertEquals(3, readListener.beforeWriteCount); assertEquals(0, readListener.onProcessError); assertEquals(0, readListener.onReadError); assertEquals(0, readListener.onWriteError); }
@Test public void testProcessorFilteringNoListeners() throws Exception{ processor.filter = true; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) readListener).build(); runStep(step); int count = 0; for (String curItem : writer.results) { assertEquals("item " + count, curItem); count += 2; } assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(13, stepExecution.getWriteCount()); assertEquals(12, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, processor.count); }
@Test public void testMultipleChunks() throws Exception{ Step step = builder.chunk(10).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertEquals(25, processor.count); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(25, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(25, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, listener.afterProcess); assertEquals(25, listener.afterRead); assertEquals(3, listener.afterWrite); assertEquals(25, listener.beforeProcess); assertEquals(26, listener.beforeRead); assertEquals(3, listener.beforeWriteCount); assertEquals(0, listener.onProcessError); assertEquals(0, listener.onReadError); assertEquals(0, listener.onWriteError); }
@Test public void testProcessorFilteringNoListeners() throws Exception{ processor.filter = true; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); int count = 0; for (String curItem : writer.results) { assertEquals("item " + count, curItem); count += 2; } assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(13, stepExecution.getWriteCount()); assertEquals(12, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, processor.count); }
@Test public void testWriteError() throws Exception{ writer.fail = true; Step step = builder.chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertEquals(25, processor.count); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(0, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, listener.afterProcess); assertEquals(25, listener.afterRead); assertEquals(0, listener.afterWrite); assertEquals(25, listener.beforeProcess); assertEquals(25, listener.beforeRead); assertEquals(1, listener.beforeWriteCount); assertEquals(0, listener.onProcessError); assertEquals(0, listener.onReadError); assertEquals(1, listener.onWriteError); }
@Test public void testRetryWriteError() throws Exception{ writer.fail = true; Step step = builder.faultTolerant().retry(RuntimeException.class).retryLimit(25).chunk(25).reader(reader).processor(processor).writer(writer).listener((ItemReadListener<String>) listener).build(); runStep(step); assertEquals(25, processor.count); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(25, writer.results.size()); assertEquals(0, stepExecution.getProcessSkipCount()); assertEquals(25, stepExecution.getReadCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(0, stepExecution.getSkipCount()); assertEquals(25, stepExecution.getWriteCount()); assertEquals(0, stepExecution.getFilterCount()); assertEquals(0, stepExecution.getWriteSkipCount()); assertEquals(25, listener.afterProcess); assertEquals(25, listener.afterRead); assertEquals(1, listener.afterWrite); assertEquals(25, listener.beforeProcess); assertEquals(26, listener.beforeRead); assertEquals(2, listener.beforeWriteCount); assertEquals(0, listener.onProcessError); assertEquals(0, listener.onReadError); assertEquals(1, listener.onWriteError); }