OPEN - issue BATCH-1407: Integration tests for core (including multi-threaded long running tests)
This commit is contained in:
@@ -7,16 +7,11 @@ batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true
|
||||
# batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples
|
||||
batch.jdbc.user=sa
|
||||
batch.jdbc.password=
|
||||
batch.schema=
|
||||
batch.jndi.name=
|
||||
batch.naming.factory.initial=
|
||||
batch.naming.provider.url=
|
||||
batch.schema.script=schema-hsqldb.sql
|
||||
batch.drop.script=schema-drop-hsqldb.sql
|
||||
batch.business.schema.script=business-schema-hsqldb.sql
|
||||
batch.jdbc.testWhileIdle=false
|
||||
batch.jdbc.validationQuery=
|
||||
batch.schema.script=classpath:/org/springframework/batch/core/schema-hsqldb.sql
|
||||
batch.business.schema.script=classpath:/business-schema-hsqldb.sql
|
||||
batch.data.source.init=true
|
||||
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer
|
||||
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
|
||||
|
||||
# Bean Properties for override
|
||||
# when not using sequences:
|
||||
incrementerParent.columnName=ID
|
||||
batch.database.incrementer.parent=columnIncrementerParent
|
||||
batch.grid.size=2
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<!-- Initialise the database before every test case: -->
|
||||
<bean id="dataSourceInitializer" class="com.springsource.batch.test.datasource.DataSourceInitializer">
|
||||
<property name="initialize" value="${batch.data.source.init}" />
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="initScripts">
|
||||
<list>
|
||||
<value>${batch.schema.script}</value>
|
||||
<value>${batch.business.schema.script}
|
||||
</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Set up or detect a System property called "environment" used to
|
||||
construct a properties file on the classpath. The default is
|
||||
determined from the data source.
|
||||
-->
|
||||
<bean id="environment"
|
||||
class="org.springframework.batch.support.SystemPropertyInitializer">
|
||||
<property name="defaultValue" value="hsql"/>
|
||||
</bean>
|
||||
|
||||
<!-- Use this to set additional properties on beans at run time -->
|
||||
<bean id="placeholderProperties"
|
||||
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
|
||||
depends-on="environment">
|
||||
<property name="location"
|
||||
value="classpath:batch-${org.springframework.batch.support.SystemPropertyInitializer.ENVIRONMENT}.properties" />
|
||||
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
|
||||
<property name="ignoreUnresolvablePlaceholders" value="false" />
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
|
||||
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob" abstract="true">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="restartable" value="true" />
|
||||
</bean>
|
||||
|
||||
<bean id="taskletStep" class="org.springframework.batch.core.step.tasklet.TaskletStep" abstract="true">
|
||||
<property name="transactionManager" ref="transactionManager" />
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="allowStartIfComplete" value="true" />
|
||||
</bean>
|
||||
|
||||
<bean id="simpleStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" abstract="true">
|
||||
<property name="transactionManager" ref="transactionManager" />
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="startLimit" value="100" />
|
||||
<property name="commitInterval" value="1" />
|
||||
</bean>
|
||||
|
||||
<bean id="skipLimitStep" class="org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean" parent="simpleStep"
|
||||
abstract="true">
|
||||
<property name="skipLimit" value="0" />
|
||||
</bean>
|
||||
|
||||
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="taskExecutor" ref="taskExecutor" />
|
||||
</bean>
|
||||
|
||||
<bean id="poolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
|
||||
<property name="corePoolSize" value="2"></property>
|
||||
<property name="maxPoolSize" value="20"></property>
|
||||
</bean>
|
||||
|
||||
<bean id="taskExecutor" parent="poolTaskExecutor" />
|
||||
|
||||
<bean id="throttledTaskExecutor" class="com.springsource.batch.util.ThrottledTaskExecutor">
|
||||
<property name="taskExecutor">
|
||||
<bean parent="poolTaskExecutor" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
|
||||
p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" />
|
||||
|
||||
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
|
||||
p:dataSource-ref="dataSource" />
|
||||
|
||||
<bean id="jobLoader" class="org.springframework.batch.core.configuration.support.ClassPathXmlJobLoader">
|
||||
<property name="jobPaths" value="classpath*:/META-INF/batch/*-context.xml" />
|
||||
<property name="jobRegistry" ref="jobRegistry"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
|
||||
|
||||
<bean class="com.springsource.batch.service.JdbcSearchableJobExecutionDao">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.batch.core.repository.dao.JdbcExecutionContextDao">
|
||||
<property name="jdbcTemplate">
|
||||
<bean class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
|
||||
<constructor-arg ref="dataSource" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="com.springsource.batch.service.JdbcSearchableStepExecutionDao">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
<bean class="com.springsource.batch.service.JdbcSearchableJobInstanceDao">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
<bean class="com.springsource.batch.service.SimpleJobService" />
|
||||
|
||||
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
|
||||
<property name="customEditors">
|
||||
<map>
|
||||
<entry key="int[]" value="org.springframework.batch.support.IntArrayPropertyEditor" />
|
||||
<entry key="double[]" value="org.springframework.batch.support.IntArrayPropertyEditor" />
|
||||
<entry key="java.lang.Class[]" value="org.springframework.beans.propertyeditors.ClassArrayEditor" />
|
||||
<entry key="org.springframework.batch.item.file.transform.Range[]" value="org.springframework.batch.item.file.transform.RangeArrayPropertyEditor" />
|
||||
<!--
|
||||
entry key="java.util.Date"> <bean class="org.springframework.beans.propertyeditors.CustomDateEditor">
|
||||
<constructor-arg> <bean class="java.text.SimpleDateFormat"> <constructor-arg value="yyyyMMdd" /> </bean>
|
||||
</constructor-arg> <constructor-arg value="false" /> </bean> </entry
|
||||
-->
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -1,6 +0,0 @@
|
||||
DROP TABLE T_FOOS;
|
||||
create table T_FOOS (
|
||||
id integer not null primary key,
|
||||
name varchar(80),
|
||||
foo_date timestamp
|
||||
);
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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.test.repository;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml" })
|
||||
public class JdbcJobRepositoryTests {
|
||||
|
||||
private JobRepository repository;
|
||||
|
||||
private JobSupport job;
|
||||
|
||||
private Set<Long> jobExecutionIds = new HashSet<Long>();
|
||||
|
||||
private Set<Long> jobIds = new HashSet<Long>();
|
||||
|
||||
private List<Serializable> list = new ArrayList<Serializable>();
|
||||
|
||||
private SimpleJdbcTemplate simpleJdbcTemplate;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
/** Logger */
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRepository(JobRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void onSetUpInTransaction() throws Exception {
|
||||
job = new JobSupport("test-job");
|
||||
job.setRestartable(true);
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION_CONTEXT");
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_CONTEXT");
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION");
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION");
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_PARAMS");
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_INSTANCE");
|
||||
}
|
||||
|
||||
@AfterTransaction
|
||||
public void onTearDownAfterTransaction() throws Exception {
|
||||
for (Long id : jobExecutionIds) {
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_CONTEXT where JOB_EXECUTION_ID=?", id);
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=?", id);
|
||||
}
|
||||
for (Long id : jobIds) {
|
||||
simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", id);
|
||||
}
|
||||
for (Long id : jobIds) {
|
||||
int count = simpleJdbcTemplate.queryForInt(
|
||||
"SELECT COUNT(*) FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", id);
|
||||
assertEquals(0, count);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Test
|
||||
public void testFindOrCreateJob() throws Exception {
|
||||
job.setName("foo");
|
||||
int before = 0;
|
||||
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
|
||||
int after = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
|
||||
assertEquals(before + 1, after);
|
||||
assertNotNull(execution.getId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Test
|
||||
public void testFindOrCreateJobConcurrently() throws Exception {
|
||||
|
||||
job.setName("bar");
|
||||
|
||||
int before = 0;
|
||||
assertEquals(0, before);
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
try {
|
||||
doConcurrentStart();
|
||||
fail("Expected JobExecutionAlreadyRunningException");
|
||||
}
|
||||
catch (JobExecutionAlreadyRunningException e) {
|
||||
// expected
|
||||
}
|
||||
long t1 = System.currentTimeMillis();
|
||||
|
||||
JobExecution execution = (JobExecution) list.get(0);
|
||||
|
||||
assertNotNull(execution);
|
||||
|
||||
int after = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
|
||||
assertNotNull(execution.getId());
|
||||
assertEquals(before + 1, after);
|
||||
|
||||
logger.info("Duration: " + (t1 - t0)
|
||||
+ " - the second transaction did not block if this number is less than about 1000.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOrCreateJobConcurrentlyWhenJobAlreadyExists() throws Exception {
|
||||
|
||||
job = new JobSupport("test-job");
|
||||
job.setRestartable(true);
|
||||
job.setName("spam");
|
||||
|
||||
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
|
||||
cacheJobIds(execution);
|
||||
execution.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
repository.update(execution);
|
||||
execution.setStatus(BatchStatus.FAILED);
|
||||
|
||||
int before = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
|
||||
assertEquals(1, before);
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
try {
|
||||
doConcurrentStart();
|
||||
fail("Expected JobExecutionAlreadyRunningException");
|
||||
}
|
||||
catch (JobExecutionAlreadyRunningException e) {
|
||||
// expected
|
||||
}
|
||||
long t1 = System.currentTimeMillis();
|
||||
|
||||
int after = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
|
||||
assertNotNull(execution.getId());
|
||||
assertEquals(before, after);
|
||||
|
||||
logger.info("Duration: " + (t1 - t0)
|
||||
+ " - the second transaction did not block if this number is less than about 1000.");
|
||||
}
|
||||
|
||||
private void cacheJobIds(JobExecution execution) {
|
||||
if (execution == null)
|
||||
return;
|
||||
jobExecutionIds.add(execution.getId());
|
||||
jobIds.add(execution.getJobId());
|
||||
}
|
||||
|
||||
private JobExecution doConcurrentStart() throws Exception {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
|
||||
public Object doInTransaction(org.springframework.transaction.TransactionStatus status) {
|
||||
try {
|
||||
JobExecution execution = repository.createJobExecution(job.getName(),
|
||||
new JobParameters());
|
||||
cacheJobIds(execution);
|
||||
list.add(execution);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (Exception e) {
|
||||
list.add(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
list.add(e);
|
||||
}
|
||||
|
||||
}
|
||||
}).start();
|
||||
|
||||
Thread.sleep(400);
|
||||
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
|
||||
cacheJobIds(execution);
|
||||
|
||||
int count = 0;
|
||||
while (list.size() == 0 && count++ < 100) {
|
||||
Thread.sleep(200);
|
||||
}
|
||||
|
||||
assertEquals("Timed out waiting for JobExecution to be created", 1, list.size());
|
||||
assertTrue("JobExecution not created in thread", list.get(0) instanceof JobExecution);
|
||||
return (JobExecution) list.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.test.repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParametersIncrementer;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.UnexpectedJobExecutionException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Batch domain object representing a job. Job is an explicit abstraction
|
||||
* representing the configuration of a job specified by a developer. It should
|
||||
* be noted that restart policy is applied to the job as a whole and not to a
|
||||
* step.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class JobSupport implements BeanNameAware, Job {
|
||||
|
||||
private List<Step> steps = new ArrayList<Step>();
|
||||
|
||||
private String name;
|
||||
|
||||
private boolean restartable = false;
|
||||
|
||||
private int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public JobSupport() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience constructor to immediately add name (which is mandatory but
|
||||
* not final).
|
||||
*
|
||||
* @param name the name
|
||||
*/
|
||||
public JobSupport(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property if it is not already set. Because of the order of
|
||||
* the callbacks in a Spring container the name property will be set first
|
||||
* if it is present. Care is needed with bean definition inheritance - if a
|
||||
* parent bean has a name, then its children need an explicit name as well,
|
||||
* otherwise they will not be unique.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
if (this.name == null) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property. Always overrides the default value if this object
|
||||
* is a Spring bean.
|
||||
*
|
||||
* @see #setBeanName(java.lang.String)
|
||||
* @param name the name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.domain.IJob#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setSteps(List<Step> steps) {
|
||||
this.steps.clear();
|
||||
this.steps.addAll(steps);
|
||||
}
|
||||
|
||||
public void addStep(Step step) {
|
||||
this.steps.add(step);
|
||||
}
|
||||
|
||||
public List<Step> getSteps() {
|
||||
return steps;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.domain.IJob#getStartLimit()
|
||||
*/
|
||||
public int getStartLimit() {
|
||||
return startLimit;
|
||||
}
|
||||
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
public void setRestartable(boolean restartable) {
|
||||
this.restartable = restartable;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.domain.IJob#isRestartable()
|
||||
*/
|
||||
public boolean isRestartable() {
|
||||
return restartable;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.Job#getJobParametersIncrementer()
|
||||
*/
|
||||
public JobParametersIncrementer getJobParametersIncrementer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution)
|
||||
*/
|
||||
public void execute(JobExecution execution) throws UnexpectedJobExecutionException {
|
||||
throw new UnsupportedOperationException("JobSupport does not provide an implementation of run(). Use a smarter subclass.");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop
|
||||
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<import resource="simple-job-launcher-context.xml" />
|
||||
|
||||
<bean class="org.springframework.jmx.export.MBeanExporter">
|
||||
<property name="beans">
|
||||
<map>
|
||||
<entry key="spring:service=batch,bean=jobOperator">
|
||||
<bean class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="target" ref="jobOperator" />
|
||||
<property name="interceptorNames" value="exceptionTranslator" />
|
||||
</bean>
|
||||
</entry>
|
||||
<entry key="spring:service=batch,bean=jobLoader" value-ref="loader" />
|
||||
</map>
|
||||
</property>
|
||||
<property name="assembler">
|
||||
<bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
|
||||
<property name="interfaceMappings">
|
||||
<map>
|
||||
<entry key="spring:service=batch,bean=jobOperator" value="org.springframework.batch.core.launch.JobOperator" />
|
||||
<entry key="spring:service=batch,bean=jobLoader" value="org.springframework.batch.core.test.launch.JobLoader" />
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
|
||||
<bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator">
|
||||
<property name="jobExplorer">
|
||||
<bean class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="jobRegistry" ref="jobRegistry" />
|
||||
<property name="jobLauncher">
|
||||
<bean parent="jobLauncher">
|
||||
<property name="taskExecutor">
|
||||
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="exceptionTranslator" class="org.springframework.batch.core.launch.support.RuntimeExceptionTranslator" />
|
||||
<bean id="loader" class="org.springframework.batch.core.test.launch.DefaultJobLoader">
|
||||
<property name="registry" ref="jobRegistry" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,18 @@
|
||||
# Placeholders batch.*
|
||||
# for Derby:
|
||||
batch.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
|
||||
batch.jdbc.url=jdbc:derby:derby-home/test;create=true
|
||||
batch.jdbc.user=sa
|
||||
batch.jdbc.password=
|
||||
batch.schema=
|
||||
batch.jndi.name=
|
||||
batch.naming.factory.initial=
|
||||
batch.naming.provider.url=
|
||||
batch.schema.script=schema-derby.sql
|
||||
batch.business.schema.script=business-schema-derby.sql
|
||||
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.DerbyMaxValueIncrementer
|
||||
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
|
||||
|
||||
# Bean Properties for override
|
||||
# when not using sequences:
|
||||
incrementerParent.columnName=ID
|
||||
@@ -0,0 +1,17 @@
|
||||
# Placeholders batch.*
|
||||
# for HSQLDB:
|
||||
batch.jdbc.driver=org.hsqldb.jdbcDriver
|
||||
batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true
|
||||
# use this one for a separate server process so you can inspect the results
|
||||
# (or add it to system properties with -D to override at run time).
|
||||
# batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples
|
||||
batch.jdbc.user=sa
|
||||
batch.jdbc.password=
|
||||
batch.jdbc.testWhileIdle=false
|
||||
batch.jdbc.validationQuery=
|
||||
batch.schema.script=classpath:/org/springframework/batch/core/schema-hsqldb.sql
|
||||
batch.business.schema.script=classpath:/business-schema-hsqldb.sql
|
||||
batch.data.source.init=true
|
||||
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer
|
||||
batch.database.incrementer.parent=columnIncrementerParent
|
||||
batch.grid.size=2
|
||||
@@ -0,0 +1,19 @@
|
||||
# Placeholders batch.*
|
||||
# for MySQL:
|
||||
batch.jdbc.driver=com.mysql.jdbc.Driver
|
||||
batch.jdbc.url=jdbc:mysql://localhost/test
|
||||
batch.jdbc.user=root
|
||||
batch.jdbc.password=root
|
||||
batch.schema=
|
||||
batch.jndi.name=
|
||||
batch.naming.factory.initial=
|
||||
batch.naming.provider.url=
|
||||
batch.schema.script=schema-mysql.sql
|
||||
batch.drop.script=schema-drop-mysql.sql
|
||||
batch.business.schema.script=business-schema-mysql.sql
|
||||
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer
|
||||
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
|
||||
|
||||
# Bean Properties for override
|
||||
# when not using sequences:
|
||||
incrementerParent.columnName=ID
|
||||
@@ -7,7 +7,7 @@
|
||||
<!-- Initialise the database before every test case: -->
|
||||
<bean id="dataSourceInitializer" class="test.jdbc.datasource.DataSourceInitializer">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
<property name=""></property>
|
||||
<property name="initialize" value="${batch.data.source.init}"/>
|
||||
<property name="initScripts">
|
||||
<list>
|
||||
<value>${batch.drop.script}</value>
|
||||
@@ -17,7 +17,7 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||
<property name="driverClassName" value="${batch.jdbc.driver}" />
|
||||
<property name="url" value="${batch.jdbc.url}" />
|
||||
<property name="username" value="${batch.jdbc.user}" />
|
||||
@@ -55,9 +55,16 @@
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
|
||||
<bean id="incrementerParent" class="${batch.database.incrementer.class}" abstract="true">
|
||||
<bean id="sequenceIncrementerParent" class="${batch.database.incrementer.class}" abstract="true">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="incrementerName" value="ID" />
|
||||
</bean>
|
||||
|
||||
<bean id="columnIncrementerParent" class="${batch.database.incrementer.class}" abstract="true" parent="sequenceIncrementerParent">
|
||||
<property name="columnName" value="ID" />
|
||||
</bean>
|
||||
|
||||
<bean id="incrementerParent" parent="${batch.database.incrementer.parent}">
|
||||
<property name="incrementerName" value="DUMMY" />
|
||||
</bean>
|
||||
|
||||
<!--import resource="alt-data-source-context.xml" /-->
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/batch
|
||||
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
|
||||
http://www.springframework.org/schema/aop
|
||||
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<!-- The tasklet used in this job will run in an infinite loop. This is useful for testing graceful shutdown from
|
||||
multiple environments. -->
|
||||
|
||||
<job id="loopJob" incrementer="jobParametersIncrementer" xmlns="http://www.springframework.org/schema/batch">
|
||||
<step id="step1">
|
||||
<tasklet>
|
||||
<chunk reader="reader" writer="writer" commit-interval="3"/>
|
||||
</tasklet>
|
||||
</step>
|
||||
</job>
|
||||
|
||||
<bean id="reader" class="org.springframework.batch.core.test.launch.InfiniteLoopReader" />
|
||||
<bean id="writer" class="org.springframework.batch.core.test.launch.InfiniteLoopWriter" />
|
||||
|
||||
<bean id="jobParametersIncrementer"
|
||||
class="org.springframework.batch.core.launch.support.RunIdIncrementer"/>
|
||||
|
||||
</beans>
|
||||
12
spring-batch-core-tests/src/test/resources/log4j.properties
Normal file
12
spring-batch-core-tests/src/test/resources/log4j.properties
Normal file
@@ -0,0 +1,12 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%L - %m%n
|
||||
|
||||
log4j.category.org.apache.activemq=ERROR
|
||||
# log4j.category.org.springframework=DEBUG
|
||||
log4j.category.org.springframework.jdbc=DEBUG
|
||||
log4j.category.org.springframework.jms=DEBUG
|
||||
log4j.category.org.springframework.batch=DEBUG
|
||||
log4j.category.org.springframework.retry=DEBUG
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
<import resource="data-source-context.xml" />
|
||||
|
||||
<bean id="jobLauncher"
|
||||
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
|
||||
<property name="jobRegistry" ref="jobRegistry"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jobRepository"
|
||||
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
|
||||
p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" />
|
||||
|
||||
<bean id="mapJobRepository"
|
||||
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"
|
||||
lazy-init="true" autowire-candidate="false" />
|
||||
|
||||
<bean id="jobOperator"
|
||||
class="org.springframework.batch.core.launch.support.SimpleJobOperator"
|
||||
p:jobLauncher-ref="jobLauncher" p:jobExplorer-ref="jobExplorer"
|
||||
p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry" />
|
||||
|
||||
<bean id="jobExplorer"
|
||||
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
|
||||
p:dataSource-ref="dataSource" />
|
||||
|
||||
<bean id="jobRegistry"
|
||||
class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
|
||||
|
||||
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user