diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java index 84dfdb78f..4bbaba23a 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java @@ -39,16 +39,17 @@ import org.springframework.util.StringUtils; /** * Sql implementation of StepDao. Uses Sequences (via Spring's - * @link DataFieldMaxValueIncrementer abstraction) to create all Step and - * StepExecution primary keys before inserting a new row. All objects are - * checked to ensure all fields to be stored are not null. If any are found to - * be null, an IllegalArgumentException will be thrown. This could be left to - * JdbcTemplate, however, the exception will be fairly vague, and fails to - * highlight which field caused the exception. * - * TODO: JavaDoc should be geared more towards usability, the comments - * above are useful information, and should be there, but needs usability - * stuff. Depends on the step dao java docs as well. + * @link DataFieldMaxValueIncrementer abstraction) to create all Step and + * StepExecution primary keys before inserting a new row. All objects are + * checked to ensure all fields to be stored are not null. If any are + * found to be null, an IllegalArgumentException will be thrown. This + * could be left to JdbcTemplate, however, the exception will be fairly + * vague, and fails to highlight which field caused the exception. + * + * TODO: JavaDoc should be geared more towards usability, the comments above are + * useful information, and should be there, but needs usability stuff. Depends + * on the step dao java docs as well. * * @author Lucas Ward * @see StepDao @@ -67,16 +68,18 @@ public class SqlStepDao implements StepDao, InitializingBean { // StepExecution statements private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(ID, VERSION, STEP_ID, JOB_EXECUTION_ID, START_TIME, " - + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, TASK_STATISTICS, EXIT_CODE) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, TASK_STATISTICS, EXIT_CODE, EXIT_MESSAGE) " + + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " - + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, TASK_STATISTICS = ?, EXIT_CODE = ? where ID = ?"; + + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, TASK_STATISTICS = ?, EXIT_CODE = ?, " + + "EXIT_MESSAGE = ? where ID = ?"; private static final String GET_STEP_EXECUTION_COUNT = "SELECT count(ID) from %PREFIX%STEP_EXECUTION where " + "STEP_ID = ?"; private static final String FIND_STEP_EXECUTIONS = "SELECT ID, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT," - + " TASK_COUNT, TASK_STATISTICS, EXIT_CODE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; + + " TASK_COUNT, TASK_STATISTICS, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; private JdbcOperations jdbcTemplate; @@ -105,8 +108,10 @@ public class SqlStepDao implements StepDao, InitializingBean { * anymore than one step is found, an exception is thrown. * * @see StepDao#findStep(Long, String) - * @throws IllegalArgumentException if job, stepName, or job.id is null. - * @throws NoSuchBatchDomainObjectException if more than one step is found. + * @throws IllegalArgumentException + * if job, stepName, or job.id is null. + * @throws NoSuchBatchDomainObjectException + * if more than one step is found. */ public StepInstance findStep(JobInstance job, String stepName) { @@ -122,30 +127,30 @@ public class SqlStepDao implements StepDao, InitializingBean { StepInstance step = new StepInstance(new Long(rs.getLong(1))); step.setStatus(BatchStatus.getStatus(rs.getString(2))); - step.setRestartData( - new GenericRestartData(PropertiesConverter.stringToProperties(rs.getString(3)))); + step.setRestartData(new GenericRestartData(PropertiesConverter + .stringToProperties(rs.getString(3)))); return step; } }; - List steps = jdbcTemplate.query(getQuery(FIND_STEP), parameters, rowMapper); + List steps = jdbcTemplate.query(getQuery(FIND_STEP), parameters, + rowMapper); if (steps.size() == 0) { // No step found return null; - } - else if (steps.size() == 1) { + } else if (steps.size() == 1) { StepInstance step = (StepInstance) steps.get(0); step.setName(stepName); return step; - } - else { + } else { // This error will likely never be thrown, because there should // never be two steps with the same name and Job_ID due to database // constraints. - throw new NoSuchBatchDomainObjectException("Step Invalid, multiple steps found for StepName:" + stepName - + " and JobId:" + job.getId()); + throw new NoSuchBatchDomainObjectException( + "Step Invalid, multiple steps found for StepName:" + + stepName + " and JobId:" + job.getId()); } } @@ -156,7 +161,8 @@ public class SqlStepDao implements StepDao, InitializingBean { * Sql implementation which uses a RowMapper to populate a list of all rows * in the step table with the same JOB_ID. * - * @throws IllegalArgumentException if jobId is null. + * @throws IllegalArgumentException + * if jobId is null. */ public List findSteps(Long jobId) { @@ -172,8 +178,8 @@ public class SqlStepDao implements StepDao, InitializingBean { step.setName(rs.getString(2)); String status = rs.getString(3); step.setStatus(BatchStatus.getStatus(status)); - step.setRestartData( - new GenericRestartData(PropertiesConverter.stringToProperties(rs.getString(3)))); + step.setRestartData(new GenericRestartData(PropertiesConverter + .stringToProperties(rs.getString(3)))); return step; } }; @@ -187,7 +193,8 @@ public class SqlStepDao implements StepDao, InitializingBean { * DataFieldMaxValueIncrementer) * * @see StepDao#createStep(JobInstance, String) - * @throws IllegalArgumentException if job or stepName is null. + * @throws IllegalArgumentException + * if job or stepName is null. */ public StepInstance createStep(JobInstance job, String stepName) { @@ -206,7 +213,8 @@ public class SqlStepDao implements StepDao, InitializingBean { /** * @see StepDao#update(StepInstance) - * @throws IllegalArgumentException if step, or it's status and id is null. + * @throws IllegalArgumentException + * if step, or it's status and id is null. */ public void update(final StepInstance step) { @@ -219,12 +227,11 @@ public class SqlStepDao implements StepDao, InitializingBean { if (restartData != null) { restartProps = restartData.getProperties(); } - - Object[] parameters = new Object[]{ step.getStatus().toString(), + + Object[] parameters = new Object[] { step.getStatus().toString(), PropertiesConverter.propertiesToString(restartProps), - step.getId() - }; - + step.getId() }; + jdbcTemplate.update(getQuery(UPDATE_STEP), parameters); } @@ -240,10 +247,19 @@ public class SqlStepDao implements StepDao, InitializingBean { validateStepExecution(stepExecution); stepExecution.setId(new Long(stepExecutionIncrementer.nextLongValue())); - Object[] parameters = new Object[] { stepExecution.getId(), new Long(0), stepExecution.getStepId(), stepExecution.getJobExecutionId(), - stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), - stepExecution.getCommitCount(), stepExecution.getTaskCount(), - PropertiesConverter.propertiesToString(stepExecution.getStatistics()), stepExecution.getExitCode() }; + Object[] parameters = new Object[] { + stepExecution.getId(), + new Long(0), + stepExecution.getStepId(), + stepExecution.getJobExecutionId(), + stepExecution.getStartTime(), + stepExecution.getEndTime(), + stepExecution.getStatus().toString(), + stepExecution.getCommitCount(), + stepExecution.getTaskCount(), + PropertiesConverter.propertiesToString(stepExecution + .getStatistics()), stepExecution.getExitCode(), + stepExecution.getExitDescription() }; jdbcTemplate.update(getQuery(SAVE_STEP_EXECUTION), parameters); } @@ -254,8 +270,9 @@ public class SqlStepDao implements StepDao, InitializingBean { public void update(StepExecution stepExecution) { validateStepExecution(stepExecution); - Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved" - + " before it can be updated."); + Assert.notNull(stepExecution.getId(), + "StepExecution Id cannot be null. StepExecution must saved" + + " before it can be updated."); // TODO: Not sure if this is a good idea on step execution considering // it is saved at every commit @@ -265,10 +282,15 @@ public class SqlStepDao implements StepDao, InitializingBean { // return; // throw exception? // } - Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), - stepExecution.getStatus().toString(), stepExecution.getCommitCount(), - stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution.getStatistics()), - stepExecution.getExitCode(), + Object[] parameters = new Object[] { + stepExecution.getStartTime(), + stepExecution.getEndTime(), + stepExecution.getStatus().toString(), + stepExecution.getCommitCount(), + stepExecution.getTaskCount(), + PropertiesConverter.propertiesToString(stepExecution + .getStatistics()), stepExecution.getExitCode(), + stepExecution.getExitDescription(), stepExecution.getId() }; jdbcTemplate.update(getQuery(UPDATE_STEP_EXECUTION), parameters); @@ -278,7 +300,8 @@ public class SqlStepDao implements StepDao, InitializingBean { Object[] parameters = new Object[] { stepId }; - return jdbcTemplate.queryForInt(getQuery(GET_STEP_EXECUTION_COUNT), parameters); + return jdbcTemplate.queryForInt(getQuery(GET_STEP_EXECUTION_COUNT), + parameters); } /** @@ -286,9 +309,10 @@ public class SqlStepDao implements StepDao, InitializingBean { * they will not be returned with reconstituted object. * * @see StepDao#getStepExecution(Long) - * @throws IllegalArgumentException if id is null. - * @throws NoSuchBatchDomainObjectException if more than one step execution is - * returned. + * @throws IllegalArgumentException + * if id is null. + * @throws NoSuchBatchDomainObjectException + * if more than one step execution is returned. */ public List findStepExecutions(StepInstance step) { @@ -300,20 +324,24 @@ public class SqlStepDao implements StepDao, InitializingBean { RowMapper rowMapper = new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - StepExecution stepExecution = new StepExecution(stepId, new Long(rs.getLong(2))); + StepExecution stepExecution = new StepExecution(stepId, + new Long(rs.getLong(2))); stepExecution.setId(new Long(rs.getLong(1))); stepExecution.setStartTime(rs.getTimestamp(3)); stepExecution.setEndTime(rs.getTimestamp(4)); stepExecution.setStatus(BatchStatus.getStatus(rs.getString(5))); stepExecution.setCommitCount(rs.getInt(6)); stepExecution.setTaskCount(rs.getInt(7)); - stepExecution.setStatistics(PropertiesConverter.stringToProperties(rs.getString(8))); + stepExecution.setStatistics(PropertiesConverter + .stringToProperties(rs.getString(8))); stepExecution.setExitCode(rs.getString(9)); + stepExecution.setExitDescription(rs.getString(10)); return stepExecution; } }; - return jdbcTemplate.query(getQuery(FIND_STEP_EXECUTIONS), new Object[] { stepId }, rowMapper); + return jdbcTemplate.query(getQuery(FIND_STEP_EXECUTIONS), + new Object[] { stepId }, rowMapper); } @@ -325,32 +353,37 @@ public class SqlStepDao implements StepDao, InitializingBean { this.stepIncrementer = stepIncrementer; } - public void setStepExecutionIncrementer(DataFieldMaxValueIncrementer stepExecutionIncrementer) { + public void setStepExecutionIncrementer( + DataFieldMaxValueIncrementer stepExecutionIncrementer) { this.stepExecutionIncrementer = stepExecutionIncrementer; } public void afterPropertiesSet() throws Exception { Assert.notNull(jdbcTemplate, "JdbcTemplate cannot be null."); Assert.notNull(stepIncrementer, "StepIncrementer cannot be null."); - Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer canot be null."); + Assert.notNull(stepExecutionIncrementer, + "StepExecutionIncrementer canot be null."); } private String getQuery(String base) { return StringUtils.replace(base, "%PREFIX%", tablePrefix); } - + /* - * Validate StepExecution. At a minimum, JobId, StartTime, and - * Status cannot be null. EndTime can be null for an unfinished job. + * Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot + * be null. EndTime can be null for an unfinished job. * * @param jobExecution @throws IllegalArgumentException */ private void validateStepExecution(StepExecution stepExecution) { Assert.notNull(stepExecution); - Assert.notNull(stepExecution.getStepId(), "StepExecution Step-Id cannot be null."); - Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null."); - Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null."); + Assert.notNull(stepExecution.getStepId(), + "StepExecution Step-Id cannot be null."); + Assert.notNull(stepExecution.getStartTime(), + "StepExecution start time cannot be null."); + Assert.notNull(stepExecution.getStatus(), + "StepExecution status cannot be null."); } } diff --git a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifier.java b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifier.java new file mode 100644 index 000000000..0a5a41d40 --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifier.java @@ -0,0 +1,59 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.simple; + +import org.springframework.batch.core.executor.ExitCodeExceptionClassifier; +import org.springframework.batch.repeat.ExitStatus; + +/** + * Simple implementation of {@link ExitCodeExceptionClassifier} that returns basic + * String exit codes, and defaults to the class name of the throwable + * for the message. Most users will want to write their own implementation + * that creates more specific exit codes for different exception types. + * + * @author Lucas Ward + * + */ +public class SimpleExitCodeExceptionClassifier implements + ExitCodeExceptionClassifier { + + /* (non-Javadoc) + * @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable) + */ + public ExitStatus classifyForExitCode(Throwable throwable) { + return (ExitStatus)classify(throwable); + } + + /* (non-Javadoc) + * @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable) + */ + public Object classify(Throwable throwable) { + + ExitStatus exitStatus = new ExitStatus(false, + FATAL_EXCEPTION, throwable == null ? "" : throwable.getClass().getName()); + + return exitStatus; + } + + /* (non-Javadoc) + * @see org.springframework.batch.common.ExceptionClassifier#getDefault() + */ + public Object getDefault() { + //return without message since we don't know what the exception is + return new ExitStatus(false, FATAL_EXCEPTION); + } + +} diff --git a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java index 1980ba3fc..18bca55fb 100644 --- a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java @@ -24,6 +24,7 @@ import org.springframework.batch.core.configuration.StepConfiguration; import org.springframework.batch.core.domain.BatchStatus; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.core.executor.ExitCodeExceptionClassifier; import org.springframework.batch.core.executor.StepExecutor; import org.springframework.batch.core.executor.StepInterruptedException; import org.springframework.batch.core.repository.JobRepository; @@ -94,6 +95,8 @@ public class SimpleStepExecutor implements StepExecutor { private RepeatOperations stepOperations = new RepeatTemplate(); private JobRepository jobRepository; + + private ExitCodeExceptionClassifier exceptionClassifier = new SimpleExitCodeExceptionClassifier(); // default to checking current thread for interruption. private StepInterruptionPolicy interruptionPolicy = new ThreadStepInterruptionPolicy(); @@ -246,13 +249,13 @@ public class SimpleStepExecutor implements StepExecutor { }); - stepExecution.setExitCode(status.getExitCode()); - stepExecution.setExitDescription(status.getExitDescription()); updateStatus(stepExecutionContext, BatchStatus.COMPLETED); return status; } catch (RuntimeException e) { + //classify exception so an exit code can be stored. + status = exceptionClassifier.classifyForExitCode(e); stepExecution.setException(e); if (e.getCause() instanceof StepInterruptedException) { updateStatus(stepExecutionContext, BatchStatus.STOPPED); @@ -262,8 +265,11 @@ public class SimpleStepExecutor implements StepExecutor { updateStatus(stepExecutionContext, BatchStatus.FAILED); throw e; } + } finally { + stepExecution.setExitCode(status.getExitCode()); + stepExecution.setExitDescription(status.getExitDescription()); stepExecution.setEndTime(new Timestamp(System.currentTimeMillis())); try { jobRepository.saveOrUpdate(stepExecution); @@ -378,4 +384,15 @@ public class SimpleStepExecutor implements StepExecutor { public void setInterruptionPolicy(StepInterruptionPolicy interruptionPolicy) { this.interruptionPolicy = interruptionPolicy; } + + /** + * Setter for the {@link ExitCodeExceptionClassifier} that will be used + * to classify any exception that causes a job to fail. + * + * @param exceptionClassifier + */ + public void setExceptionClassifier( + ExitCodeExceptionClassifier exceptionClassifier) { + this.exceptionClassifier = exceptionClassifier; + } } diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java index a7baf243a..abc16b3e4 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java @@ -24,6 +24,7 @@ import org.springframework.batch.core.domain.BatchStatus; import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.core.executor.ExitCodeExceptionClassifier; import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; import org.springframework.batch.restart.GenericRestartData; @@ -160,12 +161,16 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour statistics.setProperty("statistic.key1", "0"); statistics.setProperty("statistic.key2", "5"); execution.setStatistics(statistics); + execution.setExitCode(ExitCodeExceptionClassifier.FATAL_EXCEPTION); + execution.setExitDescription("java.lang.Exception"); stepDao.save(execution); List executions = stepDao.findStepExecutions(step2); assertEquals(1, executions.size()); StepExecution tempExecution = (StepExecution)executions.get(0); assertEquals(execution, tempExecution); assertEquals(execution.getStatistics(), tempExecution.getStatistics()); + assertEquals(tempExecution.getExitCode(), execution.getExitCode()); + assertEquals(tempExecution.getExitDescription(), execution.getExitDescription()); } public void testUpdateStepExecution(){ @@ -175,10 +180,15 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour stepExecution.setCommitCount(5); stepExecution.setTaskCount(5); stepExecution.setStatistics(new Properties()); + stepExecution.setExitCode(ExitCodeExceptionClassifier.FATAL_EXCEPTION); + stepExecution.setExitDescription("java.lang.Exception"); stepDao.update(stepExecution); List executions = stepDao.findStepExecutions(step1); assertEquals(1, executions.size()); - assertEquals(stepExecution, (StepExecution)executions.get(0)); + StepExecution tempExecution = (StepExecution)executions.get(0); + assertEquals(stepExecution, tempExecution); + assertEquals(tempExecution.getExitCode(), stepExecution.getExitCode()); + assertEquals(tempExecution.getExitDescription(), stepExecution.getExitDescription()); } public void testUpdateStepExecutionWithNullId(){ diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java index 9c736d929..9a521f56a 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java @@ -24,6 +24,7 @@ import junit.framework.TestCase; import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.core.executor.ExitCodeExceptionClassifier; import org.springframework.batch.core.runtime.JobExecutionContext; import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.core.runtime.StepExecutionContext; @@ -165,7 +166,7 @@ public class DefaultStepExecutorTests extends TestCase { public void testIncrementRollbackCount(){ - Tasklet module = new Tasklet(){ + Tasklet tasklet = new Tasklet(){ public ExitStatus execute() throws Exception { int counter = 0; @@ -181,7 +182,7 @@ public class DefaultStepExecutorTests extends TestCase { }; StepInstance step = new StepInstance(new Long(1)); - stepConfiguration.setTasklet(module); + stepConfiguration.setTasklet(tasklet); JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3))); StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step); @@ -193,5 +194,36 @@ public class DefaultStepExecutorTests extends TestCase { } } + + public void testExitCodeClassification(){ + + Tasklet tasklet = new Tasklet(){ + + public ExitStatus execute() throws Exception { + int counter = 0; + counter++; + + if(counter == 1){ + throw new RuntimeException(); + } + + return ExitStatus.CONTINUABLE; + } + + }; + + StepInstance step = new StepInstance(new Long(1)); + stepConfiguration.setTasklet(tasklet); + JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3))); + StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step); + + try{ + stepExecutor.process(stepConfiguration, stepExecutionContext); + } + catch(Exception ex){ + assertEquals(step.getStepExecution().getExitCode(), ExitCodeExceptionClassifier.FATAL_EXCEPTION); + assertEquals(step.getStepExecution().getExitDescription(), "java.lang.RuntimeException"); + } + } } diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifierTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifierTests.java new file mode 100644 index 000000000..63c3b359e --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/SimpleExitCodeExceptionClassifierTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.simple; + + +import org.springframework.batch.repeat.ExitStatus; + +import junit.framework.TestCase; + +/** + * @author Lucas Ward + * + */ +public class SimpleExitCodeExceptionClassifierTests extends TestCase { + + NullPointerException exception; + + SimpleExitCodeExceptionClassifier classifier = new SimpleExitCodeExceptionClassifier(); + + protected void setUp() throws Exception { + super.setUp(); + + exception = new NullPointerException(); + } + + public void testClassifyForExitCode() { + + ExitStatus exitStatus = classifier.classifyForExitCode(exception); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), "java.lang.NullPointerException"); + } + + public void testClassify() { + ExitStatus exitStatus = (ExitStatus)classifier.classify(exception); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), "java.lang.NullPointerException"); + } + + public void testGetDefault() { + ExitStatus exitStatus = (ExitStatus)classifier.getDefault(); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), ""); + } + + /* + * Attempting to classify a null throwable should lead to a blank description, not a + * null pointer exception. + */ + public void testClassifyNullThrowable(){ + ExitStatus exitStatus = (ExitStatus)classifier.classify(null); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), ""); + } +}