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;
}
}