Initial move over from i21 repo.

This commit is contained in:
dsyer
2007-08-15 20:04:43 +00:00
parent 3237c34eb5
commit 170c815916
781 changed files with 67769 additions and 181 deletions

View File

@@ -0,0 +1,75 @@
/*
* 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.bootstrap;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.execution.bootstrap.BatchCommandLineLauncher;
import junit.framework.TestCase;
/**
* @author Dave Syer
*
*/
public class BatchCommandLineLauncherTests extends TestCase {
BatchCommandLineLauncher commandLine = new BatchCommandLineLauncher();
int count = 0;
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.BatchCommandLineLauncher#main(java.lang.String[])}.
* @throws Exception
*/
public void testMainWithDefaultArguments() throws Exception {
BatchCommandLineLauncher.main(new String[0]);
// TODO: find a way to assert something. No error actually
// means the test was successful...
}
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.BatchCommandLineLauncher#main(java.lang.String[])}.
* @throws Exception
*/
public void testMainWithParentContext() throws Exception {
// Try an XML file name for the parent context with no suffix
BatchCommandLineLauncher.main(new String[]{"job-configuration"});
}
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.BatchCommandLineLauncher#main(java.lang.String[])}.
* @throws Exception
*/
public void testMainWithParentContextAndValidJobId() throws Exception {
// Try a job id as the second argument
BatchCommandLineLauncher.main(new String[]{"job-configuration", "test-job"});
}
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.BatchCommandLineLauncher#main(java.lang.String[])}.
* @throws Exception
*/
public void testMainWithParentContextAndInvalidJobId() throws Exception {
// Try a job id as the second argument test-job
try {
BatchCommandLineLauncher.main(new String[]{"job-configuration", "foo-bar-spam"});
fail("Expected NoSuchJobConfigurationException");
}
catch (NoSuchJobConfigurationException e) {
// expected
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.bootstrap;
import junit.framework.TestCase;
import org.springframework.batch.execution.bootstrap.BatchExecutionRequestEvent;
import org.springframework.context.ApplicationEvent;
/**
* @author Dave Syer
*
*/
public class BatchExecutionRequestEventTests extends TestCase {
/**
* Test method for {@link org.springframework.batch.execution.bootstrap.BatchExecutionRequestEvent#BatchContainerRequestEvent(java.lang.Object)}.
*/
public void testBatchContainerRequestEvent() {
ApplicationEvent event = new BatchExecutionRequestEvent(this);
assertEquals(this, event.getSource());
}
}

View File

@@ -0,0 +1,195 @@
/*
* 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.bootstrap;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.runtime.JobIdentifier;
import org.springframework.batch.core.runtime.JobIdentifierFactory;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.execution.JobExecutorFacade;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.GenericApplicationContext;
public class SimpleJobLauncherTests extends TestCase {
public void testAutoStartContainer() throws Exception {
MockControl containerControl = MockControl.createControl(JobExecutorFacade.class);
JobExecutorFacade mockContainer;
AbstractJobLauncher bootstrap = new SimpleJobLauncher();
final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo");
bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() {
public JobIdentifier getJobIdentifier(String name) {
return runtimeInformation;
}
});
mockContainer = (JobExecutorFacade) containerControl.getMock();
bootstrap.setBatchContainer(mockContainer);
JobConfiguration jobConfiguration = new JobConfiguration("foo");
bootstrap.setJobConfigurationName(jobConfiguration.getName());
mockContainer.start(runtimeInformation);
containerControl.replay();
bootstrap.setAutoStart(true);
bootstrap.onApplicationEvent(new ContextRefreshedEvent(new GenericApplicationContext()));
// It ran and then stopped...
assertFalse(bootstrap.isRunning());
containerControl.verify();
}
public void testApplicationEventNotContextRefresh() throws Exception {
MockControl containerControl = MockControl.createControl(JobExecutorFacade.class);
JobExecutorFacade mockContainer;
AbstractJobLauncher bootstrap = new SimpleJobLauncher();
mockContainer = (JobExecutorFacade) containerControl.getMock();
bootstrap.setBatchContainer(mockContainer);
containerControl.replay();
bootstrap.setAutoStart(true);
bootstrap.onApplicationEvent(new ApplicationEvent(new GenericApplicationContext()) {
});
assertFalse(bootstrap.isRunning());
containerControl.verify();
}
public void testStartWithNoConfiguration() throws Exception {
final AbstractJobLauncher bootstrap = new SimpleJobLauncher();
try {
bootstrap.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
assertTrue(e.getMessage().indexOf("required") >= 0);
}
}
public void testInitializeWithNoConfiguration() throws Exception {
final AbstractJobLauncher bootstrap = new SimpleJobLauncher();
try {
bootstrap.start();
// should do nothing
}
catch (Exception e) {
fail("Unexpected IllegalStateException");
}
}
public void testStartTwiceNotFatal() throws Exception {
AbstractJobLauncher bootstrap = new SimpleJobLauncher();
final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo");
bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() {
public JobIdentifier getJobIdentifier(String name) {
return runtimeInformation;
}
});
InterruptibleContainer container = new InterruptibleContainer();
bootstrap.setBatchContainer(container);
bootstrap.setJobConfigurationName(new JobConfiguration("foo").getName());
bootstrap.start();
bootstrap.start();
// Both jobs finished running because they were not launched in a new
// Thread
assertFalse(bootstrap.isRunning());
}
public void testInterruptContainer() throws Exception {
final AbstractJobLauncher bootstrap = new SimpleJobLauncher();
final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo");
bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() {
public JobIdentifier getJobIdentifier(String name) {
return runtimeInformation;
}
});
InterruptibleContainer container = new InterruptibleContainer();
bootstrap.setBatchContainer(container);
bootstrap.setJobConfigurationName(new JobConfiguration("foo").getName());
Thread bootstrapThread = new Thread() {
public void run() {
bootstrap.start();
}
};
bootstrapThread.start();
// give the thread a second to start up
Thread.sleep(100);
assertTrue(bootstrap.isRunning());
bootstrap.stop();
Thread.sleep(100);
assertFalse(bootstrap.isRunning());
}
public void testStopOnUnstartedContainer() {
AbstractJobLauncher bootstrap = new SimpleJobLauncher();
assertFalse(bootstrap.isRunning());
// no exception should be thrown if stop is called on unstarted
// container
// this is to fullfill the contract outlined in Lifecycle#stop().
bootstrap.stop();
}
private class InterruptibleContainer implements JobExecutorFacade {
/*
* (non-Javadoc)
* @see org.springframework.batch.container.BatchContainer#start()
*/
public void start() {
try {
// 1 seconds should be long enough to allow the thread to be
// started and
// for interrupt to be called;
Thread.sleep(300);
}
catch (InterruptedException ex) {
// thread interrupted, allow to exit normally
}
}
public void start(JobIdentifier runtimeInformation) {
start();
}
public void stop(JobIdentifier runtimeInformation) {
// not needed
}
public boolean isRunning() {
// not needed
return false;
}
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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.bootstrap;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.management.Notification;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.runtime.JobIdentifier;
import org.springframework.batch.core.runtime.JobIdentifierFactory;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.execution.JobExecutorFacade;
import org.springframework.batch.repeat.interceptor.RepeatOperationsApplicationEvent;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.jmx.export.notification.NotificationPublisher;
import org.springframework.jmx.export.notification.UnableToSendNotificationException;
public class TaskExecutorJobLauncherTests extends TestCase {
private TaskExecutorJobLauncher bootstrap = new TaskExecutorJobLauncher();
protected void setUp() throws Exception {
super.setUp();
final SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo");
bootstrap.setJobRuntimeInformationFactory(new JobIdentifierFactory() {
public JobIdentifier getJobIdentifier(String name) {
return runtimeInformation;
}
});
}
public void testStopContainer() throws Exception {
// Important (otherwise start() does not return!)
bootstrap.setTaskExecutor(new SimpleAsyncTaskExecutor());
InterruptibleContainer container = new InterruptibleContainer();
bootstrap.setBatchContainer(container);
bootstrap.setJobConfigurationName(new JobConfiguration("foo").getName());
bootstrap.start();
// give the thread some time to start up:
Thread.sleep(100);
assertTrue(bootstrap.isRunning());
bootstrap.stop();
// ...and to shut down:
Thread.sleep(400);
assertFalse(bootstrap.isRunning());
}
public void testNormalApplicationEventNotRecognized() throws Exception {
bootstrap.onApplicationEvent(new ApplicationEvent("foo") {});
// nothing happens
}
public void testRepeatOperationsBeforeNotUsed() throws Exception {
final List list = new ArrayList();
bootstrap.setNotificationPublisher(new NotificationPublisher() {
public void sendNotification(Notification notification) throws UnableToSendNotificationException {
list.add(notification);
}
});
bootstrap.onApplicationEvent(new RepeatOperationsApplicationEvent(this, "foo", RepeatOperationsApplicationEvent.BEFORE) {});
assertEquals(0, list.size());
}
public void testRepeatOperationsOpenUsed() throws Exception {
final List list = new ArrayList();
bootstrap.setNotificationPublisher(new NotificationPublisher() {
public void sendNotification(Notification notification) throws UnableToSendNotificationException {
list.add(notification);
}
});
bootstrap.onApplicationEvent(new RepeatOperationsApplicationEvent(this, "foo", RepeatOperationsApplicationEvent.OPEN));
assertEquals(1, list.size());
assertEquals("foo", ((Notification) list.get(0)).getMessage().substring(0, 3));
}
public void testStatisticsRetrieved() throws Exception {
MockControl control = MockControl.createControl(JobExecutorFacadeWithStatistics.class);
JobExecutorFacadeWithStatistics batchContainer = (JobExecutorFacadeWithStatistics) control.getMock();
bootstrap.setBatchContainer(batchContainer);
Properties properties = PropertiesConverter.stringToProperties("a=b");
control.expectAndReturn(batchContainer.getStatistics(), properties);
control.replay();
assertEquals(properties, bootstrap.getStatistics());
control.verify();
}
public void testStatisticsNotRetrieved() throws Exception {
MockControl control = MockControl.createControl(JobExecutorFacade.class);
JobExecutorFacade batchContainer = (JobExecutorFacade) control.getMock();
bootstrap.setBatchContainer(batchContainer);
Properties properties = new Properties();
control.replay();
assertEquals(properties, bootstrap.getStatistics());
control.verify();
}
private class InterruptibleContainer implements JobExecutorFacade {
private volatile boolean running = true;
public void start() {
while (running) {
try {
// 1 seconds should be long enough to allow the thread to be
// started and
// for interrupt to be called;
Thread.sleep(300);
}
catch (InterruptedException ex) {
// thread intterrupted, allow to exit normally
}
}
}
public void start(JobIdentifier runtimeInformation) {
start();
}
public void stop(JobIdentifier runtimeInformation) {
running = false;
}
public boolean isRunning() {
// not needed
return false;
}
}
public void testPublishApplicationEvent() throws Exception {
final List list = new ArrayList();
bootstrap.setApplicationEventPublisher(new ApplicationEventPublisher() {
public void publishEvent(ApplicationEvent event) {
list.add(event);
}
});
MockControl control = MockControl.createControl(JobExecutorFacade.class);
JobExecutorFacade batchContainer = (JobExecutorFacade) control.getMock();
bootstrap.setBatchContainer(batchContainer);
SimpleJobIdentifier jobRuntimeInformation = new SimpleJobIdentifier("spam");
batchContainer.start(jobRuntimeInformation);
control.setThrowable(new NoSuchJobConfigurationException("SPAM"));
control.replay();
bootstrap.start(jobRuntimeInformation);
assertEquals(1, list.size());
control.verify();
}
private interface JobExecutorFacadeWithStatistics extends JobExecutorFacade, StatisticsProvider {
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.configuration;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.DuplicateJobConfigurationException;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.execution.configuration.JobConfigurationRegistryBeanPostProcessor;
import org.springframework.batch.execution.configuration.MapJobConfigurationRegistry;
import org.springframework.beans.FatalBeanException;
/**
* @author Dave Syer
*
*/
public class JobConfigurationRegistryBeanPostProcessorTests extends TestCase {
private JobConfigurationRegistryBeanPostProcessor processor = new JobConfigurationRegistryBeanPostProcessor();
public void testInitialization() throws Exception {
try {
processor.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// expected
assertTrue(e.getMessage().indexOf("JobConfigurationRegistry") >= 0);
}
}
public void testBeforeInitialization() throws Exception {
// should be a no-op
assertEquals("foo", processor.postProcessAfterInitialization("foo", "bar"));
}
public void testAfterInitializationWithWrongType() throws Exception {
// should be a no-op
assertEquals("foo", processor.postProcessAfterInitialization("foo", "bar"));
}
public void testAfterInitializationWithCorrectType() throws Exception {
MapJobConfigurationRegistry registry = new MapJobConfigurationRegistry();
processor.setJobConfigurationRegistry(registry);
JobConfiguration configuration = new JobConfiguration();
configuration.setName("foo");
assertEquals(configuration, processor.postProcessAfterInitialization(configuration, "bar"));
assertEquals(configuration, registry.getJobConfiguration("foo"));
}
public void testAfterInitializationWithDuplicate() throws Exception {
MapJobConfigurationRegistry registry = new MapJobConfigurationRegistry();
processor.setJobConfigurationRegistry(registry);
JobConfiguration configuration = new JobConfiguration();
configuration.setName("foo");
processor.postProcessAfterInitialization(configuration, "bar");
try {
processor.postProcessAfterInitialization(configuration, "spam");
fail("Expected FatalBeanException");
} catch (FatalBeanException e) {
// Expected
assertTrue(e.getCause() instanceof DuplicateJobConfigurationException);
}
}
public void testUnregisterOnDestroy() throws Exception {
MapJobConfigurationRegistry registry = new MapJobConfigurationRegistry();
processor.setJobConfigurationRegistry(registry);
JobConfiguration configuration = new JobConfiguration();
configuration.setName("foo");
assertEquals(configuration, processor.postProcessAfterInitialization(configuration, "bar"));
processor.destroy();
try {
assertEquals(null, registry.getJobConfiguration("foo"));
fail("Expected NoSuchJobConfigurationException");
} catch (NoSuchJobConfigurationException e) {
// expected
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.configuration;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.DuplicateJobConfigurationException;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.execution.configuration.MapJobConfigurationRegistry;
/**
* @author Dave Syer
*
*/
public class MapJobConfigurationRegistryTests extends TestCase {
private MapJobConfigurationRegistry registry = new MapJobConfigurationRegistry();
/**
* Test method for {@link org.springframework.batch.execution.configuration.MapJobConfigurationRegistry#unregister(org.springframework.batch.core.configuration.JobConfiguration)}.
* @throws Exception
*/
public void testUnregister() throws Exception {
registry.register(new JobConfiguration("foo"));
assertNotNull(registry.getJobConfiguration("foo"));
registry.unregister(new JobConfiguration("foo"));
try {
assertNull(registry.getJobConfiguration("foo"));
fail("Expected NoSuchJobConfigurationException");
}
catch (NoSuchJobConfigurationException e) {
// expected
assertTrue(e.getMessage().indexOf("foo")>=0);
}
}
/**
* Test method for {@link org.springframework.batch.execution.configuration.MapJobConfigurationRegistry#getJobConfiguration(java.lang.String)}.
*/
public void testReplaceDuplicateConfiguration() throws Exception {
registry.register(new JobConfiguration("foo"));
try {
registry.register(new JobConfiguration("foo"));
} catch (DuplicateJobConfigurationException e) {
fail("Unexpected DuplicateJobConfigurationException");
// expected
assertTrue(e.getMessage().indexOf("foo")>=0);
}
}
/**
* Test method for {@link org.springframework.batch.execution.configuration.MapJobConfigurationRegistry#getJobConfiguration(java.lang.String)}.
*/
public void testRealDuplicateConfiguration() throws Exception {
JobConfiguration jobConfiguration = new JobConfiguration("foo");
registry.register(jobConfiguration);
try {
registry.register(jobConfiguration);
fail("Unexpected DuplicateJobConfigurationException");
} catch (DuplicateJobConfigurationException e) {
// expected
assertTrue(e.getMessage().indexOf("foo")>=0);
}
}
/**
* Test method for {@link org.springframework.batch.execution.configuration.MapJobConfigurationRegistry#getJobConfigurations()}.
* @throws Exception
*/
public void testGetJobConfigurations() throws Exception {
registry.register(new JobConfiguration("foo"));
registry.register(new JobConfiguration("bar"));
assertEquals(2, registry.getJobConfigurations().size());
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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.facade;
import java.util.Calendar;
import junit.framework.TestCase;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
/**
* Unit tests for {@link BatchResourceFactoryBean}
*
* @author robert.kasanicky
* @author Lucas Ward
* @author Dave Syer
*/
public class BatchResourceFactoryBeanTests extends TestCase {
/**
* object under test
*/
private BatchResourceFactoryBean resourceFactory = new BatchResourceFactoryBean();
private String PATTERN_STRING = "%BATCH_ROOT%\\%JOB_NAME%-%SCHEDULE_DATE%-%JOB_RUN%-%STREAM_NAME%";
private String EXPECTED_ABSOLUTE_PATH = "C:\\temp\\testJob-20070730-0-testStream";
private String NULL_JOB_NAME_PATH = "C:\\temp\\%JOB_NAME%-20070730-0-testStream";
/**
* mock step context
*/
protected void setUp() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2007);
calendar.set(Calendar.MONTH, Calendar.JULY);
calendar.set(Calendar.DAY_OF_MONTH, 30);
// define mock behaviour
resourceFactory.setScheduleDate("20070730");
resourceFactory.setRootDirectory("C:\\temp");
resourceFactory.setJobName("testJob");
resourceFactory.setJobStream("testStream");
resourceFactory.setJobRun(0);
resourceFactory.setStepName("testStep");
resourceFactory.setFilePattern(PATTERN_STRING);
resourceFactory.afterPropertiesSet();
}
/**
* regular use with valid context and pattern provided
*/
public void testCreateFileName() throws Exception {
Resource resource = (Resource) resourceFactory.getObject();
String returnedPath = resource.getFile().getAbsolutePath();
assertEquals(returnedPath, EXPECTED_ABSOLUTE_PATH);
}
/**
* Set the job name to null and attempt to get the resource, %JOB_NAME%
* should not be replaced.
*/
public void testNullJobName() throws Exception {
resourceFactory.setJobName(null);
// set singleton to false so a new instance is returned.
resourceFactory.setSingleton(false);
Resource resource = (Resource) resourceFactory.getObject();
assertEquals(NULL_JOB_NAME_PATH, resource.getFile().getAbsolutePath());
}
public void testObjectType() throws Exception {
assertEquals(Resource.class, resourceFactory.getObjectType());
}
public void testNullFilePattern() throws Exception {
resourceFactory = new BatchResourceFactoryBean();
resourceFactory.setSingleton(false);
resourceFactory.setFilePattern(null);
try {
resourceFactory.getObject();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected
}
}
public void testResoureLoaderAware() throws Exception {
resourceFactory = new BatchResourceFactoryBean();
resourceFactory.setSingleton(false);
resourceFactory.setResourceLoader(new DefaultResourceLoader() {
public Resource getResource(String location) {
return new ByteArrayResource("foo".getBytes());
}
});
Resource resource = (Resource) resourceFactory.getObject();
assertNotNull(resource);
assertTrue(resource.exists());
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.facade;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.beans.factory.InitializingBean;
public class EmptyItemProcessor implements ItemProcessor, InitializingBean {
private boolean failed = false;
// point at which to fail...
private int failurePoint = Integer.MAX_VALUE;
protected Log logger = LogFactory.getLog(EmptyItemProcessor.class);
List list;
public void afterPropertiesSet() throws Exception {
TransactionAwareProxyFactory factory = new TransactionAwareProxyFactory(new ArrayList());
list = (List) factory.createInstance();
}
public void setFailurePoint(int failurePoint) {
this.failurePoint = failurePoint;
}
public void process(Object data) {
if (!failed && list.size() == failurePoint) {
failed = true;
throw new RuntimeException("Failed processing: [" + data + "]");
}
logger.info("Processing: [" + data + "]");
list.add(data);
}
public List getList() {
return list;
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.facade;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.context.support.StaticApplicationContext;
public class JobConfigurationTests extends TestCase {
public void testBeanName() throws Exception {
StaticApplicationContext context = new StaticApplicationContext();
JobConfiguration configuration = new JobConfiguration();
context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean");
assertNotNull(configuration.getName());
configuration.setName("foo");
context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean");
assertEquals("foo", configuration.getName());
}
}

View File

@@ -0,0 +1,222 @@
/*
* 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.facade;
import java.util.Collections;
import java.util.Properties;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.JobConfigurationLocator;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.configuration.StepConfiguration;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.executor.JobExecutor;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.JobExecutionRegistry;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.StepExecutionContext;
import org.springframework.batch.execution.NoSuchJobExecutionException;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.context.RepeatContextSupport;
/**
* SimpleBatchContainer unit tests.
*
* @author Lucas Ward
* @author Dave Syer
*/
public class SimpleJobExecutorFacaderTests extends TestCase {
SimpleJobExecutorFacade simpleContainer = new SimpleJobExecutorFacade();
JobExecutor jobExecutor;
MockControl jobLifecycleControl = MockControl.createControl(JobExecutor.class);
JobRepository jobRepository;
MockControl jobRepositoryControl = MockControl.createControl(JobRepository.class);
JobConfiguration jobConfiguration = new JobConfiguration();
StepExecutor stepExecutor = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext) throws BatchCriticalException {
return ExitStatus.FINISHED;
}
};
protected void setUp() throws Exception {
super.setUp();
jobConfiguration.setName("TestJob");
jobExecutor = (JobExecutor) jobLifecycleControl.getMock();
simpleContainer.setJobExecutor(jobExecutor);
jobRepository = (JobRepository) jobRepositoryControl.getMock();
simpleContainer.setJobRepository(jobRepository);
}
public void testNormalStart() throws Exception {
final SimpleJobIdentifier jobRuntimeInformation = new SimpleJobIdentifier("bar");
jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
jobExecutor = new JobExecutor() {
public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext) throws BatchCriticalException {
jobExecutionContext.getJob().setIdentifier(jobRuntimeInformation);
}
};
JobInstance job = new JobInstance();
JobExecutionContext jobExecutionContext = new JobExecutionContext(jobRuntimeInformation, job);
jobRepositoryControl.setReturnValue(job);
jobExecutor.run(jobConfiguration, jobExecutionContext);
jobRepositoryControl.replay();
simpleContainer.setJobConfigurationLocator(new JobConfigurationLocator() {
public JobConfiguration getJobConfiguration(String name) throws NoSuchJobConfigurationException {
return jobConfiguration;
}
});
simpleContainer.start(jobRuntimeInformation);
assertEquals(job, jobExecutionContext.getJob());
assertEquals("bar", job.getName());
jobRepositoryControl.verify();
}
private volatile boolean running = false;
public void testIsRunning() throws Exception {
simpleContainer.setJobExecutor(new JobExecutor() {
public void run(JobConfiguration configuration, JobExecutionContext jobExecutionContext)
throws BatchCriticalException {
while (running) {
try {
Thread.sleep(100L);
}
catch (InterruptedException e) {
throw new BatchCriticalException("Interrupted unexpectedly!");
}
}
}
});
simpleContainer.setJobConfigurationLocator(new JobConfigurationLocator() {
public JobConfiguration getJobConfiguration(String name) throws NoSuchJobConfigurationException {
return jobConfiguration;
}
});
final SimpleJobIdentifier jobRuntimeInformation = new SimpleJobIdentifier("foo");
jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
JobInstance job = new JobInstance();
jobRepositoryControl.setReturnValue(job);
jobRepositoryControl.replay();
running = true;
new Thread(new Runnable() {
public void run() {
try {
simpleContainer.start(jobRuntimeInformation);
}
catch (NoSuchJobConfigurationException e) {
System.err.println("Shouldn't happen");
}
}
}).start();
// Give Thread time to start
Thread.sleep(100L);
assertTrue(simpleContainer.isRunning());
running = false;
int count = 0;
while(simpleContainer.isRunning() && count ++<5) {
Thread.sleep(100L);
}
assertFalse(simpleContainer.isRunning());
jobRepositoryControl.verify();
}
public void testInvalidState() throws Exception {
simpleContainer.setJobExecutor(null);
try {
simpleContainer.start(new SimpleJobIdentifier("TestJob"));
fail("Expected IllegalStateException");
}
catch (IllegalStateException ex) {
// expected
}
}
public void testStopWithNoJob() throws Exception {
MockControl control = MockControl.createControl(JobExecutionRegistry.class);
JobExecutionRegistry jobExecutionRegistry = (JobExecutionRegistry) control.getMock();
simpleContainer.setJobExecutionRegistry(jobExecutionRegistry);
SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("TestJob");
control.expectAndReturn(jobExecutionRegistry.get(runtimeInformation), null);
control.replay();
try {
simpleContainer.stop(runtimeInformation);
fail("Expected NoSuchJobExecutionException");
} catch (NoSuchJobExecutionException e) {
// expected
assertTrue(e.getMessage().indexOf("TestJob")>=0);
}
control.verify();
}
public void testStop() throws Exception {
JobExecutionRegistry jobExecutionRegistry = new VolatileJobExecutionRegistry();
simpleContainer.setJobExecutionRegistry(jobExecutionRegistry);
SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("TestJob");
JobExecutionContext context = jobExecutionRegistry.register(runtimeInformation, new JobInstance(new Long(0)));
RepeatContextSupport stepContext = new RepeatContextSupport(null);
RepeatContextSupport chunkContext = new RepeatContextSupport(stepContext);
context.registerStepContext(stepContext);
context.registerChunkContext(chunkContext);
simpleContainer.stop(runtimeInformation);
// It is only unregistered when the start method finishes, and it hasn't
// been called.
assertTrue(jobExecutionRegistry.isRegistered(runtimeInformation));
assertTrue(stepContext.isCompleteOnly());
assertTrue(chunkContext.isCompleteOnly());
}
public void testStatisticsWithNoContext() throws Exception {
assertNotNull(simpleContainer.getStatistics());
}
public void testStatisticsWithContext() throws Exception {
MockControl control = MockControl.createControl(JobExecutionRegistry.class);
JobExecutionRegistry jobExecutionRegistry = (JobExecutionRegistry) control.getMock();
simpleContainer.setJobExecutionRegistry(jobExecutionRegistry);
SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("TestJob");
JobExecutionContext jobExecutionContext = new JobExecutionContext(runtimeInformation, new JobInstance(new Long(0)));
jobExecutionContext.registerStepContext(new RepeatContextSupport(null));
jobExecutionContext.registerChunkContext(new RepeatContextSupport(null));
control.expectAndReturn(jobExecutionRegistry.findAll(), Collections.singleton(jobExecutionContext));
control.replay();
Properties statistics = simpleContainer.getStatistics();
assertNotNull(statistics);
assertTrue(statistics.containsKey("job1.step1"));
control.verify();
}
}

View File

@@ -0,0 +1,208 @@
/*
* 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.facade;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.StepConfiguration;
import org.springframework.batch.core.domain.BatchStatus;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.JobIdentifier;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.job.DefaultJobExecutor;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory;
import org.springframework.batch.execution.step.simple.DefaultStepExecutor;
import org.springframework.batch.execution.step.simple.SimpleStepConfiguration;
import org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.item.provider.ListItemProvider;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.exception.handler.ExceptionHandler;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.transaction.interceptor.TransactionProxyFactoryBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
public class SimpleJobTests extends TestCase {
private List list = new ArrayList();
// private int count;
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapStepDao());
private List processed = new ArrayList();
private ItemProcessor processor = new ItemProcessor() {
public void process(Object data) throws Exception {
processed.add((String) data);
}
};
private ItemProvider provider;
private DefaultJobExecutor jobLifecycle = new DefaultJobExecutor();;
private DefaultStepExecutor stepLifecycle = new DefaultStepExecutor();
protected void setUp() throws Exception {
super.setUp();
jobLifecycle.setJobRepository(repository);
stepLifecycle.setRepository(repository);
jobLifecycle.setStepExecutorResolver(new StepExecutorFactory() {
public StepExecutor getExecutor(StepConfiguration configuration) {
return stepLifecycle;
}
});
}
private Tasklet getTasklet(String arg) {
return getTasklet(new String[] { arg });
}
private Tasklet getTasklet(String arg0, String arg1) {
return getTasklet(new String[] { arg0, arg1 });
}
private Tasklet getTasklet(String[] args) {
ItemProviderProcessTasklet module = new ItemProviderProcessTasklet();
List items = TransactionAwareProxyFactory.createTransactionalList();
items.addAll(Arrays.asList(args));
provider = new ListItemProvider(items) {
public boolean recover(Object item, Throwable cause) {
list.add(item);
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
return true;
}
};
module.setItemProvider(provider);
module.setItemProcessor(processor);
return module;
}
public void testSimpleJob() throws Exception {
JobConfiguration jobConfiguration = new JobConfiguration();
JobIdentifier runtimeInformation = new ScheduledJobIdentifierFactory()
.getJobIdentifier("real.job");
jobConfiguration.addStep(new SimpleStepConfiguration(getTasklet("foo", "bar")));
jobConfiguration.addStep(new SimpleStepConfiguration(getTasklet("spam")));
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
assertEquals(job.getName(), "real.job");
JobExecutionContext jobExecutionContext = new JobExecutionContext(runtimeInformation, job);
jobLifecycle.run(jobConfiguration, jobExecutionContext);
assertEquals(BatchStatus.COMPLETED, job.getStatus());
assertEquals(3, processed.size());
assertTrue(processed.contains("foo"));
}
public void testSimpleJobWithRecovery() throws Exception {
JobConfiguration jobConfiguration = new JobConfiguration();
JobIdentifier runtimeInformation = new SimpleJobIdentifier("real.job");
RepeatTemplate chunkOperations = new RepeatTemplate();
// Always handle the exception a check it is the right one...
chunkOperations.setExceptionHandler(new ExceptionHandler() {
public void handleExceptions(RepeatContext context, Collection throwables) {
assertEquals(1, throwables.size());
assertEquals("Try again Dummy!", ((Throwable) throwables.iterator().next()).getMessage());
}
});
stepLifecycle.setChunkOperations(chunkOperations);
TransactionProxyFactoryBean proxyFactoryBean = new TransactionProxyFactoryBean();
proxyFactoryBean.setTransactionManager(new ResourcelessTransactionManager());
proxyFactoryBean.setTarget(stepLifecycle);
proxyFactoryBean.setTransactionAttributes(StringUtils.splitArrayElementsIntoProperties(
new String[] { "processChunk=PROPAGATION_REQUIRED" }, "="));
proxyFactoryBean.setExposeProxy(true);
proxyFactoryBean.afterPropertiesSet();
/*
* Each message fails once and the chunk (size=1) "rolls back"; then it
* is recovered ("skipped") on the second attempt (see retry policy
* definition above)...
*/
final Tasklet module = getTasklet(new String[] { "foo", "bar", "spam" });
StepConfiguration step = new SimpleStepConfiguration(module);
((ItemProviderProcessTasklet) module).setItemProcessor(new ItemProcessor() {
public void process(Object data) throws Exception {
throw new RuntimeException("Try again Dummy!");
}
});
jobConfiguration.addStep(step);
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
JobExecutionContext jobExecutionContext = new JobExecutionContext(runtimeInformation, job);
jobLifecycle.run(jobConfiguration, jobExecutionContext);
assertEquals(BatchStatus.COMPLETED, job.getStatus());
assertEquals(0, processed.size());
// provider should be exhausted
assertEquals(null, provider.next());
assertEquals(3, list.size());
}
public void testExceptionTerminates() throws Exception {
JobConfiguration jobConfiguration = new JobConfiguration();
JobIdentifier runtimeInformation = new SimpleJobIdentifier("real.job");
final Tasklet module = getTasklet(new String[] { "foo", "bar", "spam" });
StepConfiguration step = new SimpleStepConfiguration(module);
((ItemProviderProcessTasklet) module).setItemProcessor(new ItemProcessor() {
public void process(Object data) throws Exception {
throw new RuntimeException("Foo");
}
});
jobConfiguration.addStep(step);
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
JobExecutionContext jobExecutionContext = new JobExecutionContext(runtimeInformation, job);
try {
jobLifecycle.run(jobConfiguration, jobExecutionContext);
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("Foo", e.getMessage());
// expected
}
assertEquals(BatchStatus.FAILED, job.getStatus());
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.facade;
import java.util.Collection;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
/**
* @author Dave Syer
*
*/
public class VolatileJobExecutionRegistryTests extends TestCase {
private SimpleJobIdentifier runtimeInformation = new SimpleJobIdentifier("foo");
private JobInstance job = new JobInstance(new Long(0));
private VolatileJobExecutionRegistry registry = new VolatileJobExecutionRegistry();
public void testAddAndRetrieveSingle() throws Exception {
JobExecutionContext context = registry.register(runtimeInformation, job);
assertEquals(context, registry.get(runtimeInformation));
}
public void testAddAndFindAll() throws Exception {
JobExecutionContext context = registry.register(runtimeInformation, job);
Collection list = registry.findAll();
assertEquals(1, list.size());
assertTrue(list.contains(context));
}
public void testAddAndFindAllMultiple() throws Exception {
JobExecutionContext context1 = registry.register(runtimeInformation, job);
JobExecutionContext context2 = registry.register(new SimpleJobIdentifier("spam"), job);
Collection list = registry.findAll();
assertEquals(2, list.size());
assertTrue(list.contains(context1));
assertTrue(list.contains(context2));
}
public void testAddAndFindByName() throws Exception {
JobExecutionContext context = registry.register(runtimeInformation, job);
registry.register(new SimpleJobIdentifier("bar"), job);
Collection list = registry.findByName(runtimeInformation.getName());
assertEquals(1, list.size());
assertTrue(list.contains(context));
}
public void testAddAndUnregister() throws Exception {
registry.register(runtimeInformation, job);
assertTrue(registry.isRegistered(runtimeInformation));
registry.unregister(runtimeInformation);
assertFalse(registry.isRegistered(runtimeInformation));
}
public void testAddAndIsRegistered() throws Exception {
assertFalse(registry.isRegistered(runtimeInformation));
registry.register(runtimeInformation, job);
assertTrue(registry.isRegistered(runtimeInformation));
}
}

View File

@@ -0,0 +1,247 @@
/*
* 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.job;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.StepConfiguration;
import org.springframework.batch.core.domain.BatchStatus;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.executor.StepExecutorFactory;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.StepExecutionContext;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.JobDao;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.repository.dao.StepDao;
import org.springframework.batch.execution.step.simple.AbstractStepConfiguration;
import org.springframework.batch.execution.step.simple.SimpleStepConfiguration;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
/**
* Tests for DefaultJobLifecycle. MapJobDao and MapStepDao are used instead of a
* mock repository to test that status is being stored correctly.
*
* @author Lucas Ward
*/
public class DefaultJobExecutorTests extends TestCase {
private JobRepository jobRepository;
private JobDao jobDao;
private StepDao stepDao;
private List list = new ArrayList();
StepExecutor defaultStepLifecycle = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext)
throws StepInterruptedException, BatchCriticalException {
list.add("default");
return ExitStatus.FINISHED;
}
};
StepExecutor configurationStepLifecycle = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext)
throws StepInterruptedException, BatchCriticalException {
list.add("special");
return ExitStatus.FINISHED;
}
};
private JobInstance job;
private JobExecutionContext jobExecutionContext;
private StepInstance step1;
private StepInstance step2;
private StepExecutionContext stepExecutionContext1;
private StepExecutionContext stepExecutionContext2;
private AbstractStepConfiguration stepConfiguration1;
private AbstractStepConfiguration stepConfiguration2;
private JobConfiguration jobConfiguration;
private SimpleJobIdentifier jobRuntimeInformation;
private DefaultJobExecutor jobLifecycle;
protected void setUp() throws Exception {
super.setUp();
MapJobDao.clear();
MapStepDao.clear();
jobDao = new MapJobDao();
stepDao = new MapStepDao();
jobRepository = new SimpleJobRepository(jobDao, stepDao);
jobLifecycle = new DefaultJobExecutor();
jobLifecycle.setJobRepository(jobRepository);
jobLifecycle.setStepExecutorResolver(new StepExecutorFactory() {
public StepExecutor getExecutor(StepConfiguration configuration) {
return defaultStepLifecycle;
}
});
stepConfiguration1 = new SimpleStepConfiguration();
stepConfiguration1.setName("TestStep1");
stepConfiguration2 = new SimpleStepConfiguration();
stepConfiguration2.setName("TestStep2");
List stepConfigurations = new ArrayList();
stepConfigurations.add(stepConfiguration1);
stepConfigurations.add(stepConfiguration2);
jobConfiguration = new JobConfiguration();
jobConfiguration.setSteps(stepConfigurations);
jobRuntimeInformation = new SimpleJobIdentifier("TestJob");
job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
jobExecutionContext = new JobExecutionContext(jobRuntimeInformation, job);
List steps = job.getSteps();
step1 = (StepInstance) steps.get(0);
step2 = (StepInstance) steps.get(1);
stepExecutionContext1 = new StepExecutionContext(jobExecutionContext, step1);
stepExecutionContext2 = new StepExecutionContext(jobExecutionContext, step2);
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testRunWithDefaultLifecycle() throws Exception {
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
jobLifecycle.run(jobConfiguration, jobExecutionContext);
assertEquals(2, list.size());
checkRepository(BatchStatus.COMPLETED);
}
public void testExecutionContextIsSet() throws Exception {
testRunWithDefaultLifecycle();
assertEquals(job, jobExecutionContext.getJob());
assertEquals(step1, stepExecutionContext1.getStep());
assertEquals(step2, stepExecutionContext2.getStep());
}
public void testRunWithNonDefaultExecutor() throws Exception {
jobLifecycle.setStepExecutorResolver(new StepExecutorFactory() {
public StepExecutor getExecutor(StepConfiguration configuration) {
return configuration == stepConfiguration2 ? defaultStepLifecycle : configurationStepLifecycle;
}
});
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
jobLifecycle.run(jobConfiguration, jobExecutionContext);
assertEquals(2, list.size());
assertEquals("special", list.get(0));
assertEquals("default", list.get(1));
checkRepository(BatchStatus.COMPLETED);
}
public void testInterrupted() throws Exception {
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
final StepInterruptedException exception = new StepInterruptedException("Interrupt!");
defaultStepLifecycle = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext)
throws StepInterruptedException, BatchCriticalException {
throw exception;
}
};
try {
jobLifecycle.run(jobConfiguration, jobExecutionContext);
}
catch (BatchCriticalException e) {
assertEquals(exception, e.getCause());
}
assertEquals(0, list.size());
checkRepository(BatchStatus.STOPPED);
}
public void testFailed() throws Exception {
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
final RuntimeException exception = new RuntimeException("Foo!");
defaultStepLifecycle = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext)
throws StepInterruptedException, BatchCriticalException {
throw exception;
}
};
try {
jobLifecycle.run(jobConfiguration, jobExecutionContext);
}
catch (RuntimeException e) {
assertEquals(exception, e);
}
assertEquals(0, list.size());
checkRepository(BatchStatus.FAILED);
}
public void testStepShouldNotStart() throws Exception {
// Start policy will return false, keeping the step from being started.
stepConfiguration1.setStartLimit(0);
try{
jobLifecycle.run(jobConfiguration, jobExecutionContext);
fail();
}
catch( Exception ex ){
//expected
}
}
/*
* Check JobRepository to ensure status is being saved.
*/
private void checkRepository(BatchStatus status) {
assertEquals(job, jobDao.findJobs(jobRuntimeInformation).get(0));
// because map dao stores in memory, it can be checked directly
assertEquals(status, job.getStatus());
JobExecution jobExecution = (JobExecution) jobDao.findJobExecutions(job).get(0);
assertEquals(job.getId(), jobExecution.getJobId());
assertEquals(status, jobExecution.getStatus());
int exitCode = status==BatchStatus.STOPPED || status==BatchStatus.FAILED ? -1 : 0;
assertEquals(exitCode, jobExecution.getExitCode());
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.repository;
import java.util.List;
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.execution.repository.dao.StepDao;
import org.springframework.batch.restart.RestartData;
public class MockStepDao implements StepDao {
private List newSteps;
private int currentNewStep = 0;
public StepInstance createStep(JobInstance job, String stepName) {
StepInstance newStep = (StepInstance) newSteps.get(currentNewStep);
currentNewStep++;
newStep.setName(stepName);
return newStep;
}
public StepInstance findStep(JobInstance job, String stepName) {
StepInstance newStep = (StepInstance) newSteps.get(currentNewStep);
currentNewStep++;
newStep.setName(stepName);
return newStep;
}
public List findSteps(Long jobId) {
return newSteps;
}
public RestartData getRestartData(Long stepId) {
return null;
}
public int getStepExecutionCount(Long stepId) {
return 1;
}
public void save(StepExecution stepExecution) {
}
public void saveRestartData(Long stepId, RestartData restartData) {
}
public void update(StepInstance step) {
}
public void update(StepExecution stepExecution) {
}
public void setStepsToReturnOnCreate(List steps) {
this.newSteps = steps;
}
public void resetCurrentNewStep() {
currentNewStep = 0;
}
public List findStepExecutions(StepInstance step) {
return null;
}
}

View File

@@ -0,0 +1,316 @@
/*
* 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.repository;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.StepConfiguration;
import org.springframework.batch.core.domain.JobExecution;
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.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.repository.dao.JobDao;
import org.springframework.batch.execution.repository.dao.StepDao;
/*
* Test SimpleJobRepository. The majority of test cases are tested using EasyMock,
* however, there were some issues with using it for the stepDao when testing finding
* or creating steps, so an actual mock class had to be written.
*
* @author Lucas Ward
*
*/
public class SimpleJobRepositoryTests extends TestCase {
SimpleJobRepository jobRepository;
JobConfiguration jobConfiguration;
SimpleJobIdentifier jobRuntimeInformation;
StepConfiguration stepConfiguration1;
StepConfiguration stepConfiguration2;
MockControl jobDaoControl = MockControl.createControl(JobDao.class);
MockControl stepDaoControl = MockControl.createControl(StepDao.class);
JobDao jobDao;
StepDao stepDao;
MockStepDao mockStepDao = new MockStepDao();
JobInstance databaseJob;
StepInstance databaseStep1;
StepInstance databaseStep2;
List steps;
public void setUp() throws Exception {
jobDao = (JobDao) jobDaoControl.getMock();
stepDao = (StepDao) stepDaoControl.getMock();
jobRepository = new SimpleJobRepository(jobDao, stepDao);
jobRuntimeInformation = new SimpleJobIdentifier("RepositoryTest");
jobConfiguration = new JobConfiguration();
jobConfiguration.setName("RepositoryTest");
jobConfiguration.setRestartable(true);
stepConfiguration1 = new StubStepConfiguration("TestStep1");
stepConfiguration2 = new StubStepConfiguration("TestStep2");
List stepConfigurations = new ArrayList();
stepConfigurations.add(stepConfiguration1);
stepConfigurations.add(stepConfiguration2);
jobConfiguration.setSteps(stepConfigurations);
databaseJob = new JobInstance(new Long(1));
databaseStep1 = new StepInstance(new Long(1));
databaseStep2 = new StepInstance(new Long(2));
steps = new ArrayList();
steps.add(databaseStep1);
steps.add(databaseStep2);
}
public void testCreateRestartableJob(){
List jobs = new ArrayList();
jobDao.findJobs(jobRuntimeInformation);
jobDaoControl.setReturnValue(jobs);
jobDao.createJob(jobRuntimeInformation);
jobDaoControl.setReturnValue(databaseJob);
stepDao.createStep(databaseJob, "TestStep1");
stepDaoControl.setReturnValue(databaseStep1);
stepDao.createStep(databaseJob, "TestStep2");
stepDaoControl.setReturnValue(databaseStep2);
stepDaoControl.replay();
jobDaoControl.replay();
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
assertTrue(job.equals(databaseJob));
List jobSteps = job.getSteps();
Iterator it = jobSteps.iterator();
StepInstance step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep1));
step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep2));
}
public void testRestartedJob(){
List jobs = new ArrayList();
jobDao.findJobs(jobRuntimeInformation);
jobs.add(databaseJob);
jobDaoControl.setReturnValue(jobs);
stepDao.findStep(databaseJob, "TestStep1");
stepDaoControl.setReturnValue(databaseStep1);
stepDao.getStepExecutionCount(databaseStep1.getId());
stepDaoControl.setReturnValue(1);
stepDao.findStep(databaseJob, "TestStep2");
stepDaoControl.setReturnValue(databaseStep2);
stepDao.getStepExecutionCount(databaseStep2.getId());
stepDaoControl.setReturnValue(1);
stepDaoControl.replay();
jobDao.getJobExecutionCount(databaseJob.getId());
jobDaoControl.setReturnValue(1);
jobDaoControl.replay();
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
assertTrue(job.equals(databaseJob));
List jobSteps = job.getSteps();
Iterator it = jobSteps.iterator();
StepInstance step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep1));
assertTrue(step.getStepExecutionCount() == 1);
step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep2));
assertTrue(step.getStepExecutionCount() == 1);
}
public void testCreateNonRestartableJob(){
List jobs = new ArrayList();
jobDao.findJobs(jobRuntimeInformation);
jobDaoControl.setReturnValue(jobs);
jobDao.createJob(jobRuntimeInformation);
jobDaoControl.setReturnValue(databaseJob);
stepDao.createStep(databaseJob, "TestStep1");
stepDaoControl.setReturnValue(databaseStep1);
stepDao.createStep(databaseJob, "TestStep2");
stepDaoControl.setReturnValue(databaseStep2);
stepDaoControl.replay();
jobDaoControl.replay();
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
assertTrue(job.equals(databaseJob));
List jobSteps = job.getSteps();
Iterator it = jobSteps.iterator();
StepInstance step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep1));
step = (StepInstance) it.next();
assertTrue(step.equals(databaseStep2));
}
public void testUpdateJob() {
// failure scenario - no ID
JobInstance updateJob = new JobInstance(null);
try {
jobRepository.update(updateJob);
fail();
}
catch (Exception ex) {
// expected
}
// successful update
updateJob = new JobInstance(new Long(0L));
jobDao.update(updateJob);
jobDaoControl.replay();
jobRepository.update(updateJob);
}
public void testSaveOrUpdateJobExecution() {
// failure scenario - must have job ID
JobExecution jobExecution = new JobExecution(null);
try {
jobRepository.saveOrUpdate(jobExecution);
fail();
}
catch (Exception ex) {
// expected
}
// new execution - call save on job dao
jobExecution.setJobId(new Long(1));
jobDao.save(jobExecution);
jobDaoControl.replay();
jobRepository.saveOrUpdate(jobExecution);
jobDaoControl.reset();
// update existing execution
jobExecution.setId(new Long(5));
jobDao.update(jobExecution);
jobDaoControl.replay();
jobRepository.saveOrUpdate(jobExecution);
}
public void testUpdateStep() {
StepInstance step = new StepInstance(null);
// failure scenario - id not set
try {
jobRepository.update(step);
fail();
}
catch (Exception ex) {
// expected
}
// successful update
step = new StepInstance(new Long(0L));
stepDao.update(step);
stepDaoControl.replay();
jobRepository.update(step);
}
public void testUpdateStepExecution(){
StepExecution stepExecution = new StepExecution(new Long(10), null);
stepExecution.setId(new Long(11));
stepDao.update(stepExecution);
stepDaoControl.replay();
jobRepository.saveOrUpdate(stepExecution);
stepDaoControl.verify();
}
public void testSaveStepExecution(){
StepExecution stepExecution = new StepExecution(new Long(10), null);
//TODO: Not sure why, but calling save on the EasyMock stepDao causes a NullPointerException
// stepDao.save(stepExecution);
// stepDaoControl.replay();
jobRepository.saveOrUpdate(stepExecution);
// stepDaoControl.verify();
}
public void testSaveOrUpdateStepExecutionException() {
StepExecution stepExecution = new StepExecution(null, null);
// failure scenario -- no step id set.
try {
jobRepository.saveOrUpdate(stepExecution);
fail();
}
catch (Exception ex) {
// expected
}
}
/**
* @author Dave Syer
*
*/
private class StubStepConfiguration implements StepConfiguration {
private String name;
/**
* @param name
*/
public StubStepConfiguration(String name) {
this.name = name;
}
public Tasklet getTasklet() {
return null;
}
public String getName() {
return name;
}
public int getStartLimit() {
return 1;
}
public boolean isAllowStartIfComplete() {
return true;
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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.repository.dao;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.springframework.batch.core.domain.BatchStatus;
import org.springframework.util.ClassUtils;
public class HibernateJobDaoTests extends SqlJobDaoTests {
private SessionFactory sessionFactory;
protected String[] getConfigLocations(){
return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "hibernate-dao-test.xml") };
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public void testUpdateJobExecution() {
jobExecution.setStatus(BatchStatus.COMPLETED);
jobExecution.setEndTime(new Timestamp(System.currentTimeMillis()));
jobDao.update(jobExecution);
sessionFactory.getCurrentSession().flush();
List executions = jdbcTemplate.queryForList("SELECT * FROM BATCH_JOB_EXECUTION where JOB_ID=?", new Object[] {job.getId()});
assertEquals(1, executions.size());
assertEquals(jobExecution.getEndTime(), ((Map)executions.get(0)).get("END_TIME"));
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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.repository.dao;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.support.PropertiesConverter;
import org.springframework.util.ClassUtils;
public class HibernateStepDaoTests extends SqlStepDaoTests {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected String[] getConfigLocations() {
return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "hibernate-dao-test.xml") };
}
public void testSaveStatistics() throws Exception {
StepInstance step = stepDao.createStep(job, "foo");
StepExecution stepExecution = new StepExecution(step.getId(), new Long(10));
Properties statistics = new Properties();
statistics.setProperty("x", "y");
statistics.setProperty("a", "b");
stepExecution.setStatistics(statistics);
stepDao.save(stepExecution);
sessionFactory.getCurrentSession().flush();
String returnedStatistics = (String) jdbcTemplate.queryForObject(
"SELECT TASK_STATISTICS from BATCH_STEP_EXECUTION where ID=?", new Object[] { stepExecution.getId() },
String.class);
Properties fromDb = PropertiesConverter.stringToProperties(returnedStatistics);
//assertEquals("x=y, a=b", returnedStatistics);
assertEquals(fromDb, statistics);
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.repository.dao;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
public class MapJobDaoTests extends TestCase {
MapJobDao dao = new MapJobDao();
protected void setUp() throws Exception {
MapJobDao.clear();
}
public void testCreateAndRetrieveSingle() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
List result = dao.findJobs(new SimpleJobIdentifier("foo"));
assertTrue(result.contains(job));
}
public void testCreateAndRetrieveMultiple() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
job = dao.createJob(new SimpleJobIdentifier("bar"));
List result = dao.findJobs(new SimpleJobIdentifier("bar"));
assertEquals(1, result.size());
assertTrue(result.contains(job));
}
public void testNoExecutionsForNewJob() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
assertEquals(0, dao.getJobExecutionCount(job.getId()));
}
public void testSaveExecutionUpdatesId() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
JobExecution execution = new JobExecution(job.getId());
assertNull(execution.getId());
dao.save(execution);
assertNotNull(execution.getId());
}
public void testCorrectExecutionCountForExistingJob() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
dao.save(new JobExecution(job.getId()));
assertEquals(1, dao.getJobExecutionCount(job.getId()));
}
public void testMultipleExecutionsPerExisting() throws Exception {
JobInstance job = dao.createJob(new SimpleJobIdentifier("foo"));
dao.save(new JobExecution(job.getId()));
Thread.sleep(50L); // Hack, hack, hackety, hack - job executions are not unique if created too close together!
dao.save(new JobExecution(job.getId()));
assertEquals(2, dao.getJobExecutionCount(job.getId()));
}
}

View File

@@ -0,0 +1,122 @@
/*
* 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.repository.dao;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
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.execution.repository.dao.MapStepDao;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
public class MapStepDaoTests extends TestCase {
MapStepDao dao = new MapStepDao();
private JobInstance job;
private StepInstance step;
// Make sure we get a new job for each test...
static long jobId=100;
protected void setUp() throws Exception {
MapStepDao.clear();
job = new JobInstance(new Long(jobId++));
step = dao.createStep(job, "foo");
}
public void testCreateUnequal() throws Exception {
StepInstance step2 = dao.createStep(job, "foo");;
assertFalse(step.equals(step2));
assertFalse(step.hashCode()==step2.hashCode());
}
public void testCreateAndRetrieveSingle() throws Exception {
StepInstance result = dao.findStep(job, "foo");
assertEquals(step, result);
}
public void testCreateAndRetrieveSingleWhenMultipleStored() throws Exception {
dao.createStep(job, "bar");;
StepInstance result = dao.findStep(job, "foo");
assertEquals(step, result);
}
public void testCreateAndRetrieveSingleFromList() throws Exception {
List result = dao.findSteps(job.getId());
assertTrue(result.contains(step));
}
public void testCreateAndRetrieveMultiple() throws Exception {
step = dao.createStep(job, "bar");
List result = dao.findSteps(job.getId());
assertEquals(2, result.size());
assertTrue(result.contains(step));
}
public void testFindWithEmptyResults() throws Exception {
List result = dao.findSteps(new Long(22));
assertEquals(0, result.size());
}
public void testFindSingleWithEmptyResults() throws Exception {
StepInstance result = dao.findStep(new JobInstance(new Long(22)), "bar");
assertEquals(null, result);
}
public void testNoExecutionsForNew() throws Exception {
assertEquals(0, dao.getStepExecutionCount(step.getId()));
}
public void testSaveExecutionUpdatesId() throws Exception {
StepExecution execution = new StepExecution(step.getId(), null);
assertNull(execution.getId());
dao.save(execution);
assertNotNull(execution.getId());
}
public void testCorrectExecutionCountForExisting() throws Exception {
dao.save(new StepExecution(step.getId(), null));
assertEquals(1, dao.getStepExecutionCount(step.getId()));
}
public void testOnlyOneExecutionPerStep() throws Exception {
dao.save(new StepExecution(step.getId(), null));
dao.save(new StepExecution(step.getId(), null));
assertEquals(2, dao.getStepExecutionCount(step.getId()));
}
public void testSaveRestartData() throws Exception {
assertEquals(null, dao.getRestartData(step.getId()));
step.setStatus(BatchStatus.COMPLETED);
Properties data = new Properties();
data.setProperty("restart.key1", "restartData");
RestartData restartData = new GenericRestartData(data);
step.setRestartData(restartData);
dao.update(step);
StepInstance tempStep = dao.findStep(job, step.getName());
assertEquals(tempStep, step);
assertEquals(tempStep.getRestartData().getProperties().toString(),
restartData.getProperties().toString());
}
}

View File

@@ -0,0 +1,221 @@
/*
* 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.repository.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.List;
import org.springframework.batch.core.domain.BatchStatus;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException;
import org.springframework.batch.execution.runtime.ScheduledJobIdentifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import org.springframework.util.ClassUtils;
public class SqlJobDaoTests extends AbstractTransactionalDataSourceSpringContextTests {
private static final String GET_JOB_EXECUTION = "SELECT JOB_ID, START_TIME, END_TIME, STATUS from " +
"BATCH_JOB_EXECUTION where ID = ?";
protected JobDao jobDao;
protected ScheduledJobIdentifier jobRuntimeInformation;
protected JobInstance job;
protected JobExecution jobExecution;
protected Timestamp jobExecutionStartTime = new Timestamp(System.currentTimeMillis());
protected String[] getConfigLocations() {
return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "sql-dao-test.xml") };
}
/*
* Because AbstractTransactionalSpringContextTests is used, this method will
* be called by Spring to set the JobRepository.
*/
public void setJobRepositoryDao(JobDao jobRepositoryDao) {
this.jobDao = jobRepositoryDao;
}
protected void onSetUpInTransaction() throws Exception {
jobRuntimeInformation = new ScheduledJobIdentifier("Job1");
jobRuntimeInformation.setName("Job1");
jobRuntimeInformation.setJobStream("TestStream");
jobRuntimeInformation.setJobRun(1);
jobRuntimeInformation.setScheduleDate(new SimpleDateFormat("yyyyMMdd").parse("20070505"));
// Create job.
job = jobDao.createJob(jobRuntimeInformation);
// Create an execution
jobExecutionStartTime = new Timestamp(System.currentTimeMillis());
jobExecution = new JobExecution(job.getId());
jobExecution.setStartTime(jobExecutionStartTime);
jobExecution.setStatus(BatchStatus.STARTED);
jobDao.save(jobExecution);
}
public void testVersionIsNotNullForJob() throws Exception {
int version = jdbcTemplate.queryForInt("select version from BATCH_JOB where ID="+job.getId());
assertEquals(0, version);
}
public void testVersionIsNotNullForJobExecution() throws Exception {
int version = jdbcTemplate.queryForInt("select version from BATCH_JOB_EXECUTION where ID="+jobExecution.getId());
assertEquals(0, version);
}
public void testFindNonExistentJob(){
// No job should be found since it hasn't been created.
List jobs = jobDao.findJobs(new ScheduledJobIdentifier("Job2"));
assertTrue(jobs.size() == 0);
}
public void testFindJob(){
List jobs = jobDao.findJobs(jobRuntimeInformation);
assertTrue(jobs.size() == 1);
JobInstance tempJob = (JobInstance) jobs.get(0);
assertTrue(job.equals(tempJob));
}
public void testFindJobWithNullRuntime(){
ScheduledJobIdentifier runtimeInformation = null;
try{
jobDao.findJobs(runtimeInformation);
fail();
}catch(IllegalArgumentException ex){
//expected
}
}
public void testUpdateJob(){
// Update the returned job with a new status
job.setStatus(BatchStatus.COMPLETED);
jobDao.update(job);
// The job just updated should be found, with the saved status.
List jobs = jobDao.findJobs(jobRuntimeInformation);
assertTrue(jobs.size() == 1);
JobInstance tempJob = (JobInstance) jobs.get(0);
assertTrue(job.equals(tempJob));
assertEquals(tempJob.getStatus(), BatchStatus.COMPLETED);
}
public void testUpdateJobWithNullId(){
JobInstance testJob = new JobInstance(null);
try{
jobDao.update(testJob);
fail();
}catch(IllegalArgumentException ex){
//expected
}
}
public void testUpdateNullJob(){
JobInstance testJob = null;
try{
jobDao.update(testJob);
}catch(IllegalArgumentException ex){
//expected
}
}
public void testUpdateJobExecution() {
jobExecution.setStatus(BatchStatus.COMPLETED);
jobExecution.setEndTime(new Timestamp(System.currentTimeMillis()));
jobDao.update(jobExecution);
List executions = retrieveJobExecution(jobExecution.getId());
assertEquals(executions.size(), 1);
assertEquals(jobExecution, ((JobExecution)executions.get(0)));
}
public void testUpdateInvalidJobExecution(){
JobExecution execution = new JobExecution(job.getId());
//id is invalid
execution.setId(new Long(29432));
try{
jobDao.update(execution);
fail();
}catch(NoSuchBatchDomainObjectException ex){
//expected
}
}
public void testUpdateNullIdJobExection(){
JobExecution execution = new JobExecution(job.getId());
try{
jobDao.update(execution);
fail();
}catch(IllegalArgumentException ex){
//expected
}
}
public void testIncrementExecutionCount(){
// 1 JobExection already added in setup
assertEquals(jobDao.getJobExecutionCount(job.getId()), 1);
// Save new JobExecution for same job
JobExecution testJobExecution = new JobExecution(job.getId());
jobDao.save(testJobExecution);
//JobExecutionCount should be incremented by 1
assertEquals(jobDao.getJobExecutionCount(job.getId()), 2);
}
public void testZeroExecutionCount(){
JobInstance testJob = jobDao.createJob(new ScheduledJobIdentifier("TestJob"));
//no jobExecutions saved for new job, count should be 0
assertEquals(jobDao.getJobExecutionCount(testJob.getId()), 0);
}
private List retrieveJobExecution(final Long id){
RowMapper rowMapper = new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
JobExecution execution = new JobExecution(new Long(rs.getLong(1)));
execution.setStartTime(rs.getTimestamp(2));
execution.setEndTime(rs.getTimestamp(3));
execution.setStatus(BatchStatus.getStatus(rs.getString(4)));
execution.setId(id);
return execution;
}
};
return jdbcTemplate.query(GET_JOB_EXECUTION, new Object[]{id}, rowMapper);
}
}

View File

@@ -0,0 +1,206 @@
/*
* 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.repository.dao;
import java.sql.Timestamp;
import java.util.List;
import java.util.Properties;
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.runtime.JobIdentifier;
import org.springframework.batch.execution.runtime.ScheduledJobIdentifier;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import org.springframework.util.ClassUtils;
/**
* Test for StepDao. Because it is very reasonable to assume that there is a
* foreign key constraint on the JobId of a step, the JobDao is used to create
* jobs, to have an id for creating steps.
*
* @author Lucas Ward
*/
public class SqlStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests {
protected JobDao jobDao;
protected StepDao stepDao;
protected JobInstance job;
protected StepInstance step1;
protected StepInstance step2;
protected StepExecution stepExecution;
public void setJobDao(JobDao jobDao) {
this.jobDao = jobDao;
}
public void setStepDao(StepDao stepDao) {
this.stepDao = stepDao;
}
/*
* (non-Javadoc)
* @see org.springframework.test.AbstractSingleSpringContextTests#getConfigLocations()
*/
protected String[] getConfigLocations() {
return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "sql-dao-test.xml") };
}
/*
* (non-Javadoc)
* @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction()
*/
protected void onSetUpInTransaction() throws Exception {
JobIdentifier jobIdentifier = new ScheduledJobIdentifier("TestJob");
job = jobDao.createJob(jobIdentifier);
step1 = stepDao.createStep(job, "TestStep1");
step2 = stepDao.createStep(job, "TestStep2");
stepExecution = new StepExecution(step1.getId(), new Long(23));
stepExecution.setStatus(BatchStatus.STARTED);
stepExecution.setStartTime(new Timestamp(System.currentTimeMillis()));
stepDao.save(stepExecution);
}
public void testVersionIsNotNullForStep() throws Exception {
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP where ID="+step1.getId());
assertEquals(0, version);
}
public void testVersionIsNotNullForStepExecution() throws Exception {
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where ID="+stepExecution.getId());
assertEquals(0, version);
}
public void testFindStepNull(){
StepInstance step = stepDao.findStep(job, "UnSavedStep");
assertNull(step);
}
public void testFindStep(){
StepInstance tempStep = stepDao.findStep(job, "TestStep1");
assertEquals(tempStep, step1);
}
public void testFindSteps(){
List steps = stepDao.findSteps(job.getId());
assertEquals(steps.size(), 2);
assertTrue(steps.contains(step1));
assertTrue(steps.contains(step2));
}
public void testFindStepsNotSaved(){
//no steps are saved for given id, empty list should be returned
List steps = stepDao.findSteps(new Long(38922));
assertEquals(steps.size(), 0);
}
public void testCreateStep(){
StepInstance step3 = stepDao.createStep(job, "TestStep3");
StepInstance tempStep = stepDao.findStep(job, "TestStep3");
assertEquals(step3, tempStep);
}
public void testUpdateStepWithoutRestartData(){
step1.setStatus(BatchStatus.COMPLETED);
stepDao.update(step1);
StepInstance tempStep = stepDao.findStep(job, step1.getName());
assertEquals(tempStep, step1);
}
public void testUpdateStepWithRestartData(){
step1.setStatus(BatchStatus.COMPLETED);
Properties data = new Properties();
data.setProperty("restart.key1", "restartData");
RestartData restartData = new GenericRestartData(data);
step1.setRestartData(restartData);
stepDao.update(step1);
StepInstance tempStep = stepDao.findStep(job, step1.getName());
assertEquals(tempStep, step1);
assertEquals(tempStep.getRestartData().getProperties().toString(),
restartData.getProperties().toString());
}
public void testSaveStepExecution(){
StepExecution execution = new StepExecution(step2.getId(), new Long(10));
execution.setStatus(BatchStatus.STARTED);
execution.setStartTime(new Timestamp(System.currentTimeMillis()));
Properties statistics = new Properties();
statistics.setProperty("statistic.key1", "0");
statistics.setProperty("statistic.key2", "5");
execution.setStatistics(statistics);
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());
}
public void testUpdateStepExecution(){
stepExecution.setStatus(BatchStatus.COMPLETED);
stepExecution.setEndTime(new Timestamp(System.currentTimeMillis()));
stepExecution.setCommitCount(5);
stepExecution.setTaskCount(5);
stepExecution.setStatistics(new Properties());
stepDao.update(stepExecution);
List executions = stepDao.findStepExecutions(step1);
assertEquals(1, executions.size());
assertEquals(stepExecution, (StepExecution)executions.get(0));
}
public void testUpdateStepExecutionWithNullId(){
StepExecution stepExecution = new StepExecution(null, null);
try{
stepDao.update(stepExecution);
fail();
}catch(IllegalArgumentException ex){
//expected
}
}
public void testGetStepExecutionCountForNoExecutions(){
int executionCount = stepDao.getStepExecutionCount(step2.getId());
assertEquals(executionCount, 0);
}
public void testIncrementStepExecutionCount(){
assertEquals(1, stepDao.getStepExecutionCount(step1.getId()));
StepExecution execution = new StepExecution(step1.getId(), new Long(9));
stepDao.save(execution);
assertEquals(2, stepDao.getStepExecutionCount(step1.getId()));
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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.runtime;
import java.sql.Date;
import junit.framework.TestCase;
/**
* @author Dave Syer
*
*/
public class ScheduledJobIdentifierTests extends TestCase {
private ScheduledJobIdentifier instance = new ScheduledJobIdentifier(null);
/**
* Test method for {@link org.springframework.batch.core.domain.JobInstance#getName()}.
*/
public void testGetName() {
assertEquals(null, instance.getName());
instance.setName("foo");
assertEquals("foo", instance.getName());
}
/**
* Test method for {@link org.springframework.batch.core.domain.JobInstance#getJobStream()}.
*/
public void testGetJobStream() {
assertEquals("", instance.getJobStream());
instance.setJobStream("foo");
assertEquals("foo", instance.getJobStream());
}
/**
* Test method for {@link org.springframework.batch.core.domain.JobInstance#getScheduleDate()}.
*/
public void testGetScheduleDate() {
assertNotNull(instance.getScheduleDate());
instance.setScheduleDate(new Date(100L));
assertEquals(100L, instance.getScheduleDate().getTime());
}
/**
* Test method for {@link org.springframework.batch.core.domain.JobInstance#getJobRun()}.
*/
public void testGetJobRun() {
assertEquals(0, instance.getJobRun());
instance.setJobRun(1);
assertEquals(1, instance.getJobRun());
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.AttributeAccessor;
/**
* @author Dave Syer
*
*/
public class StepContextAwareStepScopeTests extends TestCase {
private static List list = new ArrayList();
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
StepSynchronizationManager.clear();
list.clear();
}
public void testScopedBean() throws Exception {
StepSynchronizationManager.open();
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBean bean = (TestBean) applicationContext.getBean("bean");
assertNotNull(bean);
assertEquals("foo", bean.name);
}
public void testScopedBeanWithDestroyCallback() throws Exception {
assertEquals(0, list.size());
StepSynchronizationManager.open();
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBean bean = (TestBean) applicationContext.getBean("bean");
assertNotNull(bean);
StepSynchronizationManager.close();
assertEquals(1, list.size());
}
public void testScopedBeanWithAware() throws Exception {
StepContext context = StepSynchronizationManager.open();
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("aware");
assertNotNull(bean);
assertEquals("bar", bean.name);
assertEquals(context, bean.context);
}
public static class TestBean {
String name;
TestBean child;
public void setName(String name) {
this.name = name;
}
public void setChild(TestBean child) {
this.child = child;
}
public void close() {
list.add("close");
}
}
public static class TestBeanAware extends TestBean implements StepContextAware {
AttributeAccessor context;
public void setStepScopeContext(AttributeAccessor context) {
this.context = context;
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
/**
* @author Dave Syer
*
*/
public class StepScopeContextTests extends TestCase {
private SimpleStepContext context = new SimpleStepContext(new SimpleStepContext());
/**
* Test method for {@link org.springframework.batch.execution.scope.SimpleStepContext#StepScopeContext()}.
*/
public void testStepScopeContext() {
assertNull(new SimpleStepContext().getParent());
}
/**
* Test method for {@link org.springframework.batch.execution.scope.SimpleStepContext#getParent()}.
*/
public void testGetParent() {
assertNotNull(context.getParent());
}
/**
* Test method for {@link org.springframework.batch.execution.scope.SimpleStepContext#getJobIdentifier()}.
*/
public void testGetJobIdentifier() {
assertNull(context.getJobIdentifier());
context.setJobIdentifier(new SimpleJobIdentifier("bar"));
assertEquals("bar", context.getJobIdentifier().getName());
}
private List list = new ArrayList();
/**
* Test method for {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackSunnyDay() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.setAttribute("foo", "FOO");
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
context.close();
assertEquals(1, list.size());
assertEquals("bar", list.get(0));
}
/**
* Test method for {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackMissingAttribute() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
context.close();
assertEquals(0, list.size());
}
/**
* Test method for {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackWithException() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.setAttribute("foo", "FOO");
context.setAttribute("bar", "BAR");
context.registerDestructionCallback("bar", new Runnable() {
public void run() {
list.add("spam");
throw new RuntimeException("fail!");
}
});
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
throw new RuntimeException("fail!");
}
});
try {
context.close();
fail("Expected RuntimeException");
} catch (RuntimeException e) {
// We don't care which one was thrown...
assertEquals("fail!", e.getMessage());
}
// ...but we do care that both were executed:
assertEquals(2, list.size());
assertTrue(list.contains("bar"));
assertTrue(list.contains("spam"));
}
}

View File

@@ -0,0 +1,192 @@
/*
* 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.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.execution.scope.StepScope;
import org.springframework.batch.execution.scope.SimpleStepContext;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.repeat.synch.RepeatSynchronizationManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
/**
* @author Dave Syer
*
*/
public class StepScopeTests extends TestCase {
private StepScope scope = new StepScope();
private SimpleStepContext context;
/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
context = StepSynchronizationManager.open();
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
RepeatSynchronizationManager.clear();
super.tearDown();
}
public void testGetWithNoContext() throws Exception {
final String foo = "bar";
StepSynchronizationManager.clear();
try {
scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithNothingAlreadyThere() {
final String foo = "bar";
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
assertEquals(foo, value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithSomethingAlreadyThere() {
context.setAttribute("foo", "bar");
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return null;
}
});
assertEquals("bar", value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithSomethingAlreadyInParentContext() {
SimpleStepContext context = StepSynchronizationManager.open();
context.setAttribute("foo", "bar");
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return null;
}
});
assertEquals("bar", value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#getConversationId()}.
*/
public void testGetConversationId() {
String id = scope.getConversationId();
assertNotNull(id);
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#getConversationId()}.
*/
public void testGetConversationIdFromAttribute() {
context.setAttribute(StepScope.ID_KEY, "foo");
String id = scope.getConversationId();
assertEquals("foo", id);
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testRegisterDestructionCallback() {
final List list = new ArrayList();
context.setAttribute("foo", "bar");
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("foo");
}
});
assertEquals(0, list.size());
// When the context is closed, provided the attribute exists the
// callback is called...
context.close();
assertEquals(1, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testRegisterAnotherDestructionCallback() {
final List list = new ArrayList();
context.setAttribute("foo", "bar");
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("foo");
}
});
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
assertEquals(0, list.size());
// When the context is closed, provided the attribute exists the
// callback is called...
context.close();
assertEquals(2, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#remove(java.lang.String)}.
*/
public void testRemove() {
context.setAttribute("foo", "bar");
scope.remove("foo");
assertFalse(context.hasAttribute("foo"));
}
}

View File

@@ -0,0 +1,136 @@
/*
* 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;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.StepConfiguration;
import org.springframework.batch.core.configuration.StepConfigurationSupport;
import org.springframework.batch.core.executor.StepExecutor;
import org.springframework.batch.core.runtime.StepExecutionContext;
import org.springframework.batch.execution.step.simple.SimpleStepConfiguration;
import org.springframework.batch.execution.step.simple.SimpleStepExecutor;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.StaticApplicationContext;
/**
* @author Dave Syer
*
*/
public class DefaultStepExecutorFactoryTests extends TestCase {
private DefaultStepExecutorFactory factory = new DefaultStepExecutorFactory();
private StaticApplicationContext applicationContext = new StaticApplicationContext();
protected void setUp() throws Exception {
factory.setBeanFactory(applicationContext);
}
public void testMissingStepExecutorName() throws Exception {
try {
factory.afterPropertiesSet();
fail("Expected IllegalArgumentException");
} catch(IllegalArgumentException e) {
// Missing name is illegal
}
}
public void testMissingStepExecutor() throws Exception {
factory.setStepExecutorName("foo");
try {
factory.afterPropertiesSet();
fail("Expected NoSuchBeanDefinitionException");
} catch(NoSuchBeanDefinitionException e) {
// expected
}
}
public void testSingletonStepExecutor() throws Exception {
applicationContext.getDefaultListableBeanFactory().registerBeanDefinition("foo", new RootBeanDefinition(SimpleStepExecutor.class));
factory.setStepExecutorName("foo");
try {
factory.afterPropertiesSet();
fail("Expected IllegalStateException");
} catch(IllegalStateException e) {
// expected
}
}
public void testSuccessfulStepExecutor() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new SimpleStepConfiguration()));
}
public void testSuccessfulStepExecutorWithNonSimpleConfigugration() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new StepConfigurationSupport()));
}
public void testSuccessfulStepExecutorWithSimpleConfigurationAndNotSimpleExecutor() throws Exception {
StepExecutor executor = new StepExecutor() {
public ExitStatus process(StepConfiguration configuration, StepExecutionContext stepExecutionContext) throws BatchCriticalException {
return ExitStatus.FINISHED;
}
};
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
assertEquals(executor, factory.getExecutor(new SimpleStepConfiguration()));
}
public void testSuccessfulStepExecutorHolderStrategy() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
RepeatTemplate repeatTemplate = new RepeatTemplate();
assertEquals(executor, factory.getExecutor(new SimpleHolderStepConfiguration(repeatTemplate)));
}
public void testUnsuccessfulStepExecutorHolderStrategy() throws Exception {
SimpleStepExecutor executor = new SimpleStepExecutor();
applicationContext.getBeanFactory().registerSingleton("foo", executor);
factory.setStepExecutorName("foo");
try {
factory.getExecutor(new SimpleHolderStepConfiguration(null));
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected
}
}
/**
* @author Dave Syer
*
*/
public class SimpleHolderStepConfiguration extends SimpleStepConfiguration implements RepeatOperationsHolder {
private RepeatOperations executor;
public SimpleHolderStepConfiguration(RepeatOperations executor) {
this.executor = executor;
}
public RepeatOperations getChunkOperations() {
return executor;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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 junit.framework.TestCase;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.repeat.support.RepeatTemplate;
/**
* @author Dave Syer
*
*/
public class ChunkOperationsStepConfigurationTests extends TestCase {
ChunkOperationsStepConfiguration configuration = new ChunkOperationsStepConfiguration();
/**
* Test method for {@link org.springframework.batch.execution.step.simple.ChunkOperationsStepConfiguration#StepExecutorStepConfiguration(org.springframework.batch.core.executor.StepExecutor)}.
*/
public void testStepExecutorStepConfigurationRepeatOperations() {
RepeatTemplate executor = new RepeatTemplate();
configuration = new ChunkOperationsStepConfiguration(executor);
assertEquals(executor, configuration.getChunkOperations());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.ChunkOperationsStepConfiguration#StepExecutorStepConfiguration(org.springframework.batch.core.tasklet.Tasklet)}.
*/
public void testStepExecutorStepConfigurationTasklet() {
Tasklet tasklet = new Tasklet() {
public boolean execute() throws Exception {
return false;
}
};
configuration = new ChunkOperationsStepConfiguration(tasklet);
assertEquals(tasklet, configuration.getTasklet());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.ChunkOperationsStepConfiguration#getChunkOperations()}.
*/
public void testGetExecutor() {
assertNull(configuration.getChunkOperations());
RepeatTemplate executor = new RepeatTemplate();
configuration.setChunkOperations(executor);
assertEquals(executor, configuration.getChunkOperations());
}
}

View File

@@ -0,0 +1,196 @@
/*
* 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 java.util.ArrayList;
import java.util.Arrays;
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.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.StepExecutionContext;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.item.provider.ListItemProvider;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
public class DefaultStepExecutorTests extends TestCase {
ArrayList processed = new ArrayList();
ItemProcessor processor = new ItemProcessor() {
public void process(Object data) throws Exception {
processed.add((String) data);
}
};
private DefaultStepExecutor stepExecutor;
private AbstractStepConfiguration stepConfiguration;
private ItemProvider getProvider(String[] args) {
return new ListItemProvider(Arrays.asList(args));
}
/**
* @param strings
* @return
*/
private Tasklet getTasklet(String[] strings) {
ItemProviderProcessTasklet module = new ItemProviderProcessTasklet();
module.setItemProcessor(processor);
module.setItemProvider(getProvider(strings));
return module;
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
stepExecutor = new DefaultStepExecutor();
stepExecutor.setRepository(new JobRepositorySupport());
stepConfiguration = new SimpleStepConfiguration();
stepConfiguration.setTasklet(getTasklet(new String[] {"foo", "bar", "spam"}));
// Only process one chunk:
RepeatTemplate template = new RepeatTemplate();
template.setCompletionPolicy(new SimpleCompletionPolicy(1));
stepExecutor.setStepOperations(template);
// Only process one item:
template = new RepeatTemplate();
template.setCompletionPolicy(new SimpleCompletionPolicy(1));
stepExecutor.setChunkOperations(template);
}
public void testStepExecutor() throws Exception {
StepInstance step = new StepInstance(new Long(9));
JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3)));
StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step);
stepExecutor.process(stepConfiguration, stepExecutionContext);
assertEquals(1, processed.size());
}
public void testChunkExecutor() throws Exception {
RepeatTemplate template = new RepeatTemplate();
// Only process one item:
template.setCompletionPolicy(new SimpleCompletionPolicy(1));
stepExecutor.setChunkOperations(template);
StepInstance step = new StepInstance(new Long(1));
step.setStepExecution(new StepExecution(new Long(1), new Long(2)));
JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(1)));
StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step);
stepExecutor.processChunk(stepConfiguration, stepExecutionContext);
assertEquals(1, processed.size());
}
public void testStepContextInitialized() throws Exception {
RepeatTemplate template = new RepeatTemplate();
// Only process one item:
template.setCompletionPolicy(new SimpleCompletionPolicy(1));
stepExecutor.setChunkOperations(template);
final StepInstance step = new StepInstance(new Long(1));
step.setStepExecution(new StepExecution(new Long(1),new Long(1)));
final JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3)));
final StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step);
stepConfiguration.setTasklet(new Tasklet() {
public boolean execute() throws Exception {
assertEquals(step, stepExecutionContext.getStep());
assertEquals(1, jobExecutionContext.getChunkContexts().size());
assertEquals(1, jobExecutionContext.getStepContexts().size());
assertNotNull(StepSynchronizationManager.getContext().getJobIdentifier());
processed.add("foo");
return true;
}
});
stepExecutor.process(stepConfiguration, stepExecutionContext);
assertEquals(1, processed.size());
}
public void testRepository() throws Exception {
SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapStepDao());
stepExecutor.setRepository(repository);
StepInstance step = new StepInstance(new Long(1));
JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3)));
StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step);
JobInstance job = new JobInstance(new Long(1));
job.setIdentifier(new SimpleJobIdentifier("foo_bar"));
stepExecutor.process(stepConfiguration, stepExecutionContext);
assertEquals(1, processed.size());
// assertEquals(1, repository.findJobs(job.?).size());
}
public void testIncrementRollbackCount(){
Tasklet module = new Tasklet(){
public boolean execute() throws Exception {
int counter = 0;
counter++;
if(counter == 1){
throw new Exception();
}
return true;
}
};
StepInstance step = new StepInstance(new Long(1));
stepConfiguration.setTasklet(module);
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().getRollbackCount(), new Integer(1));
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.configuration.JobConfiguration;
import org.springframework.batch.core.domain.JobExecution;
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.repository.JobRepository;
import org.springframework.batch.core.runtime.JobIdentifier;
/**
* @author Dave Syer
*
*/
public class JobRepositorySupport implements JobRepository {
/* (non-Javadoc)
* @see org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob(org.springframework.batch.container.common.domain.JobConfiguration)
*/
public JobInstance findOrCreateJob(JobConfiguration jobConfiguration, JobIdentifier runtimeInformation) {
return null;
}
/* (non-Javadoc)
* @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.JobExecution)
*/
public void saveOrUpdate(JobExecution jobExecution) {
}
/* (non-Javadoc)
* @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.StepExecution)
*/
public void saveOrUpdate(StepExecution stepExecution) {
}
/* (non-Javadoc)
* @see org.springframework.batch.container.common.repository.JobRepository#update(org.springframework.batch.container.common.domain.Job)
*/
public void update(JobInstance job) {
}
/* (non-Javadoc)
* @see org.springframework.batch.container.common.repository.JobRepository#update(org.springframework.batch.container.common.domain.Step)
*/
public void update(StepInstance step) {
}
}

View File

@@ -0,0 +1,106 @@
/*
* 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 junit.framework.TestCase;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.repeat.exception.handler.DefaultExceptionHandler;
/**
* @author Dave Syer
*
*/
public class SimpleStepConfigurationTests extends TestCase {
SimpleStepConfiguration configuration = new SimpleStepConfiguration("foo");
/**
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStepConfiguration#SimpleStepConfiguration()}.
*/
public void testSimpleStepConfiguration() {
assertNotNull(configuration.getName());
configuration = new SimpleStepConfiguration();
assertNull(configuration.getName());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStepConfiguration#SimpleStepConfiguration(org.springframework.batch.core.tasklet.Tasklet)}.
*/
public void testSimpleStepConfigurationTasklet() {
Tasklet tasklet = new Tasklet() {
public boolean execute() throws Exception {
return false;
}
};
configuration = new SimpleStepConfiguration(tasklet);
assertEquals(tasklet, configuration.getTasklet());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.SimpleStepConfiguration#getCommitInterval()}.
*/
public void testGetCommitInterval() {
assertEquals(1, configuration.getCommitInterval());
configuration.setCommitInterval(20);
assertEquals(20, configuration.getCommitInterval());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStepConfiguration#setBeanName(java.lang.String)}.
*/
public void testSetBeanName() {
configuration.setBeanName("bar");
assertEquals("foo", configuration.getName());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStepConfiguration#setBeanName(java.lang.String)}.
*/
public void testSetBeanNameOverrideNull() {
configuration = new SimpleStepConfiguration();
configuration.setBeanName("bar");
assertEquals("bar", configuration.getName());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStepConfiguration#getExceptionHandler()}.
*/
public void testGetExceptionHandler() {
assertNull(configuration.getExceptionHandler());
configuration.setExceptionHandler(new DefaultExceptionHandler());
assertNotNull(configuration.getExceptionHandler());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStepConfiguration#getSkipLimit()}.
*/
public void testGetSkipLimit() {
assertEquals(0, configuration.getSkipLimit());
configuration.setSkipLimit(20);
assertEquals(20, configuration.getSkipLimit());
}
/**
* Test method for {@link org.springframework.batch.execution.step.simple.AbstractStepConfiguration#isSaveRestartData()}.
*/
public void testIsSaveRestartData() {
assertEquals(false, configuration.isSaveRestartData());
configuration.setSaveRestartData(true);
assertEquals(true, configuration.isSaveRestartData());
}
}

View File

@@ -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.execution.step.simple;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.domain.BatchStatus;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.StepInstance;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.JobExecutionContext;
import org.springframework.batch.core.runtime.JobIdentifier;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.StepExecutionContext;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.JobDao;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;
import org.springframework.batch.execution.repository.dao.StepDao;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
public class StepExecutorInterruptionTests extends TestCase {
private JobRepository jobRepository;
private JobDao jobDao = new MapJobDao();
private StepDao stepDao = new MapStepDao();
private JobInstance job;
private AbstractStepConfiguration stepConfiguration;
private SimpleStepExecutor executor;
public void setUp() {
jobRepository = new SimpleJobRepository(jobDao, stepDao);
JobConfiguration jobConfiguration = new JobConfiguration();
stepConfiguration = new SimpleStepConfiguration();
jobConfiguration.addStep(stepConfiguration);
JobIdentifier runtimeInformation = new SimpleJobIdentifier("TestJob");
jobConfiguration.setName("testJob");
job = jobRepository.findOrCreateJob(jobConfiguration, runtimeInformation);
executor = new SimpleStepExecutor();
}
public void testInterruptChunk() throws Exception {
executor.setRepository(jobRepository);
List steps = job.getSteps();
final StepInstance step = (StepInstance) steps.get(0);
JobExecutionContext jobExecutionContext = new JobExecutionContext(null, new JobInstance(new Long(0)));
final StepExecutionContext stepExecutionContext = new StepExecutionContext(jobExecutionContext, step);
stepConfiguration.setTasklet(new Tasklet() {
public boolean execute() throws Exception {
// do something non-trivial (and not Thread.sleep())
double foo = 1;
for (int i = 2; i < 250; i++) {
foo = foo * i;
}
// always return true, so processing always continues
return foo != 1;
}
});
Thread processingThread = new Thread() {
public void run() {
try {
executor.process(stepConfiguration, stepExecutionContext);
}
catch (StepInterruptedException e) {
// do nothing...
}
}
};
processingThread.start();
Thread.sleep(500);
processingThread.interrupt();
int count = 0;
while (processingThread.isAlive() && count < 15) {
Thread.sleep(20);
count++;
}
assertFalse(processingThread.isAlive());
assertEquals(BatchStatus.STOPPED, step.getStatus());
}
public void testInterruptStep() throws Exception {
RepeatTemplate template = new RepeatTemplate();
// N.B, If we don't set the completion policy it might run forever
template.setCompletionPolicy(new SimpleCompletionPolicy(2));
executor.setChunkOperations(template);
testInterruptChunk();
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 junit.framework.TestCase;
import org.springframework.batch.core.executor.StepInterruptedException;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.context.RepeatContextSupport;
/**
* @author Dave Syer
*
*/
public class ThreadStepInterruptionPolicyTests extends TestCase {
ThreadStepInterruptionPolicy policy = new ThreadStepInterruptionPolicy();
private RepeatContext context = new RepeatContextSupport(null);;
/**
* Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}.
* @throws Exception
*/
public void testCheckInterruptedNotComplete() throws Exception {
policy.checkInterrupted(context);
// no exception
}
/**
* Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}.
* @throws Exception
*/
public void testCheckInterruptedComplete() throws Exception {
context.setTerminateOnly();
try {
policy.checkInterrupted(context);
fail("Expected StepInterruptedException");
} catch (StepInterruptedException e) {
// expected
assertTrue(e.getMessage().indexOf("interrupt")>=0);
}
}
}

View File

@@ -0,0 +1,342 @@
/*
* 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.tasklet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.item.provider.AbstractItemProvider;
import org.springframework.batch.repeat.context.RepeatContextSupport;
import org.springframework.batch.repeat.synch.RepeatSynchronizationManager;
import org.springframework.batch.retry.policy.NeverRetryPolicy;
import org.springframework.batch.retry.support.RetryTemplate;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
/**
* @author Dave Syer
* @author Peter Zozom
*/
public class ItemProviderProcessTaskletTests extends TestCase {
private List list = new ArrayList();
private List items = new ArrayList();
private ItemProvider itemProvider = new AbstractItemProvider() {
int count = 0;
public Object next() throws Exception {
if (count < items.size()) {
Object data = items.get(count++);
if (data instanceof Exception) {
throw (Exception) data;
}
return data;
}
return null;
}
};
private ItemProcessor itemProcessor = new ItemProcessor() {
public void process(Object data) throws Exception {
list.add(data);
}
};
private ItemProviderProcessTasklet module;
public void setUp() {
// create module
module = new ItemProviderProcessTasklet();
// set up module
module.setItemProvider(itemProvider);
module.setItemProcessor(itemProcessor);
RepeatSynchronizationManager.register(new RepeatContextSupport(null));
}
/*
* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
RepeatSynchronizationManager.clear();
}
// tests also read and process
public void testExecute() throws Exception {
// TEST1: data provider returns some object and data processor should
// process it
// set up mock objects
items = Collections.singletonList("foo");
// call execute
assertTrue(module.execute());
// verify method calls
assertEquals(1, list.size());
assertEquals("foo", list.get(0));
}
public void testExecuteWithNothingToRead() throws Exception {
// TEST2: data provider returns null (nothing to read)
// call read
assertFalse(module.execute());
}
public void testExecuteWithExceptionOnRead() throws Exception {
// TEST3: exception is thrown by data provider
// set up mock objects
items = Collections.singletonList(new RuntimeException("foo"));
// call read
try {
module.execute();
// TODO: should we expect Batch exception?
fail("RuntimeException was expected");
}
catch (RuntimeException bce) {
// expected
}
}
public void testNotSkippable() throws Exception {
try {
module.skip();
} catch (Exception e) {
// Unexpected
throw e;
}
}
public void testSkippableProvider() throws Exception {
module.setItemProvider(new SkippableItemProvider());
module.skip();
assertEquals(1, list.size());
}
public void testSkippablProviderProcessor() throws Exception {
module.setItemProvider(new SkippableItemProvider());
module.setItemProcessor(new SkippableItemProcessor());
module.skip();
assertEquals(2, list.size());
}
public void testStatisticsProvider() throws Exception {
module.setItemProvider(new SkippableItemProvider());
Properties stats = module.getStatistics();
assertEquals(1, stats.size());
assertEquals("bar", stats.getProperty("foo"));
}
public void testStatisticsProcessor() throws Exception {
module.setItemProcessor(new SkippableItemProcessor());
Properties stats = module.getStatistics();
assertEquals(1, stats.size());
assertEquals("bar", stats.getProperty("foo"));
}
public void testStatisticsProviderProcessor() throws Exception {
module.setItemProvider(new SkippableItemProvider());
module.setItemProcessor(new SkippableItemProcessor());
Properties stats = module.getStatistics();
assertEquals(2, stats.size());
assertEquals("bar", stats.getProperty("provider.foo"));
assertEquals("bar", stats.getProperty("processor.foo"));
}
public void testStatisticsProviderProcessorMergeDuplicates() throws Exception {
module.setItemProvider(new SkippableItemProvider());
module.setItemProcessor(new SkippableItemProcessor("foo=bar\nspam=bucket"));
Properties stats = module.getStatistics();
assertEquals(3, stats.size());
assertEquals("bar", stats.getProperty("provider.foo"));
assertEquals("bar", stats.getProperty("processor.foo"));
assertEquals("bucket", stats.getProperty("spam"));
}
public void testRecoverable() throws Exception {
// set up and call execute
items = Collections.singletonList("foo");
module.setItemProvider(new AbstractItemProvider() {
public boolean recover(Object item, Throwable cause) {
assertEquals("foo", cause.getMessage());
list.add(item);
return true;
}
public Object next() throws Exception {
return itemProvider.next();
}
});
module.setItemProcessor(new ItemProcessor() {
public void process(Object data) throws Exception {
throw new RuntimeException("FOO");
}
});
try {
module.execute();
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("FOO", e.getMessage());
}
list.clear();
// After a processing exception client has to call recover directly
module.recover(new RuntimeException("foo"));
// verify method calls
assertEquals(1, list.size());
assertEquals("The item was not passed in to recover method", "foo", list.get(0));
}
public void testRetryPolicy() throws Exception {
module.setRetryPolicy(new NeverRetryPolicy());
// set up mock objects
items = new ArrayList() {
{
add("foo");
add("foo"); // in production use this would be the second
// attempt after rollback
}
};
module.setItemProvider(new AbstractItemProvider() {
public boolean recover(Object item, Throwable cause) {
assertEquals("FOO", cause.getMessage());
list.add(item + "_recovered");
return true;
}
public Object next() throws Exception {
return itemProvider.next();
}
});
module.setItemProcessor(new ItemProcessor() {
public void process(Object data) throws Exception {
throw new RuntimeException("FOO");
}
});
// finish initialisation
module.afterPropertiesSet();
try {
module.execute();
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("FOO", e.getMessage());
}
// No exception thrown now because we are going to recover...
module.execute();
// No need for client has to call recover directly
// verify method calls
assertEquals(1, list.size());
assertEquals("The item was not passed in to recover method", "foo_recovered", list.get(0));
}
public void testInitialisationWithNullProvider() throws Exception {
module.setItemProvider(null);
try {
module.afterPropertiesSet();
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().toLowerCase().indexOf("provider") >= 0);
}
}
public void testInitialisationWithNullProcessor() throws Exception {
module.setItemProcessor(null);
try {
module.afterPropertiesSet();
}
catch (IllegalArgumentException e) {
assertTrue(e.getMessage().toLowerCase().indexOf("processor") >= 0);
}
}
public void testInitialisationWithNotNullPolicyAndOperations() throws Exception {
module.setRetryPolicy(new NeverRetryPolicy());
module.setRetryOperations(new RetryTemplate());
try {
module.afterPropertiesSet();
}
catch (IllegalStateException e) {
assertTrue(e.getMessage().toLowerCase().indexOf("not both") >= 0);
}
}
private class SkippableItemProvider extends AbstractItemProvider implements Skippable, StatisticsProvider {
public Object next() throws Exception {
return itemProvider.next();
}
public void skip() {
list.add("provider");
}
public Properties getStatistics() {
return PropertiesConverter.stringToProperties("foo=bar");
}
}
private class SkippableItemProcessor implements ItemProcessor, Skippable, StatisticsProvider {
String props = "foo=bar";
public SkippableItemProcessor() {
super();
}
public SkippableItemProcessor(String props) {
this();
this.props = props;
}
public void process(Object data) throws Exception {
// no-op
}
public void skip() {
list.add("processor");
}
public Properties getStatistics() {
return PropertiesConverter.stringToProperties(props);
}
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.tasklet;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.execution.tasklet.RestartableItemProviderTasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.support.PropertiesConverter;
/**
* @author Peter Zozom
*/
public class RestartableItemProviderTaskletTests extends TestCase {
private static class MockProvider implements ItemProvider, Restartable {
RestartData data = new RestartData() {
public Properties getProperties() {
return PropertiesConverter.stringToProperties("a=b");
}
};
public Object next() {
return null;
}
public RestartData getRestartData() {
return data;
}
public void restoreFrom(RestartData data) {
// restart data should be same as returned by getRestartData
assertEquals(this.data.getProperties(), data.getProperties());
}
public Object getKey(Object item) {
return null;
}
public boolean recover(Object data, Throwable cause) {
return false;
}
}
private static class MockProcessor implements ItemProcessor, Restartable {
RestartData data = new RestartData() {
public Properties getProperties() {
return PropertiesConverter.stringToProperties("x=y");
}
};
public void process(Object data) {
}
public RestartData getRestartData() {
return data;
}
public void restoreFrom(RestartData data) {
// restart data should be same as returned by getRestartData
assertEquals(this.data.getProperties(), data.getProperties());
}
}
private ItemProvider itemProvider;
private ItemProcessor itemProcessor;
private RestartableItemProviderTasklet module;
public void testRestart() {
// create data provider and data processor
itemProvider = new MockProvider();
itemProcessor = new MockProcessor();
// create and set up module
module = new RestartableItemProviderTasklet();
module.setItemProvider(itemProvider);
module.setItemProcessor(itemProcessor);
// get restart data
RestartData data = module.getRestartData();
assertNotNull(data);
// restore from restart data (see asserts in mock classes)
module.restoreFrom(data);
}
public void testRestartFromGenericData() {
// create data provider and data processor
itemProvider = new MockProvider();
itemProcessor = new MockProcessor();
// create and set up module
module = new RestartableItemProviderTasklet();
module.setItemProvider(itemProvider);
module.setItemProcessor(itemProcessor);
// get restart data
RestartData data = module.getRestartData();
assertNotNull(data);
data = new GenericRestartData(data.getProperties());
// restore from restart data (see asserts in mock classes)
module.restoreFrom(data);
}
public void testRestartFromNotRestartable() {
// create and set up module
module = new RestartableItemProviderTasklet();
module.setItemProvider(null);
module.setItemProcessor(null);
// get restart data
RestartData data = module.getRestartData();
assertNotNull(data);
// restore from restart data (see asserts in mock classes)
module.restoreFrom(data);
System.err.println(data.getProperties());
}
}

View File

@@ -0,0 +1,148 @@
package org.springframework.batch.execution.tasklet.support;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
/**
* Tests for {@link CompositeItemProcessor}
*
* @author Robert Kasanicky
*/
public class CompositeItemProcessorTests extends TestCase {
// object under test
private CompositeItemProcessor itemProcessor = new CompositeItemProcessor();
/**
* Regular usage scenario.
* All injected processors should be called.
*/
public void testProcess() throws Exception {
final int NUMBER_OF_PROCESSORS = 10;
Object data = new Object();
List controls = new ArrayList(NUMBER_OF_PROCESSORS);
List processors = new ArrayList(NUMBER_OF_PROCESSORS);
for (int i = 0; i < NUMBER_OF_PROCESSORS; i++) {
MockControl control = MockControl.createStrictControl(ItemProcessor.class);
ItemProcessor processor = (ItemProcessor) control.getMock();
processor.process(data);
control.setVoidCallable();
control.replay();
processors.add(processor);
controls.add(control);
}
itemProcessor.setItemProcessors(processors);
itemProcessor.process(data);
for (Iterator iterator = controls.iterator(); iterator.hasNext();) {
MockControl control = (MockControl) iterator.next();
control.verify();
}
}
/**
* Statistics of injected ItemProcessors should be returned under keys prefixed with their list index.
*/
public void testStatistics() {
final ItemProcessor p1 = new ItemProcessorStub();
final ItemProcessor p2 = new ItemProcessorStub();
List itemProcessors = new ArrayList(){{
add(p1);
add(p2);
}};
itemProcessor.setItemProcessors(itemProcessors);
Properties stats = itemProcessor.getStatistics();
assertEquals(String.valueOf(p1.hashCode()), stats.getProperty("0#" + ItemProcessorStub.STATS_KEY));
assertEquals(String.valueOf(p2.hashCode()), stats.getProperty("1#" + ItemProcessorStub.STATS_KEY));
}
/**
* All Restartable processors should be restarted, not-Restartable processors should be ignored.
*/
public void testRestart() {
//this mock with undefined behavior makes sure not-Restartable processor is ignored
MockControl p1c = MockControl.createStrictControl(ItemProcessor.class);
final ItemProcessor p1 = (ItemProcessor) p1c.getMock();
final ItemProcessor p2 = new ItemProcessorStub();
final ItemProcessor p3 = new ItemProcessorStub();
List itemProcessors = new ArrayList(){{
add(p1);
add(p2);
add(p3);
}};
itemProcessor.setItemProcessors(itemProcessors);
RestartData rd = itemProcessor.getRestartData();
itemProcessor.restoreFrom(rd);
for (Iterator iterator = itemProcessors.iterator(); iterator.hasNext();) {
ItemProcessor processor = (ItemProcessor) iterator.next();
if (processor instanceof ItemProcessorStub) {
assertTrue("Injected processors are restarted",
((ItemProcessorStub)processor).restarted);
}
}
}
/**
* Stub for testing restart. Checks the restart data received is the same that was returned by
* <code>getRestartData()</code>
*/
private static class ItemProcessorStub implements ItemProcessor, Restartable, StatisticsProvider {
private static final String RESTART_KEY = "restartData";
private static final String STATS_KEY = "stats";
private boolean restarted = false;
private final int hashCode = this.hashCode();
public RestartData getRestartData() {
Properties props = new Properties(){{
setProperty(RESTART_KEY, String.valueOf(hashCode));
}};
return new GenericRestartData(props);
}
public void restoreFrom(RestartData data) {
if (Integer.valueOf(data.getProperties().getProperty(RESTART_KEY)).intValue() != hashCode()) {
fail("received restart data is not the same which was saved");
}
restarted = true;
}
public void process(Object data) throws Exception {
// do nothing
}
public Properties getStatistics() {
return new Properties() {{
setProperty(STATS_KEY, String.valueOf(hashCode));
}};
}
}
}

View File

@@ -0,0 +1,189 @@
/*
* 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.tasklet.support;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.execution.tasklet.support.DefaultFlatFileItemProvider;
import org.springframework.batch.io.exception.ValidationException;
import org.springframework.batch.io.file.FieldSet;
import org.springframework.batch.io.file.FieldSetInputSource;
import org.springframework.batch.io.file.FieldSetMapper;
import org.springframework.batch.io.file.support.DefaultFlatFileInputSource;
import org.springframework.batch.item.validator.Validator;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
import org.springframework.core.io.ByteArrayResource;
/**
* Unit tests for {@link DefaultFlatFileItemProvider}
*
* @author Robert Kasanicky
*/
public class DefaultFlatFileItemProviderTests extends TestCase {
public static String FOO = "foo";
// object under test
private DefaultFlatFileItemProvider itemProvider = new DefaultFlatFileItemProvider();
// Input source
private DefaultFlatFileInputSource source;
//mock mapper
private FieldSetMapper mapper;
private List list = new ArrayList();
// create mock objects and inject them into data provider
protected void setUp() throws Exception {
source = new DefaultFlatFileInputSource();
source.setResource(new ByteArrayResource("a,b".getBytes()));
mapper = new FieldSetMapper() {
public Object mapLine(FieldSet fs) {
return FOO;
}
};
itemProvider.setSource(source);
itemProvider.setMapper(mapper);
assertTrue(Restartable.class.isAssignableFrom(DefaultFlatFileInputSource.class));
assertTrue(FieldSetInputSource.class.isAssignableFrom(DefaultFlatFileInputSource.class));
assertTrue(StatisticsProvider.class.isAssignableFrom(DefaultFlatFileInputSource.class));
}
/**
* Uses input template to provide the domain object.
*/
public void testNext() {
Object result = itemProvider.next();
assertSame("domain object is provided by the input template", FOO, result);
}
/**
* Uses input template to provide the domain object.
*/
public void testNextWithValidator() {
itemProvider.setValidator(new Validator() {
public void validate(Object value) throws ValidationException {
list.add(value);
}
});
itemProvider.next();
assertSame("domain object is provided by the input template", FOO, list.get(0));
}
/**
* Uses input template to provide the domain object.
*/
public void testNextWithValidatorAndInvalidData() {
itemProvider.setValidator(new Validator() {
public void validate(Object value) throws ValidationException {
throw new ValidationException("Invalid input");
}
});
try {
itemProvider.next();
fail("Expected ValidationException");
} catch (ValidationException e) {
// expected
assertEquals("Invalid input", e.getMessage());
}
}
/**
* Gets statistics from the input template
*/
public void testGetStatistics() {
Properties statistics = ((StatisticsProvider) source).getStatistics();
assertEquals(statistics, itemProvider.getStatistics());
}
/**
* Gets statistics from the input template
*/
public void testGetStatisticsWithoutStatisticsProvider() {
itemProvider.setSource(null);
Properties props = itemProvider.getStatistics();
assertEquals(null, props.getProperty("a"));
}
/**
* Gets restart data from the input template
*/
public void testGetRestartData() {
RestartData data = ((Restartable) source).getRestartData();
assertEquals(data.getProperties(), itemProvider.getRestartData().getProperties());
}
/**
* Forwarded restart data to input template
*/
public void testRestoreFrom() {
final List list = new ArrayList();
RestartData data = new RestartData() {
public Properties getProperties() {
list.add(FOO);
return ((Restartable) source).getRestartData().getProperties();
}};
itemProvider.restoreFrom(data);
//assertEquals(1, list.size()); getProperties are called multiple times due to null checks
assertTrue(list.size() > 0);
}
/**
* Forward restart data to input template
* @throws Exception
*/
public void testRestoreFromWithoutRestartable() throws Exception {
itemProvider.setSource(null);
try {
itemProvider.restoreFrom(new GenericRestartData(PropertiesConverter.stringToProperties("value=bar")));
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
/**
* Forward restart data to input template
* @throws Exception
*/
public void testGetRestartDataWithoutRestartable() throws Exception {
itemProvider.setSource(null);
try {
itemProvider.getRestartData();
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.tasklet.support;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.execution.tasklet.support.InputSourceItemProvider;
import org.springframework.batch.io.InputSource;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
/**
* Unit test for {@link InputSourceItemProvider}
*
* @author Robert Kasanicky
*/
public class InputSourceItemProviderTests extends TestCase {
// object under test
private InputSourceItemProvider itemProvider = new InputSourceItemProvider();
private InputSource source;
// create input template and inject it to data provider
protected void setUp() throws Exception {
source = new MockInputSource(this);
itemProvider.setInputSource(source);
}
/**
* Uses input template to provide the domain object.
*/
public void testNext() {
Object result = itemProvider.next();
assertSame("domain object is provided by the input template", this, result);
}
/**
* Gets statistics from the input template
*/
public void testGetStatistics() {
Properties props = itemProvider.getStatistics();
assertEquals("b", props.getProperty("a"));
}
/**
* Gets restart data from the input template
*/
public void testGetRestartData() {
Properties props = itemProvider.getRestartData().getProperties();
assertEquals("foo", props.getProperty("value"));
}
/**
* Forwared restart data to input template
*/
public void testRestoreFrom() {
itemProvider.restoreFrom(new GenericRestartData(PropertiesConverter.stringToProperties("value=bar")));
assertEquals("bar", itemProvider.next());
}
private class MockInputSource implements InputSource, StatisticsProvider, Restartable {
private Object value;
public Properties getStatistics() {
return PropertiesConverter.stringToProperties("a=b");
}
public RestartData getRestartData() {
return new GenericRestartData(PropertiesConverter.stringToProperties("value=foo"));
}
public void restoreFrom(RestartData data) {
value = data.getProperties().getProperty("value");
}
public MockInputSource(Object value) {
this.value = value;
}
public Object read() {
return value;
}
public void close() {
}
public void open() {
}
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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.tasklet.support;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.springframework.batch.execution.tasklet.support.OutputSourceItemProcessor;
import org.springframework.batch.io.OutputSource;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;
/**
* @author Dave Syer
*
*/
public class OutputSourceItemProcessorTests extends TestCase {
private OutputSourceItemProcessor processor = new OutputSourceItemProcessor();
private OutputSource source;
/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
source = new MockOutputSource("test");
processor.setOutputSource(source);
}
public void testProcess() throws Exception {
processor.process("foo");
assertEquals(1, list.size());
assertEquals("test:foo", list.get(0));
}
/**
* Gets statistics from the input template
*/
public void testGetStatistics() {
Properties props = processor.getStatistics();
assertEquals("b", props.getProperty("a"));
}
/**
* Gets restart data from the input template
*/
public void testGetRestartData() {
Properties props = processor.getRestartData().getProperties();
assertEquals("foo", props.getProperty("value"));
}
/**
* Forward restart data to input template
* @throws Exception
*/
public void testRestoreFrom() throws Exception {
processor.restoreFrom(new GenericRestartData(PropertiesConverter.stringToProperties("value=bar")));
processor.process("foo");
assertEquals("bar:foo", list.get(0));
}
/**
* Forward restart data to input template
* @throws Exception
*/
public void testGetRestartDataWithoutRestartable() throws Exception {
processor.setOutputSource(null);
try {
processor.getRestartData();
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
/**
* Forward restart data to input template
* @throws Exception
*/
public void testRestoreFromWithoutRestartable() throws Exception {
processor.setOutputSource(null);
try {
processor.restoreFrom(new GenericRestartData(PropertiesConverter.stringToProperties("value=bar")));
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
/**
* Gets statistics from the input template
*/
public void testGetStatisticsWithoutStatisticsProvider() {
processor.setOutputSource(null);
Properties props = processor.getStatistics();
assertEquals(null, props.getProperty("a"));
}
private List list = new ArrayList();
/**
* @author Dave Syer
*
*/
public class MockOutputSource implements OutputSource, StatisticsProvider, Restartable {
private String value;
public MockOutputSource(String string) {
this.value = string;
}
public void write(Object output) {
list.add(value+":"+output);
}
public void close() {
}
public void open() {
}
public Properties getStatistics() {
return PropertiesConverter.stringToProperties("a=b");
}
public RestartData getRestartData() {
return new GenericRestartData(PropertiesConverter.stringToProperties("value=foo"));
}
public void restoreFrom(RestartData data) {
value = data.getProperties().getProperty("value");
}
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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 test.jdbc.datasource;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
public class InitializingDataSourceFactoryBean extends AbstractFactoryBean {
private Resource[] initScripts;
private Resource destroyScript;
DataSource dataSource;
private static boolean initialized = false;
/**
* @throws Throwable
* @see java.lang.Object#finalize()
*/
protected void finalize() throws Throwable {
super.finalize();
initialized = false;
logger.debug("finalize called");
}
protected void destroyInstance(Object instance) throws Exception {
try {
doExecuteScript(destroyScript);
}
catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.warn("Could not execute destroy script [" + destroyScript + "]", e);
}
else {
logger.warn("Could not execute destroy script [" + destroyScript + "]");
}
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(dataSource);
super.afterPropertiesSet();
}
protected Object createInstance() throws Exception {
Assert.notNull(dataSource);
if (!initialized) {
try {
doExecuteScript(destroyScript);
}
catch (Exception e) {
logger.debug("Could not execute destroy script [" + destroyScript + "]", e);
}
if (initScripts != null) {
for (int i = 0; i < initScripts.length; i++) {
Resource initScript = initScripts[i];
doExecuteScript(initScript);
}
}
initialized = true;
}
return dataSource;
}
private void doExecuteScript(final Resource scriptResource) {
if (scriptResource == null || !scriptResource.exists())
return;
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String[] scripts;
try {
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
.getInputStream())), ";");
}
catch (IOException e) {
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
}
for (int i = 0; i < scripts.length; i++) {
String script = scripts[i].trim();
if (StringUtils.hasText(script)) {
jdbcTemplate.execute(scripts[i]);
}
}
return null;
}
});
}
private String stripComments(List list) {
StringBuffer buffer = new StringBuffer();
for (Iterator iter = list.iterator(); iter.hasNext();) {
String line = (String) iter.next();
if (!line.startsWith("//") && !line.startsWith("--")) {
buffer.append(line + "\n");
}
}
return buffer.toString();
}
public Class getObjectType() {
return DataSource.class;
}
public void setInitScript(Resource initScript) {
this.initScripts = new Resource[] { initScript };
}
public void setInitScripts(Resource[] initScripts) {
this.initScripts = initScripts;
}
public void setDestroyScript(Resource destroyScript) {
this.destroyScript = destroyScript;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}

View File

@@ -0,0 +1,11 @@
<?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-2.0.xsd">
<bean id="simple-container" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<value>simple-container-definition.xml</value>
</constructor-arg>
</bean>
</beans>

View File

@@ -0,0 +1,172 @@
Product: Clover
License: Open Source License, 0.x, 1.x
Issued: Thu Mar 15 2007 12:55:00 CDT
Expiry: Never
Maintenance Expiry: Never
Key: d24b469cbe33bb71017d39a9d
Name: Andy Colyer
Org: Spring Portfolio
Certificate: AAACUG+Ow8B7/zEbxOMqqKwwrdpP+a1COmJGHco7sCNLjHkHnajPF+dQW
Ct12PMy0uml0s9xuus5wKngJ9OFk5/FZgYzdyIG5/rxEgRevOoLO7uYipoJrkt4TPBwIm4
hxEw+b9xUNP0x1tTqSsgUP6fqSYilMajaHYGuRD9iV3LeP7hwWulpXY3hz3W5WjsKYp3Nf
fPyts/AffWHANGj5DHV+4yGm2IGIzIgHOGx9hISC7boFknmwM/GQ78RO1yzNnkSJ9dHPz2
VdGTrKob36k3OVy7vwwCPpSm+01KDpkY4ZQN4ynqPIFzvJ07F1IBUvU49CGzSvX3v6qmOp
mT11CTGtP49xPafrKNjDDV8PxCsoesEBRaY4FJzquzWz0j6CkIQqidzCj3WDCtog3ct+za
SuuZ51n027sVFhbM69dZZzv8bYCgSHdQ3sG1a9DxM7+6JRfRcIBFgt/V78vK41MF4p9Mi1
qmEPMLizpu7eBo1GDoQ8Lb3EhIWrfxDb4Db3NFc9hYpCKoreFlEw1A+eJlrLeomy43pVtk
SNPTDDoahNrXLeIu7SiRoHiemMrUjWvYtT9jwnVOsIjELa8n8cfW7gMzJdenCcNWl/T3Cr
8rSu3pVfz07AvX6+wQZWqzvGGnlwpnFXu1YJROxITYNINVNKXCAby33Mdbm51DPA3rEyk+
dpS31tU2XrR4iY1Zypja1M0voOkzL74pf9ExgUGeJqyvi5LWTn3b4kGGT/bkwhbbDn6sAA
zlxKRvxsbYOBUzk3UZ448Heg2HwCjwarCh/C0QIcX8vWnUjqssdvxT7Jlr1rZwqK1LKqbH
l7YvP9Ee7SoHfoHrW770yK23u2IdDK44Sf6G3NBE0Muq7W1bcZwrZ1/ZRk8vE2kt0F0fXI
wz7Thjs5lXvcZDJO4nEtXpmSdCaDjUXBpjvsZE2ZjPa2Q1tv3KFhHWqdfNRant7FyeWYg=
=
License Agreement: CLOVER VERSION 1 (ONE) SOFTWARE LICENSE AGREEMENT
1. Licenses and Software
Cenqua Pty Ltd, an Australian Proprietary Limited Company ("CENQUA")
hereby grants to the purchaser (the "LICENSEE") a limited, revocable,
worldwide, non-exclusive, nontransferable, non-sublicensable license
to use the Clover version 1 (one) software (the "Software"),
including any minor upgrades thereof during the Term (hereinafter
defined) up to, but not including the next major version of the
Software. The licensee shall not, or knowingly allow others to,
reverse engineer, decompile, disassemble, modify, adapt, create
derivative works from or otherwise attempt to derive source code from
the Software provided. And, in accordance with the terms and
conditions of this Software License Agreement (the "Agreement"), the
Software shall be used solely by the licensed users in accordance
with the following edition specific conditions:
a) Server Edition
A Server Edition license entitles the Licensee to execute one
instance of Clover Server Edition on one (1) machine for the purposes
of instrumententing source code and generating reports. There are no
limitations on the use of the instrumented source code or generated
reports produced by Server Edition.
b) Workstation Edition
A Workstation Edition license entitles the licensee to use Clover
Workstation Edition on one (1) machine by one (1) individual end
user. Workstation Edition does not permit the generation of reports
for distribution.
c) Team Edition
A Team Edition license entitles the licensee to use Clover Team
edition on any number of machines solely by the licensed number of
users. Reports generated by Clover Team Edition are strictly for use
only by the licensed number of individual end users.
2. License Fee
In exchange for the License(s), the Licensee shall pay to CENQUA a
one-time, up front, non-refundable license fee. At the sole
discretion of CENQUA this fee will be waived for non-commercial
projects. Notwithstanding the Licensee's payment of the License Fee,
CENQUA reserves the right to terminate the License if CENQUA
discovers that the Licensee and/or the Licensee's use of the Software
is in breach of this Agreement.
3. Proprietary Rights
CENQUA will retain all right, title and interest in and to the
Software, all copies thereof, and CENQUA website(s), software, and
other intellectual property, including, but not limited to, ownership
of all copyrights, look and feel, trademark rights, design rights,
trade secret rights and any and all other intellectual property and
other proprietary rights therein. The Licensee will not directly or
indirectly obtain or attempt to obtain at any time, any right, title
or interest by registration or otherwise in or to the trademarks,
service marks, copyrights, trade names, symbols, logos or
designations or other intellectual property rights owned or used by
CENQUA. All technical manuals or other information provided by CENQUA
to the Licensee shall be the sole property of CENQUA.
4. Term and Termination
Subject to the other provisions hereof, this Agreement shall commence
upon the Licensee's opting into this Agreement and continue until the
Licensee discontinues use of the Software or the Agreement terminates
automatically upon the Licensee's breach of any term or condition of
this Agreement (the "Term"). Upon any such termination, the Licensee
will delete the Software immediately.
5. Copying & Transfer
The Licensee may copy the Software for back-up purposes only. The
Licensee may not assign or otherwise transfer the Software to any
third party.
6. Specific Disclaimer of Warranty and Limitation of Liability
THE SOFTWARE IS PROVIDED WITHOUT WARRANTY OF ANY KIND. CENQUA
DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. CENQUA WILL NOT BE LIABLE FOR ANY DAMAGES
ASSOCIATED WITH THE SOFTWARE, INCLUDING, WITHOUT LIMITATION,
ORDINARY, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OF ANY KIND,
INCLUDING BUT NOT LIMITED TO DAMAGES RELATING TO LOST DATA OR LOST
PROFITS, EVEN IF CENQUA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
7. Warranties and Representations
Licensee Indemnification. CENQUA agrees to indemnify, defend and hold
the Licensee harmless from and against any and all liabilities,
damages, losses, claims, costs, and expenses (including reasonable
legal fees) arising out of or resulting from the Software or the use
thereof infringing upon, misappropriating or violating any patents,
copyrights, trademarks, or trade secret rights or other proprietary
rights of persons, firms or entities who are not parties to this
Agreement.
CENQUA Indemnification. The Licensee warrants and represents that the
Licensee's actions with regard to the Software will be in compliance
with all applicable laws; and the Licensee agrees to indemnify,
defend, and hold CENQUA harmless from and against any and all
liabilities, damages, losses, claims, costs, and expenses (including
reasonable legal fees) arising out of or resulting from the
Licensee's failure to observe the use restrictions set forth herein.
8. Publicity
The Licensee grants permission for CENQUA to use Licensee's name
solely in customer lists. CENQUA shall not, without prior consent in
writing, use the Licensee's name, or that of its affiliates, in any
form with the specific exception of customer lists. CENQUA agrees to
remove Licensee's name from any and all materials within 7 days if
notified by the Licensee in writing.
9. Governing Law
This Agreement shall be governed by the laws of New South Wales,
Australia.
10.Independent Contractors
The parties are independent contractors with respect to each other,
and nothing in this Agreement shall be construed as creating an
employer-employee relationship, a partnership, agency relationship or
a joint venture between the parties.
11. Assignment
This Agreement is not assignable or transferable by the Licensee.
CENQUA in its sole discretion may transfer a license to a third party
at the written request of the Licensee.
12. Entire Agreement
This Agreement constitutes the entire agreement between the parties
concerning the Licensee's use of the Software. This Agreement
supersedes any prior verbal understanding between the parties and any
Licensee purchase order or other ordering document, regardless of
whether such document is received by CENQUA before or after execution
of this Agreement. This Agreement may be amended only in writing by
CENQUA.

View File

@@ -0,0 +1,36 @@
<?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.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean class="org.springframework.batch.execution.configuration.JobConfigurationRegistryBeanPostProcessor">
<property name="jobConfigurationRegistry" ref="jobConfigurationRegistry"/>
</bean>
<bean id="test-job" parent="simpleJob">
<property name="name" value="test-job"/>
<property name="steps">
<bean id="step1" parent="simpleStep">
<constructor-arg>
<bean
class="org.springframework.batch.execution.tasklet.ItemProviderProcessTasklet">
<property name="itemProvider">
<bean
class="org.springframework.batch.item.provider.ListItemProvider">
<constructor-arg value="foo,bar,spam"/>
</bean>
</property>
<property name="itemProcessor">
<bean class="org.springframework.batch.execution.facade.EmptyItemProcessor"/>
</property>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,13 @@
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 %p [%c] - <%m>%n
log4j.category.org.apache.activemq=ERROR
log4j.category.org.springframework.batch=DEBUG
log4j.category.org.springframework.transaction=INFO
log4j.category.org.hibernate.SQL=DEBUG
# for debugging datasource initialization
# log4j.category.test.jdbc=DEBUG

View File

@@ -0,0 +1,48 @@
<?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-2.0.xsd">
<bean id="dataSource" class="test.jdbc.datasource.InitializingDataSourceFactoryBean">
<property name="dataSource">
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:testdb"/>
</bean>
</property>
<property name="initScript" value="org/springframework/batch/execution/repository/dao/init.sql" />
<property name="destroyScript" value="org/springframework/batch/execution/repository/dao/destroy.sql" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="incrementerParent" class="org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer" abstract="true">
<property name="dataSource" ref="dataSource" />
<property name="columnName" value="ID" />
</bean>
<bean id="jobIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_JOB_SEQ" />
</bean>
<bean id="jobExecutionIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_JOB_EXECUTION_SEQ" />
</bean>
<bean id="stepIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_STEP_SEQ" />
</bean>
<bean id="stepExecutionIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_STEP_EXECUTION_SEQ" />
</bean>
<bean id="partitionIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_PARTITION_SEQ" />
</bean>
<bean id="partitionExecutionIncrementer" parent="incrementerParent">
<property name="incrementerName" value="BATCH_PARTITION_EXECUTION_SEQ" />
</bean>
</beans>

View File

@@ -0,0 +1,10 @@
-- Autogenerated: do not edit this file
DROP TABLE BATCH_STEP_EXECUTION IF EXISTS;
DROP TABLE BATCH_JOB_EXECUTION IF EXISTS;
DROP TABLE BATCH_STEP IF EXISTS;
DROP TABLE BATCH_JOB IF EXISTS;
DROP TABLE BATCH_STEP_EXECUTION_SEQ IF EXISTS;
DROP TABLE BATCH_STEP_SEQ IF EXISTS;
DROP TABLE BATCH_JOB_EXECUTION_SEQ IF EXISTS;
DROP TABLE BATCH_JOB_SEQ IF EXISTS;

View File

@@ -0,0 +1,34 @@
<?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-2.0.xsd">
<import resource="data-source-context.xml"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingLocations">
<list>
<value>classpath:/org/springframework/batch/execution/repository/dao/JobInstance.hbm.xml</value>
<value>classpath:/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml</value>
<value>classpath:/org/springframework/batch/execution/repository/dao/StepInstance.hbm.xml</value>
<value>classpath:/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value><![CDATA[
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.dialect=org.hibernate.dialect.HSQLDialect
]]></value>
</property>
<property name="dataSource" ref="dataSource" />
<property name="lobHandler">
<bean class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>

View File

@@ -0,0 +1,14 @@
<?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-2.0.xsd">
<import resource="hibernate-context.xml" />
<bean id="jobDao" class="org.springframework.batch.execution.repository.dao.HibernateJobDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="stepDao" class="org.springframework.batch.execution.repository.dao.HibernateStepDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>

View File

@@ -0,0 +1,53 @@
-- Autogenerated: do not edit this file
CREATE TABLE BATCH_JOB (
ID BIGINT IDENTITY PRIMARY KEY ,
VERSION BIGINT,
JOB_NAME VARCHAR(100) NOT NULL ,
JOB_STREAM VARCHAR(20) ,
SCHEDULE_DATE DATE ,
JOB_RUN CHAR(2),
STATUS VARCHAR(10) );
CREATE TABLE BATCH_JOB_EXECUTION (
ID BIGINT IDENTITY PRIMARY KEY ,
VERSION BIGINT,
JOB_ID BIGINT NOT NULL,
START_TIME TIMESTAMP NOT NULL ,
END_TIME TIMESTAMP ,
STATUS VARCHAR(10),
EXIT_CODE BIGINT);
CREATE TABLE BATCH_STEP (
ID BIGINT IDENTITY PRIMARY KEY ,
VERSION BIGINT,
JOB_ID BIGINT NOT NULL,
STEP_NAME VARCHAR(100) NOT NULL,
STATUS VARCHAR(10),
RESTART_DATA VARCHAR(200));
CREATE TABLE BATCH_STEP_EXECUTION (
ID BIGINT IDENTITY PRIMARY KEY ,
VERSION BIGINT NOT NULL,
STEP_ID BIGINT NOT NULL,
JOB_EXECUTION_ID BIGINT NOT NULL,
START_TIME TIMESTAMP NOT NULL ,
END_TIME TIMESTAMP ,
STATUS VARCHAR(10),
COMMIT_COUNT BIGINT ,
TASK_COUNT BIGINT ,
TASK_STATISTICS VARCHAR(250),
EXIT_CODE BIGINT,
EXIT_MESSAGE VARCHAR(250));
CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
ID BIGINT IDENTITY
);
CREATE TABLE BATCH_STEP_SEQ (
ID BIGINT IDENTITY
);
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
ID BIGINT IDENTITY
);
CREATE TABLE BATCH_JOB_SEQ (
ID BIGINT IDENTITY
);

View File

@@ -0,0 +1,23 @@
<?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-2.0.xsd">
<import resource="data-source-context.xml" />
<bean id="jobDao" class="org.springframework.batch.execution.repository.dao.SqlJobDao" >
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="jobIncrementer" ref="jobIncrementer" />
<property name="jobExecutionIncrementer" ref="jobExecutionIncrementer" />
</bean>
<bean id="stepDao" class="org.springframework.batch.execution.repository.dao.SqlStepDao" >
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="stepIncrementer" ref="stepIncrementer" />
<property name="stepExecutionIncrementer" ref="stepExecutionIncrementer" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource" />
</bean>
</beans>

View File

@@ -0,0 +1,35 @@
<?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.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<!-- ideally we want the scope to be an inner bean - it's fine if it isn't a BeanFactoryPostProcessor -->
<entry key="step" value-ref="scope"/>
</map>
</property>
</bean>
<bean id="scope" class="org.springframework.batch.execution.scope.StepScope" />
<bean id="bean" class="org.springframework.batch.execution.scope.StepScopeContextAwareStepScopeTests$TestBean" scope="step" destroy-method="close">
<property name="name" value="foo"/>
</bean>
<bean id="inner" class="org.springframework.batch.execution.scope.StepScopeContextAwareStepScopeTests$TestBean" scope="step">
<property name="child">
<bean class="org.springframework.batch.execution.scope.StepScopeContextAwareStepScopeTests$TestBean" destroy-method="close"/>
</property>
</bean>
<bean id="aware" class="org.springframework.batch.execution.scope.StepScopeContextAwareStepScopeTests$TestBeanAware" scope="step">
<property name="name" value="bar"/>
</bean>
</beans>

View File

@@ -0,0 +1,94 @@
<?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.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="simpleContainer" class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator" ref="jobConfigurationRegistry"/>
<property name="jobExecutor" ref="jobLifecycle" />
</bean>
<bean id="simpleContainerLauncher" class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="batchContainer" ref="simpleContainer" />
<property name="jobRuntimeInformationFactory" ref="jobRuntimeInformationFactory"/>
</bean>
<bean id="jobConfigurationRegistry" class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry"/>
<bean id="jobLifecycle" class="org.springframework.batch.execution.job.DefaultJobExecutor">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="stepExecutorResolver">
<bean class="org.springframework.batch.execution.step.DefaultStepExecutorFactory">
<property name="stepExecutorName" value="stepLifecycle" />
</bean>
</property>
</bean>
<bean id="simpleJob" class="org.springframework.batch.core.configuration.JobConfiguration"
abstract="true">
<property name="restartable" value="true" />
</bean>
<bean id="simpleStep" class="org.springframework.batch.execution.step.simple.SimpleStepConfiguration"
abstract="true">
<property name="allowStartIfComplete" value="true" />
<property name="saveRestartData" value="false" />
<property name="exceptionHandler">
<bean
class="org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler">
<property name="limit" value="5" />
<property name="useParent" value="true"/>
</bean>
</property>
</bean>
<bean id="stepLifecycle" class="org.springframework.batch.execution.step.simple.SimpleStepExecutor" scope="prototype">
<property name="transactionManager" ref="transactionManager" />
<property name="repository" ref="simpleJobRepository" />
</bean>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="simpleJobRepository" class="org.springframework.batch.execution.repository.SimpleJobRepository">
<constructor-arg ref="jobDao" />
<constructor-arg ref="stepDao" />
</bean>
<bean id="jobDao" class="org.springframework.batch.execution.repository.dao.MapJobDao"/>
<!-- init-method="clear"/-->
<bean id="stepDao" class="org.springframework.batch.execution.repository.dao.MapStepDao" />
<!-- init-method="clear"/-->
<bean id="jobRuntimeInformationFactory"
class="org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory">
<property name="jobStream" value="TestStream" />
<property name="scheduleDate" value="20070505" />
<property name="jobRun" value="1" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="int[]">
<bean class="org.springframework.batch.support.IntArrayPropertyEditor" />
</entry>
<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>