diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java similarity index 98% rename from spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java rename to spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java index 353cfffbf..8504347aa 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java @@ -26,7 +26,7 @@ import org.springframework.batch.core.JobParameters; * @author Dave Syer * */ -public interface BatchMetaDataExplorer { +public interface JobExplorer { /** * @param jobName the name of the job to query diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/package.html b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/package.html new file mode 100644 index 000000000..d8d027732 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/package.html @@ -0,0 +1,7 @@ + + +

+Interfaces and related classes to support meta data browsing. +

+ + diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java new file mode 100644 index 000000000..f3f2aba05 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java @@ -0,0 +1,44 @@ +package org.springframework.batch.core.explore.support; + +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.repository.dao.JobExecutionDao; +import org.springframework.batch.core.repository.dao.JobInstanceDao; +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} that automates the creation of a + * {@link SimpleJobExplorer}. Declares abstract methods for providing DAO + * object implementations. + * + * @see JobExplorerFactoryBean + * @see MapJobExplorerFactoryBean + * + * @author Dave Syer + */ +public abstract class AbstractJobExplorerFactoryBean implements FactoryBean { + + /** + * @return fully configured {@link JobInstanceDao} implementation. + */ + protected abstract JobInstanceDao createJobInstanceDao() throws Exception; + + /** + * @return fully configured {@link JobExecutionDao} implementation. + */ + protected abstract JobExecutionDao createJobExecutionDao() throws Exception; + + /** + * The type of object to be returned from {@link #getObject()}. + * + * @return JobExplorer.class + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + public Class getObjectType() { + return JobExplorer.class; + } + + public boolean isSingleton() { + return true; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java new file mode 100644 index 000000000..043ca50d9 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java @@ -0,0 +1,141 @@ +/* + * Copyright 2002-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.core.explore.support; + +import javax.sql.DataSource; + +import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; +import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao; +import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao; +import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao; +import org.springframework.batch.core.repository.dao.JobExecutionDao; +import org.springframework.batch.core.repository.dao.JobInstanceDao; +import org.springframework.batch.core.repository.dao.StepExecutionDao; +import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; +import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.jdbc.core.simple.SimpleJdbcOperations; +import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * A {@link FactoryBean} that automates the creation of a + * {@link SimpleJobExplorer} using JDBC DAO implementations. Requires the user + * to describe what kind of database they are using. + * + * @author Dave Syer + */ +public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean implements InitializingBean { + + private DataSource dataSource; + + private SimpleJdbcOperations jdbcTemplate; + + private String databaseType; + + private String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX; + + private DataFieldMaxValueIncrementerFactory incrementerFactory; + + /** + * Public setter for the {@link DataSource}. + * @param dataSource a {@link DataSource} + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Sets the database type. + * @param dbType as specified by + * {@link DefaultDataFieldMaxValueIncrementerFactory} + */ + public void setDatabaseType(String dbType) { + this.databaseType = dbType; + } + + /** + * Sets the table prefix for all the batch meta-data tables. + * @param tablePrefix + */ + public void setTablePrefix(String tablePrefix) { + this.tablePrefix = tablePrefix; + } + + public void setIncrementerFactory(DataFieldMaxValueIncrementerFactory incrementerFactory) { + this.incrementerFactory = incrementerFactory; + } + + public void afterPropertiesSet() throws Exception { + + Assert.notNull(dataSource, "DataSource must not be null."); + + jdbcTemplate = new SimpleJdbcTemplate(dataSource); + + if (incrementerFactory == null) { + incrementerFactory = new DefaultDataFieldMaxValueIncrementerFactory(dataSource); + } + + Assert.isTrue(incrementerFactory.isSupportedIncrementerType(databaseType), "'" + databaseType + + "' is an unsupported database type. The supported database types are " + + StringUtils.arrayToCommaDelimitedString(incrementerFactory.getSupportedIncrementerTypes())); + + } + + private Object getTarget() throws Exception { + return new SimpleJobExplorer(createJobInstanceDao(), createJobExecutionDao()); + } + + @Override + protected JobInstanceDao createJobInstanceDao() throws Exception { + JdbcJobInstanceDao dao = new JdbcJobInstanceDao(); + dao.setJdbcTemplate(jdbcTemplate); + dao.setJobIncrementer(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_SEQ")); + dao.setTablePrefix(tablePrefix); + dao.afterPropertiesSet(); + return dao; + } + + @Override + protected JobExecutionDao createJobExecutionDao() throws Exception { + JdbcJobExecutionDao dao = new JdbcJobExecutionDao(); + dao.setJdbcTemplate(jdbcTemplate); + dao.setJobExecutionIncrementer(incrementerFactory.getIncrementer(databaseType, tablePrefix + + "JOB_EXECUTION_SEQ")); + dao.setJobInstanceDao(createJobInstanceDao()); + dao.setStepExecutionDao(createStepExecutionDao()); + dao.setTablePrefix(tablePrefix); + dao.afterPropertiesSet(); + return dao; + } + + protected StepExecutionDao createStepExecutionDao() throws Exception { + JdbcStepExecutionDao dao = new JdbcStepExecutionDao(); + dao.setJdbcTemplate(jdbcTemplate); + dao.setStepExecutionIncrementer(incrementerFactory.getIncrementer(databaseType, tablePrefix + + "STEP_EXECUTION_SEQ")); + dao.setTablePrefix(tablePrefix); + dao.afterPropertiesSet(); + return dao; + } + + public Object getObject() throws Exception { + return getTarget(); + } +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/MapJobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/MapJobExplorerFactoryBean.java new file mode 100644 index 000000000..a518f507a --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/MapJobExplorerFactoryBean.java @@ -0,0 +1,31 @@ +package org.springframework.batch.core.explore.support; + +import org.springframework.batch.core.repository.dao.JobExecutionDao; +import org.springframework.batch.core.repository.dao.JobInstanceDao; +import org.springframework.batch.core.repository.dao.MapJobExecutionDao; +import org.springframework.batch.core.repository.dao.MapJobInstanceDao; +import org.springframework.beans.factory.FactoryBean; + +/** + * A {@link FactoryBean} that automates the creation of a + * {@link SimpleJobExplorer} using in-memory DAO implementations. + * + * @author Dave Syer + */ +public class MapJobExplorerFactoryBean extends AbstractJobExplorerFactoryBean { + + @Override + protected JobExecutionDao createJobExecutionDao() throws Exception { + return new MapJobExecutionDao(); + } + + @Override + protected JobInstanceDao createJobInstanceDao() throws Exception { + return new MapJobInstanceDao(); + } + + public Object getObject() throws Exception { + return new SimpleJobExplorer(createJobInstanceDao(), createJobExecutionDao()); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java new file mode 100644 index 000000000..cbb9a930b --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java @@ -0,0 +1,105 @@ +/* + * 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.core.explore.support; + +import java.util.List; +import java.util.Set; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.repository.dao.JobExecutionDao; +import org.springframework.batch.core.repository.dao.JobInstanceDao; +import org.springframework.batch.core.repository.dao.StepExecutionDao; + +/** + * + *

+ * Implementation of {@link JobExplorer} using the injected DAOs. + *

+ * + * @author Dave Syer + * + * @see JobExplorer + * @see JobInstanceDao + * @see JobExecutionDao + * @see StepExecutionDao + * + */ +public class SimpleJobExplorer implements JobExplorer { + + private JobInstanceDao jobInstanceDao; + + private JobExecutionDao jobExecutionDao; + + /** + * Provide default constructor with low visibility in case user wants to use + * use aop:proxy-target-class="true" for AOP interceptor. + */ + SimpleJobExplorer() { + } + + public SimpleJobExplorer(JobInstanceDao jobInstanceDao, JobExecutionDao jobExecutionDao) { + super(); + this.jobInstanceDao = jobInstanceDao; + this.jobExecutionDao = jobExecutionDao; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#findJobExecutions(org.springframework.batch.core.JobInstance) + */ + public List findJobExecutions(JobInstance jobInstance) { + return jobExecutionDao.findJobExecutions(jobInstance); + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#findRunningJobExecutions(java.lang.String) + */ + public Set findRunningJobExecutions(String jobName) { + return jobExecutionDao.findRunningJobExecutions(jobName); + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#getJobExecution(java.lang.Long) + */ + public JobExecution getJobExecution(Long executionId) { + return jobExecutionDao.getJobExecution(executionId); + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#getJobInstance(java.lang.Long) + */ + public JobInstance getJobInstance(Long instanceId) { + return jobInstanceDao.getJobInstance(instanceId); + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#getLastJobInstances(java.lang.String, int) + */ + public List getLastJobInstances(String jobName, int count) { + return jobInstanceDao.getLastJobInstances(jobName, count); + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.explore.JobExplorer#isJobInstanceExists(java.lang.String, org.springframework.batch.core.JobParameters) + */ + public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { + return jobInstanceDao.getJobInstance(jobName, jobParameters)!=null; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/package.html b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/package.html new file mode 100644 index 000000000..68494a733 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/package.html @@ -0,0 +1,7 @@ + + +

+Specific implementations of explorer concerns. +

+ + diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java index edaf392f5..c008340b0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java @@ -35,7 +35,7 @@ import org.springframework.batch.core.UnexpectedJobExecutionException; import org.springframework.batch.core.configuration.ListableJobRegistry; import org.springframework.batch.core.converter.DefaultJobParametersConverter; import org.springframework.batch.core.converter.JobParametersConverter; -import org.springframework.batch.core.explore.BatchMetaDataExplorer; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.JobOperator; @@ -63,7 +63,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { private ListableJobRegistry jobRegistry; - private BatchMetaDataExplorer batchMetaDataExplorer; + private JobExplorer jobExplorer; private JobLauncher jobLauncher; @@ -79,7 +79,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { public void afterPropertiesSet() throws Exception { Assert.notNull(jobLauncher, "JobLauncher must be provided"); Assert.notNull(jobRegistry, "JobLocator must be provided"); - Assert.notNull(batchMetaDataExplorer, "BatchMetaDataExplorer must be provided"); + Assert.notNull(jobExplorer, "BatchMetaDataExplorer must be provided"); } /** @@ -99,11 +99,11 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { } /** - * Public setter for the {@link BatchMetaDataExplorer}. - * @param batchMetaDataExplorer the {@link BatchMetaDataExplorer} to set + * Public setter for the {@link JobExplorer}. + * @param jobExplorer the {@link JobExplorer} to set */ - public void setBatchMetaDataExplorer(BatchMetaDataExplorer batchMetaDataExplorer) { - this.batchMetaDataExplorer = batchMetaDataExplorer; + public void setJobExplorer(JobExplorer jobExplorer) { + this.jobExplorer = jobExplorer; } /** @@ -122,12 +122,12 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { * lang.Long) */ public List getExecutions(Long instanceId) throws NoSuchJobException { - JobInstance jobInstance = batchMetaDataExplorer.getJobInstance(instanceId); + JobInstance jobInstance = jobExplorer.getJobInstance(instanceId); if (jobInstance == null) { throw new NoSuchJobException(String.format("No job instance with id=%d", instanceId)); } List list = new ArrayList(); - for (JobExecution jobExecution : batchMetaDataExplorer.findJobExecutions(jobInstance)) { + for (JobExecution jobExecution : jobExplorer.findJobExecutions(jobInstance)) { list.add(jobExecution.getId()); } return list; @@ -151,7 +151,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { */ public List getLastInstances(String jobName, int count) throws NoSuchJobException { List list = new ArrayList(); - for (JobInstance jobInstance : batchMetaDataExplorer.getLastJobInstances(jobName, count)) { + for (JobInstance jobInstance : jobExplorer.getLastJobInstances(jobName, count)) { list.add(jobInstance.getId()); } return list; @@ -165,7 +165,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { * lang.Long) */ public String getParameters(Long executionId) throws NoSuchJobExecutionException { - JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + JobExecution jobExecution = jobExplorer.getJobExecution(executionId); if (jobExecution == null) { throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); } @@ -182,7 +182,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { */ public Set getRunningExecutions(String jobName) throws NoSuchJobException { Set set = new LinkedHashSet(); - for (JobExecution jobExecution : batchMetaDataExplorer.findRunningJobExecutions(jobName)) { + for (JobExecution jobExecution : jobExplorer.findRunningJobExecutions(jobName)) { set.add(jobExecution.getId()); } return set; @@ -196,7 +196,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { * (java.lang.Long) */ public Map getStepExecutionSummaries(Long executionId) throws NoSuchJobExecutionException { - JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + JobExecution jobExecution = jobExplorer.getJobExecution(executionId); if (jobExecution == null) { throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); } @@ -215,7 +215,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { * .Long) */ public String getSummary(Long executionId) throws NoSuchJobExecutionException { - JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + JobExecution jobExecution = jobExplorer.getJobExecution(executionId); if (jobExecution == null) { throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); } @@ -233,7 +233,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { logger.info("Checking status of job execution with id=" + executionId); - JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + JobExecution jobExecution = jobExplorer.getJobExecution(executionId); if (jobExecution == null) { throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); } @@ -267,7 +267,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { JobParameters jobParameters = jobParametersConverter.getJobParameters(PropertiesConverter .stringToProperties(parameters)); - if (batchMetaDataExplorer.isJobInstanceExists(jobName, jobParameters)) { + if (jobExplorer.isJobInstanceExists(jobName, jobParameters)) { throw new JobInstanceAlreadyExistsException(String.format( "Cannot start a job instance that already exists with name=%s and parameters=%s", jobName, parameters)); @@ -305,7 +305,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { logger.info("Locating parameters for next instance of job with name=" + jobName); Job job = jobRegistry.getJob(jobName); - List lastInstances = batchMetaDataExplorer.getLastJobInstances(jobName, 1); + List lastInstances = jobExplorer.getLastJobInstances(jobName, 1); JobParametersIncrementer incrementer = job.getJobParametersIncrementer(); if (incrementer == null) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/JobExplorerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/JobExplorerFactoryBeanTests.java new file mode 100644 index 000000000..3a97a5d70 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/JobExplorerFactoryBeanTests.java @@ -0,0 +1,148 @@ +/* + * Copyright 2006-2008 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.core.exlore.support; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import javax.sql.DataSource; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; +import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; + +/** + * @author Lucas Ward + * + */ +public class JobExplorerFactoryBeanTests { + + private JobExplorerFactoryBean factory; + + private DataFieldMaxValueIncrementerFactory incrementerFactory; + + private DataSource dataSource; + + private String tablePrefix = "TEST_BATCH_PREFIX_"; + + @Before + public void setUp() throws Exception { + + factory = new JobExplorerFactoryBean(); + dataSource = createMock(DataSource.class); + factory.setDataSource(dataSource); + incrementerFactory = createMock(DataFieldMaxValueIncrementerFactory.class); + factory.setIncrementerFactory(incrementerFactory); + factory.setTablePrefix(tablePrefix); + + } + + @Test + public void testNoDatabaseType() throws Exception { + + try { + expect(incrementerFactory.isSupportedIncrementerType(null)).andReturn(false); + expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]); + replay(incrementerFactory); + factory.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException ex) { + // expected + String message = ex.getMessage(); + assertTrue("Wrong message: " + message, message.indexOf("unsupported database type") >= 0); + } + + } + + @Test + public void testMissingDataSource() throws Exception { + + factory.setDataSource(null); + try { + factory.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException ex) { + // expected + String message = ex.getMessage(); + assertTrue("Wrong message: " + message, message.indexOf("DataSource") >= 0); + } + + } + + @Test + public void testInvalidDatabaseType() throws Exception { + + factory.setDatabaseType("foo"); + try { + expect(incrementerFactory.isSupportedIncrementerType("foo")).andReturn(false); + expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]); + replay(incrementerFactory); + factory.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException ex) { + // expected + String message = ex.getMessage(); + assertTrue("Wrong message: " + message, message.indexOf("foo") >= 0); + } + + } + + @Test + public void testCreateExplorer() throws Exception { + String databaseType = "foo"; + factory.setDatabaseType(databaseType); + + expect(incrementerFactory.isSupportedIncrementerType("foo")).andReturn(true); + expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]); + expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer()).times(2); + expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + replay(incrementerFactory); + + factory.afterPropertiesSet(); + factory.getObject(); + + verify(incrementerFactory); + + } + + private static class StubIncrementer implements DataFieldMaxValueIncrementer { + + public int nextIntValue() throws DataAccessException { + return 0; + } + + public long nextLongValue() throws DataAccessException { + return 0; + } + + public String nextStringValue() throws DataAccessException { + return null; + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/MapJobExplorerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/MapJobExplorerFactoryBeanTests.java new file mode 100644 index 000000000..83ed253fb --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/MapJobExplorerFactoryBeanTests.java @@ -0,0 +1,26 @@ +package org.springframework.batch.core.exlore.support; + +import org.junit.Test; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean; + +/** + * Tests for {@link MapJobExplorerFactoryBean}. + */ +public class MapJobExplorerFactoryBeanTests { + + private MapJobExplorerFactoryBean tested = new MapJobExplorerFactoryBean(); + + /** + * Use the factory to create repository and check the repository remembers + * created executions. + */ + @Test + public void testCreateRepository() throws Exception { + JobExplorer explorer = (JobExplorer) tested.getObject(); + + explorer.findRunningJobExecutions("foo"); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/SimpleJobExplorerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/SimpleJobExplorerTests.java new file mode 100644 index 000000000..922b16a93 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/exlore/support/SimpleJobExplorerTests.java @@ -0,0 +1,124 @@ +/* + * 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.core.exlore.support; + +import static org.easymock.EasyMock.createMock; + +import java.util.Collections; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.explore.support.SimpleJobExplorer; +import org.springframework.batch.core.repository.dao.JobExecutionDao; +import org.springframework.batch.core.repository.dao.JobInstanceDao; + +/** + * Test {@link SimpleJobExplorer}. + * + * @author Dave Syer + * + */ +public class SimpleJobExplorerTests extends TestCase { + + SimpleJobExplorer jobExplorer; + + JobExecutionDao jobExecutionDao; + + JobInstanceDao jobInstanceDao; + + JobInstance jobInstance = new JobInstance(111L, new JobParameters(), "job"); + + JobExecution jobExecution = new JobExecution(jobInstance, 123L); + + public void setUp() throws Exception { + + jobExecutionDao = createMock(JobExecutionDao.class); + jobInstanceDao = createMock(JobInstanceDao.class); + + jobExplorer = new SimpleJobExplorer(jobInstanceDao, jobExecutionDao); + + } + + @Test + public void testGetJobExecution() throws Exception { + jobExecutionDao.getJobExecution(123L); + EasyMock.expectLastCall().andReturn(jobExecution); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + jobExplorer.getJobExecution(123L); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testFindRunningJobExecutions() throws Exception { + jobExecutionDao.findRunningJobExecutions("job"); + EasyMock.expectLastCall().andReturn(Collections.singleton(jobExecution)); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + jobExplorer.findRunningJobExecutions("job"); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testFindJobExecutions() throws Exception { + jobExecutionDao.findJobExecutions(jobInstance); + EasyMock.expectLastCall().andReturn(Collections.singletonList(jobExecution)); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + jobExplorer.findJobExecutions(jobInstance); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testGetJobInstance() throws Exception { + jobInstanceDao.getJobInstance(111L); + EasyMock.expectLastCall().andReturn(jobInstance); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + jobExplorer.getJobInstance(111L); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testGetLastJobInstances() throws Exception { + jobInstanceDao.getLastJobInstances("foo", 1); + EasyMock.expectLastCall().andReturn(Collections.singletonList(jobInstance)); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + jobExplorer.getLastJobInstances("foo", 1); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testIsJobInstanceFalse() throws Exception { + jobInstanceDao.getJobInstance("foo", new JobParameters()); + EasyMock.expectLastCall().andReturn(null); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + assertFalse(jobExplorer.isJobInstanceExists("foo", new JobParameters())); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + + @Test + public void testIsJobInstanceTrue() throws Exception { + jobInstanceDao.getJobInstance("foo", new JobParameters()); + EasyMock.expectLastCall().andReturn(jobInstance); + EasyMock.replay(jobExecutionDao, jobInstanceDao); + assertTrue(jobExplorer.isJobInstanceExists("foo", new JobParameters())); + EasyMock.verify(jobExecutionDao, jobInstanceDao); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java index 196111ab9..c5d97cb78 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java @@ -37,7 +37,7 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.batch.core.configuration.support.MapJobRegistry; import org.springframework.batch.core.converter.DefaultJobParametersConverter; -import org.springframework.batch.core.explore.BatchMetaDataExplorer; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.job.JobSupport; import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException; import org.springframework.batch.core.launch.JobLauncher; @@ -58,7 +58,7 @@ public class SimpleJobOperatorTests { protected Job job; - private BatchMetaDataExplorer batchMetaDataExplorer; + private JobExplorer jobExplorer; private JobParameters jobParameters; @@ -102,9 +102,9 @@ public class SimpleJobOperatorTests { } }); - batchMetaDataExplorer = EasyMock.createNiceMock(BatchMetaDataExplorer.class); + jobExplorer = EasyMock.createNiceMock(JobExplorer.class); - jobOperator.setBatchMetaDataExplorer(batchMetaDataExplorer); + jobOperator.setJobExplorer(jobExplorer); jobOperator.setJobParametersConverter(new DefaultJobParametersConverter() { @Override @@ -155,31 +155,31 @@ public class SimpleJobOperatorTests { @Test public void testStartNextInstanceSunnyDay() throws Exception { final JobParameters jobParameters = new JobParameters(); - batchMetaDataExplorer.getLastJobInstances("foo", 1); + jobExplorer.getLastJobInstances("foo", 1); EasyMock.expectLastCall().andReturn(Collections.singletonList(new JobInstance(321L, jobParameters, "foo"))); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); Long value = jobOperator.startNextInstance("foo"); assertEquals(999, value.longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testStartNewInstanceSunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.isJobInstanceExists("foo", jobParameters); + jobExplorer.isJobInstanceExists("foo", jobParameters); EasyMock.expectLastCall().andReturn(false); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); Long value = jobOperator.start("foo", "a=b"); assertEquals(999, value.longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testStartNewInstanceAlreadyExists() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.isJobInstanceExists("foo", jobParameters); + jobExplorer.isJobInstanceExists("foo", jobParameters); EasyMock.expectLastCall().andReturn(true); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); try { jobOperator.start("foo", "a=b"); fail("Expected JobInstanceAlreadyExistsException"); @@ -187,82 +187,82 @@ public class SimpleJobOperatorTests { catch (JobInstanceAlreadyExistsException e) { // expected } - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testResumeSunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.getJobExecution(111L); + jobExplorer.getJobExecution(111L); EasyMock.expectLastCall() .andReturn(new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L)); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); Long value = jobOperator.resume(111L); assertEquals(999, value.longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testGetSummarySunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.getJobExecution(111L); + jobExplorer.getJobExecution(111L); JobExecution jobExecution = new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L); EasyMock.expectLastCall().andReturn(jobExecution); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); String value = jobOperator.getSummary(111L); assertEquals(jobExecution.toString(), value); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testGetStepExecutionSummariesSunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.getJobExecution(111L); + jobExplorer.getJobExecution(111L); JobExecution jobExecution = new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L); jobExecution.createStepExecution(new StepSupport("step1")); jobExecution.createStepExecution(new StepSupport("step2")); jobExecution.getStepExecutions().iterator().next().setId(21L); EasyMock.expectLastCall().andReturn(jobExecution); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); Map value = jobOperator.getStepExecutionSummaries(111L); assertEquals(2, value.size()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testFindRunningExecutionsSunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.findRunningJobExecutions("foo"); + jobExplorer.findRunningJobExecutions("foo"); JobExecution jobExecution = new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L); EasyMock.expectLastCall().andReturn(Collections.singleton(jobExecution)); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); Set value = jobOperator.getRunningExecutions("foo"); assertEquals(111L, value.iterator().next().longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testGetJobParametersSunnyDay() throws Exception { final JobParameters jobParameters = new JobParameters(); - batchMetaDataExplorer.getJobExecution(111L); + jobExplorer.getJobExecution(111L); EasyMock.expectLastCall() .andReturn(new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L)); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); String value = jobOperator.getParameters(111L); assertEquals("a=b", value); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test public void testGetLastInstancesSunnyDay() throws Exception { jobParameters = new JobParameters(); - batchMetaDataExplorer.getLastJobInstances("foo",2); + jobExplorer.getLastJobInstances("foo",2); JobInstance jobInstance = new JobInstance(123L, jobParameters, job.getName()); EasyMock.expectLastCall().andReturn(Collections.singletonList(jobInstance)); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); List value = jobOperator.getLastInstances("foo",2); assertEquals(123L, value.get(0).longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } @Test @@ -275,15 +275,15 @@ public class SimpleJobOperatorTests { @Test public void testGetExecutionsSunnyDay() throws Exception { JobInstance jobInstance = new JobInstance(123L, jobParameters, job.getName()); - batchMetaDataExplorer.getJobInstance(123L); + jobExplorer.getJobInstance(123L); EasyMock.expectLastCall().andReturn(jobInstance); JobExecution jobExecution = new JobExecution(jobInstance, 111L); - batchMetaDataExplorer.findJobExecutions(jobInstance); + jobExplorer.findJobExecutions(jobInstance); EasyMock.expectLastCall().andReturn(Collections.singletonList(jobExecution)); - EasyMock.replay(batchMetaDataExplorer); + EasyMock.replay(jobExplorer); List value = jobOperator.getExecutions(123L); assertEquals(111L, value.iterator().next().longValue()); - EasyMock.verify(batchMetaDataExplorer); + EasyMock.verify(jobExplorer); } }