@Test public void testRestartJobOnNonRestartableTasklet() throws Exception { step.setTasklet(new TestingChunkOrientedTasklet<>(new ItemReader<String>() { @Override public String read() throws Exception { return "foo"; } }, itemWriter)); JobExecution jobExecution = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); step.execute(stepExecution); }
@Test public void testDirectlyInjectedListenerOnError() throws Exception { step.registerStepExecutionListener(new StepExecutionListenerSupport() { @Override public ExitStatus afterStep(StepExecution stepExecution) { list.add("exception"); return null; } }); step.setTasklet(new TestingChunkOrientedTasklet<>(new MockRestartableItemReader() { @Override public String read() throws RuntimeException { throw new RuntimeException("FOO"); } }, itemWriter)); JobExecution jobExecution = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); step.execute(stepExecution); assertEquals("FOO", stepExecution.getFailureExceptions().get(0).getMessage()); assertEquals(1, list.size()); }
@Test public void testStatusForNormalFailure() throws Exception { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { // Trigger a rollback throw new RuntimeException("Foo"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); stepExecution.setExecutionContext(foobarEc); // step.setLastExecution(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); // The original rollback was caused by this one: assertEquals("Foo", stepExecution.getFailureExceptions().get(0).getMessage()); }
@Test public void testStatusForErrorFailure() throws Exception { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { // Trigger a rollback throw new Error("Foo"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); stepExecution.setExecutionContext(foobarEc); // step.setLastExecution(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); // The original rollback was caused by this one: assertEquals("Foo", stepExecution.getFailureExceptions().get(0).getMessage()); }
@Test public void testLockNotReleasedIfChunkFails() throws Exception { configureStep(new TaskletStep("step") { @SuppressWarnings("serial") @Override protected Semaphore createSemaphore() { return new Semaphore(1) { private boolean locked = false; @Override public void acquire() throws InterruptedException { locked = true; } @Override public void release() { assertTrue("Lock released before it is acquired", locked); } }; } }); step.setTasklet(new TestingChunkOrientedTasklet<>(new ItemReader<Object>() { @Override public Object read() throws Exception { throw new RuntimeException("Planned!"); } }, itemWriter)); jobRepository.add(stepExecution); step.execute(stepExecution); assertEquals("Planned!", stepExecution.getFailureExceptions().get(0).getMessage()); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); }
public void testStatus() throws Exception { step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[] { "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c" }), new ItemWriter<String>() { @Override
private TaskletStep getStep(String[] strings, int commitInterval) throws Exception { TaskletStep step = new TaskletStep("stepName"); // Only process one item: RepeatTemplate template = new RepeatTemplate(); template.setCompletionPolicy(new SimpleCompletionPolicy(commitInterval)); step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(strings), itemWriter, template)); step.setJobRepository(new JobRepositorySupport()); step.setTransactionManager(transactionManager); return step; }
@Test public void testIncrementRollbackCount() { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { throw new RuntimeException(); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); try { step.execute(stepExecution); } catch (Exception ex) { assertEquals(1, stepExecution.getRollbackCount()); } }
@Test public void testExitCodeDefaultClassification() throws Exception { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { throw new RuntimeException(); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); try { step.execute(stepExecution); } catch (Exception ex) { ExitStatus status = stepExecution.getExitStatus(); assertEquals(ExitStatus.COMPLETED, status); } }
@Test public void testNoSaveExecutionAttributesRestartableJob() { MockRestartableItemReader tasklet = new MockRestartableItemReader(); step.setTasklet(new TestingChunkOrientedTasklet<>(tasklet, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); try { step.execute(stepExecution); } catch (Throwable t) { fail(); } assertFalse(tasklet.isRestoreFromCalled()); }
@SuppressWarnings("serial") @Test public void testStatusForResetFailedException() throws Exception { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { // Trigger a rollback throw new RuntimeException("Foo"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); step.setTransactionManager(new ResourcelessTransactionManager() { @Override protected void doRollback(DefaultTransactionStatus status) throws TransactionException { // Simulate failure on rollback when stream resets throw new RuntimeException("Bar"); } }); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); stepExecution.setExecutionContext(foobarEc); // step.setLastExecution(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); String msg = stepExecution.getExitStatus().getExitDescription(); assertTrue("Message does not contain ResetFailedException: " + msg, msg.contains("ResetFailedException")); // The original rollback was caused by this one: assertEquals("Bar", stepExecution.getFailureExceptions().get(0).getMessage()); }
/** * Execution context must not be left empty even if job failed before * committing first chunk - otherwise ItemStreams won't recognize it is * restart scenario on next run. */ @Test public void testRestartAfterFailureInFirstChunk() throws Exception { MockRestartableItemReader reader = new MockRestartableItemReader() { @Override public String read() throws RuntimeException { // fail on the very first item throw new RuntimeException("CRASH!"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(reader, itemWriter)); step.registerStream(reader); StepExecution stepExecution = new StepExecution(step.getName(), new JobExecution(jobInstance, jobParameters)); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); Throwable expected = stepExecution.getFailureExceptions().get(0); assertEquals("CRASH!", expected.getMessage()); assertFalse(stepExecution.getExecutionContext().isEmpty()); assertTrue(stepExecution.getExecutionContext().getString("spam").equals("bucket")); }
@Test public void testStatusForCloseFailedException() throws Exception { MockRestartableItemReader itemReader = new MockRestartableItemReader() { @Override public void close() throws ItemStreamException { super.close(); // Simulate failure on rollback when stream resets throw new RuntimeException("Bar"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); step.registerStream(itemReader); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); stepExecution.setExecutionContext(foobarEc); // step.setLastExecution(stepExecution); step.execute(stepExecution); // The job actually completed, but the streams couldn't be closed. assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); String msg = stepExecution.getExitStatus().getExitDescription(); assertEquals("", msg); Throwable ex = stepExecution.getFailureExceptions().get(0); // The original rollback was caused by this one: assertEquals("Bar", ex.getMessage()); }
@Test public void testStatusForInterruptedException() throws Exception { StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy() { @Override public void checkInterrupted(StepExecution stepExecution) throws JobInterruptedException { throw new JobInterruptedException("interrupted"); } }; step.setInterruptionPolicy(interruptionPolicy); ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { throw new RuntimeException(); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); stepExecution.setExecutionContext(foobarEc); step.execute(stepExecution); assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); String msg = stepExecution.getExitStatus().getExitDescription(); assertTrue("Message does not contain 'JobInterruptedException': " + msg, msg .contains("JobInterruptedException")); }
@Test public void testNonRestartedJob() throws Exception { MockRestartableItemReader tasklet = new MockRestartableItemReader(); step.setTasklet(new TestingChunkOrientedTasklet<>(tasklet, itemWriter)); step.registerStream(tasklet); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); step.execute(stepExecution); assertFalse(tasklet.isRestoreFromCalled()); assertTrue(tasklet.isGetExecutionAttributesCalled()); }
@Test public void testExitCodeCustomClassification() throws Exception { ItemReader<String> itemReader = new ItemReader<String>() { @Override public String read() throws Exception { throw new RuntimeException(); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(itemReader, itemWriter)); step.registerStepExecutionListener(new StepExecutionListenerSupport() { @Override public ExitStatus afterStep(StepExecution stepExecution) { return ExitStatus.FAILED.addExitDescription("FOO"); } }); JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); try { step.execute(stepExecution); } catch (Exception ex) { ExitStatus status = stepExecution.getExitStatus(); assertEquals(ExitStatus.FAILED.getExitCode(), status.getExitCode()); String description = status.getExitDescription(); assertTrue("Description does not include 'FOO': " + description, description.indexOf("FOO") >= 0); } }
@Test public void testEmptyReader() throws Exception { JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); step = getStep(new String[0]); step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[0]), itemWriter, new RepeatTemplate())); step.setStepOperations(new RepeatTemplate()); step.execute(stepExecution); assertEquals(0, processed.size()); assertEquals(0, stepExecution.getReadCount()); // Commit after end of data detected (this leads to the commit count // being one greater than people expect if the commit interval is // commensurate with the total number of items).h assertEquals(1, stepExecution.getCommitCount()); }
@Test public void testStreamManager() throws Exception { MockRestartableItemReader reader = new MockRestartableItemReader() { @Override public String read() { return "foo"; } @Override public void update(ExecutionContext executionContext) { super.update(executionContext); executionContext.putString("foo", "bar"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(reader, itemWriter)); step.registerStream(reader); JobExecution jobExecution = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); step.execute(stepExecution); // At least once in that process the statistics service was asked for // statistics... assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); }
@Test public void testDirectlyInjectedStreamWhichIsAlsoReader() throws Exception { MockRestartableItemReader reader = new MockRestartableItemReader() { @Override public String read() { return "foo"; } @Override public void update(ExecutionContext executionContext) { super.update(executionContext); executionContext.putString("foo", "bar"); } }; step.setTasklet(new TestingChunkOrientedTasklet<>(reader, itemWriter)); step.setStreams(new ItemStream[] { reader }); JobExecution jobExecution = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); step.execute(stepExecution); // At least once in that process the statistics service was asked for // statistics... assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); }
private void setUp() throws Exception { step = new TaskletStep("stepName"); ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager(); step.setTransactionManager(transactionManager); RepeatTemplate chunkTemplate = new RepeatTemplate(); chunkTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2)); step.setTasklet(new TestingChunkOrientedTasklet<>(new ListItemReader<>(items), itemProcessor, itemWriter, chunkTemplate)); jobRepository = new JobRepositorySupport(); step.setJobRepository(jobRepository); TaskExecutorRepeatTemplate template = new TaskExecutorRepeatTemplate(); template.setThrottleLimit(throttleLimit); SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); taskExecutor.setConcurrencyLimit(concurrencyLimit); template.setTaskExecutor(taskExecutor); step.setStepOperations(template); step.registerStream(new ItemStreamSupport() { private int count = 0; @Override public void update(ExecutionContext executionContext) { super.update(executionContext); executionContext.putInt("counter", count++); } }); }