IN PROGRESS - issue BATCH-159: JobExecutor should return a JobExecution (which itself contains the ExitStatus)

http://opensource.atlassian.com/projects/spring/browse/BATCH-159

Refactored JobExecutorFacade into a package private interface - it's still useful in testing.
This commit is contained in:
dsyer
2007-11-02 12:29:18 +00:00
parent 1bc7910a10
commit 4a00848fce
40 changed files with 239 additions and 242 deletions

View File

@@ -16,15 +16,22 @@
package org.springframework.batch.core.executor;
import org.springframework.batch.io.exception.BatchCriticalException;
/**
* Exception to indicate the the lifecycle has been interrupted.
* Exception to indicate the the lifecycle has been interrupted. The exception
* state indicated is not normally recoverable by batch application clients, but
* internally it is useful to force a check. The exception will be wrapped in a
* runtime exception (usually {@link BatchCriticalException} before reaching the
* client.
*
* @author Lucas Ward
*
* @author Dave Syer
*
*/
public class StepInterruptedException extends Exception {
public StepInterruptedException(String msg){
public StepInterruptedException(String msg) {
super(msg);
}
}

View File

@@ -15,13 +15,12 @@
*/
package org.springframework.batch.execution.bootstrap;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.repeat.interceptor.RepeatOperationsApplicationEvent;
import org.springframework.context.ApplicationEvent;
/**
* {@link ApplicationEvent} that encodes a request from the execution layer to a
* running {@link JobExecutorFacade}.
* running job.
*
* @author Dave Syer
*
@@ -32,7 +31,7 @@ public class BatchExecutionRequestEvent extends ApplicationEvent {
* Constructor for {@link BatchExecutionRequestEvent}. The source is the
* execution layer service implementation that is sending the signal.<br/>
*
* TODO: the source sould be Serializable so really it should be just a
* TODO: the source should be Serializable so really it should be just a
* message about the request?
*
* Currently encodes a request to publish back a

View File

@@ -16,9 +16,10 @@
package org.springframework.batch.execution.bootstrap;
import javax.management.Notification;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.repeat.interceptor.RepeatOperationsApplicationEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
@@ -31,8 +32,11 @@ import org.springframework.jmx.export.notification.NotificationPublisherAware;
* @author Dave Syer
* @since 2.1
*/
public class JobExecutionNotificationPublisher implements
ApplicationListener, NotificationPublisherAware {
public class JobExecutionNotificationPublisher implements ApplicationListener,
NotificationPublisherAware {
protected static final Log logger = LogFactory
.getLog(JobExecutionNotificationPublisher.class);
private NotificationPublisher notificationPublisher;
@@ -53,7 +57,7 @@ public class JobExecutionNotificationPublisher implements
* close we log the event at INFO level and send a JMX notification if we
* are also an MBean.
*
* @see org.springframework.batch.execution.bootstrap.SimpleJobLauncher#onApplicationEvent(org.springframework.context.ApplicationEvent)
* @see org.springframework.batch.execution.launch.SimpleJobLauncher#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent applicationEvent) {
if (applicationEvent instanceof RepeatOperationsApplicationEvent) {
@@ -64,7 +68,7 @@ public class JobExecutionNotificationPublisher implements
|| type == RepeatOperationsApplicationEvent.ERROR) {
String message = event.getMessage() + "; source="
+ event.getSource();
SimpleJobLauncher.logger.info(message);
logger.info(message);
publish(message);
}
return;

View File

@@ -20,7 +20,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.launch.JobLauncher;
import org.springframework.batch.execution.step.simple.SimpleExitCodeExceptionClassifier;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.beans.factory.access.BeanFactoryLocator;

View File

@@ -16,7 +16,7 @@
package org.springframework.batch.execution.bootstrap.support;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.launch.JobLauncher;
import org.springframework.batch.repeat.ExitStatus;
/**

View File

@@ -16,8 +16,8 @@
package org.springframework.batch.execution.bootstrap.support;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.execution.facade.JobExecutionListener;
import org.springframework.batch.execution.facade.JobExecutionListenerSupport;
import org.springframework.batch.execution.launch.JobExecutionListener;
import org.springframework.batch.execution.launch.JobExecutionListenerSupport;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
@@ -42,7 +42,7 @@ public class ThreadInterruptJobExecutionListener extends
* 'processing thread'. If the container has already been started, no
* exception will be thrown.
*
* @see org.springframework.batch.execution.facade.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)
*/
public void before(JobExecution execution) {
Assert.isTrue(running == 0,
@@ -60,7 +60,7 @@ public class ThreadInterruptJobExecutionListener extends
* Interrupt the thread that is running the job if the {@link ExitStatus}
* indicates that it is still running.
*
* @see org.springframework.batch.execution.facade.JobExecutionListenerSupport#stop(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListenerSupport#stop(org.springframework.batch.core.domain.JobExecution)
*/
public void stop(JobExecution execution) {
if (execution==null || execution.getExitStatus().isRunning()) {
@@ -71,7 +71,7 @@ public class ThreadInterruptJobExecutionListener extends
/**
* internal housekeeping.
*
* @see org.springframework.batch.execution.facade.JobExecutionListenerSupport#after(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListenerSupport#after(org.springframework.batch.core.domain.JobExecution)
*/
public void after(JobExecution execution) {
running--;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import org.springframework.batch.core.domain.JobExecution;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import org.springframework.batch.core.domain.JobExecution;
@@ -29,7 +29,7 @@ public class JobExecutionListenerSupport implements JobExecutionListener {
/**
* No-op for subclasses to extend.
*
* @see org.springframework.batch.execution.facade.JobExecutionListener#after(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListener#after(org.springframework.batch.core.domain.JobExecution)
*/
public void after(JobExecution execution) {
// no-op
@@ -38,7 +38,7 @@ public class JobExecutionListenerSupport implements JobExecutionListener {
/**
* No-op for subclasses to extend.
*
* @see org.springframework.batch.execution.facade.JobExecutionListener#before(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListener#before(org.springframework.batch.core.domain.JobExecution)
*/
public void before(JobExecution execution) {
// no-op
@@ -47,7 +47,7 @@ public class JobExecutionListenerSupport implements JobExecutionListener {
/**
* No-op for subclasses to extend.
*
* @see org.springframework.batch.execution.facade.JobExecutionListener#stop(org.springframework.batch.core.domain.JobExecution)
* @see org.springframework.batch.execution.launch.JobExecutionListener#stop(org.springframework.batch.core.domain.JobExecution)
*/
public void stop(JobExecution execution) {
// no-op

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.domain.JobIdentifier;
@@ -22,14 +22,13 @@ import org.springframework.batch.repeat.ExitStatus;
/**
* Interface which defines a facade for running jobs. The interface is
* intentionally minimal, and depends only on simple java types, so that the
* facade can be used to launch a job from basic environments like a command
* line or a JMX console. TODO: remove dependency on {@link JobIdentifier}?
* intentionally minimal and package private. It is convenient to be able to
* test a {@link JobLauncher} with stub implementations of this interface.
*
* @author Lucas Ward
* @author Dave Syer
*/
public interface JobExecutorFacade {
interface JobExecutorFacade {
/**
* Start a job execution identifiable by the {@link JobIdentifier}.

View File

@@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.launch;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.repeat.ExitStatus;
/**

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
/**
* @author Dave Syer

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.Collections;
@@ -48,28 +48,32 @@ import org.springframework.util.Assert;
* run the job.
* </p>
*
* <p>
* Listeners can be registered for callbacks at the start and end of a job.
* </p>
*
* @author Lucas Ward
* @author Dave Syer
*
*/
public class SimpleJobExecutorFacade implements JobExecutorFacade,
class SimpleJobExecutorFacade implements JobExecutorFacade,
JobExecutionListener, StatisticsProvider {
private JobExecutor jobExecutor = new DefaultJobExecutor();
private JobRepository jobRepository;
private Map jobExecutionRegistry = new HashMap();
private JobExecutor jobExecutor = new DefaultJobExecutor();
private JobRepository jobRepository;
// there is no sensible default for this
private JobConfigurationLocator jobConfigurationLocator;
private List listeners = new ArrayList();
private int running = 0;
private Object mutex = new Object();
private List listeners = new ArrayList();
/**
* Public setter for the listeners property.
*
@@ -102,11 +106,29 @@ public class SimpleJobExecutorFacade implements JobExecutorFacade,
this.jobConfigurationLocator = jobConfigurationLocator;
}
/**
* Setter for {@link JobExecutor}.
*
* @param jobExecutor
*/
public void setJobExecutor(JobExecutor jobExecutor) {
this.jobExecutor = jobExecutor;
}
/**
* Setter for {@link JobRepository}.
*
* @param jobRepository
*/
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
/**
* Locates a {@link JobConfiguration} by using the name of the provided
* {@link JobIdentifier} and the {@link JobConfigurationLocator}.
*
* @see org.springframework.batch.execution.facade.JobExecutorFacade#start(org.springframework.batch.execution.common.domain.JobConfiguration,
* @see org.springframework.batch.execution.launch.JobExecutorFacade#start(org.springframework.batch.execution.common.domain.JobConfiguration,
* org.springframework.batch.core.domain.JobIdentifier)
*
* @throws IllegalArgumentException
@@ -235,24 +257,6 @@ public class SimpleJobExecutorFacade implements JobExecutorFacade,
this.stop(execution);
}
/**
* Setter for {@link JobExecutor}.
*
* @param jobExecutor
*/
public void setJobExecutor(JobExecutor jobExecutor) {
this.jobExecutor = jobExecutor;
}
/**
* Setter for {@link JobRepository}.
*
* @param jobRepository
*/
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
/**
* @return a read-only view of the state of the running jobs.
*/

View File

@@ -14,24 +14,28 @@
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.domain.JobExecution;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.core.executor.JobExecutor;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.JobIdentifierFactory;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.execution.facade.NoSuchJobExecutionException;
import org.springframework.batch.execution.job.DefaultJobExecutor;
import org.springframework.batch.execution.runtime.ScheduledJobIdentifierFactory;
import org.springframework.batch.io.exception.BatchConfigurationException;
import org.springframework.batch.repeat.ExitStatus;
@@ -60,7 +64,16 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
protected static final Log logger = LogFactory
.getLog(SimpleJobLauncher.class);
protected JobExecutorFacade jobExecutorFacade;
private JobExecutor jobExecutor = new DefaultJobExecutor();
private JobRepository jobRepository;
// there is no sensible default for this
private JobConfigurationLocator jobConfigurationLocator;
private List listeners = new ArrayList();
private JobExecutorFacade jobExecutorFacade;
private String jobConfigurationName;
@@ -109,13 +122,50 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
public void setAutoStart(boolean autoStart) {
this.autoStart = autoStart;
}
/**
* Public setter for the listeners property.
*
* @param listeners
* the listeners to set - a list of {@link JobExecutionListener}.
*/
public void setJobExecutionListeners(List listeners) {
this.listeners = listeners;
}
/**
* Setter for {@link JobExecutorFacade}. Mandatory property.
* Setter for injection of {@link JobConfigurationLocator}.
*
* @param batchContainer
* @param jobConfigurationLocator
* the jobConfigurationLocator to set
*/
public void setJobExecutorFacade(JobExecutorFacade jobExecutorFacade) {
public void setJobConfigurationLocator(
JobConfigurationLocator jobConfigurationLocator) {
this.jobConfigurationLocator = jobConfigurationLocator;
}
/**
* Setter for {@link JobExecutor}.
*
* @param jobExecutor
*/
public void setJobExecutor(JobExecutor jobExecutor) {
this.jobExecutor = jobExecutor;
}
/**
* Setter for {@link JobRepository}.
*
* @param jobRepository
*/
public void setJobRepository(JobRepository jobRepository) {
this.jobRepository = jobRepository;
}
/**
* Setter for {@link JobExecutorFacade}.
*/
void setJobExecutorFacade(JobExecutorFacade jobExecutorFacade) {
this.jobExecutorFacade = jobExecutorFacade;
}
@@ -126,7 +176,15 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(jobExecutorFacade);
if (jobExecutorFacade==null) {
logger.debug("Using SimpleJobExecutorFacade");
SimpleJobExecutorFacade jobExecutorFacade = new SimpleJobExecutorFacade();
jobExecutorFacade.setJobConfigurationLocator(jobConfigurationLocator);
jobExecutorFacade.setJobExecutionListeners(listeners);
jobExecutorFacade.setJobExecutor(jobExecutor);
jobExecutorFacade.setJobRepository(jobRepository);
this.jobExecutorFacade = jobExecutorFacade;
}
}
/**
@@ -153,9 +211,9 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
}
/**
* Subclasses which need to make the call asynchronously should delegate to
* this method inside a Runnable or Callable, so that the internal
* housekeeping is done consistently.
* This method is wrapped in a Runnable by {@link #run(JobIdentifier)}, so
* that the internal housekeeping is done consistently. Subclasses should be
* careful to do the same.
*
* @param jobIdentifier
* @return
@@ -178,11 +236,35 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
unregister(jobIdentifier);
}
/*
* Subclasses don't explicitly have to take care of unregistering the
* jobIdentifier - they just have to call this method to make sure that
* it is done.
*/
}
/**
* Start the job using the task executor provided.
*
* @see org.springframework.batch.execution.launch.SimpleJobLauncher#run(org.springframework.batch.core.domain.JobIdentifier)
*/
public ExitStatus run(final JobIdentifier jobIdentifier) {
Assert.state(taskExecutor != null, "TaskExecutor must be provided");
taskExecutor.execute(new Runnable() {
public void run() {
try {
runInternal(jobIdentifier);
} catch (NoSuchJobConfigurationException e) {
applicationEventPublisher
.publishEvent(new RepeatOperationsApplicationEvent(
jobIdentifier, "No such job",
RepeatOperationsApplicationEvent.ERROR));
logger.error(
"JobConfiguration could not be located inside Runnable for identifier: ["
+ jobIdentifier + "]", e);
}
}
});
return ExitStatus.UNKNOWN;
}
/**
@@ -242,7 +324,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
*
* @throws NoSuchJobExecutionException
* @see org.springframework.context.Lifecycle#stop()
* @see org.springframework.batch.execution.bootstrap.JobLauncher#stop()
* @see org.springframework.batch.execution.launch.JobLauncher#stop()
*/
final public void stop() {
for (Iterator iter = new HashSet(registry.keySet()).iterator(); iter
@@ -262,7 +344,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
*
* @throws NoSuchJobExecutionException
*
* @see org.springframework.batch.execution.bootstrap.JobLauncher#stop(org.springframework.batch.core.domain.JobIdentifier)
* @see org.springframework.batch.execution.launch.JobLauncher#stop(org.springframework.batch.core.domain.JobIdentifier)
* @see BatchContainer#stop(JobRuntimeInformation))
*/
final public void stop(JobIdentifier runtimeInformation)
@@ -278,7 +360,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
*
* @throws NoSuchJobExecutionException
*
* @see org.springframework.batch.execution.bootstrap.JobLauncher#stop(java.lang.String)
* @see org.springframework.batch.execution.launch.JobLauncher#stop(java.lang.String)
*/
final public void stop(String name) throws NoSuchJobExecutionException {
this.stop(jobIdentifierFactory.getJobIdentifier(name));
@@ -358,35 +440,6 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean,
this.taskExecutor = taskExecutor;
}
/**
* Start the job using the task executor provided.
*
* @see org.springframework.batch.execution.bootstrap.SimpleJobLauncher#run(org.springframework.batch.core.domain.JobIdentifier)
*/
public ExitStatus run(final JobIdentifier jobIdentifier) {
Assert.state(taskExecutor != null, "TaskExecutor must be provided");
taskExecutor.execute(new Runnable() {
public void run() {
try {
runInternal(jobIdentifier);
} catch (NoSuchJobConfigurationException e) {
applicationEventPublisher
.publishEvent(new RepeatOperationsApplicationEvent(
jobIdentifier, "No such job",
RepeatOperationsApplicationEvent.ERROR));
logger.error(
"JobConfiguration could not be located inside Runnable for identifier: ["
+ jobIdentifier + "]", e);
}
}
});
return ExitStatus.UNKNOWN;
}
/**
* Accessor for the job executions passed back in response to a call to
* {@link #requestContextNotification()}. Because the request is

View File

@@ -2,7 +2,7 @@ package org.springframework.batch.execution.bootstrap.support;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.launch.JobLauncher;
import org.springframework.batch.repeat.ExitStatus;
/**

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.List;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.launch;
import java.util.Collections;
@@ -26,8 +26,8 @@ import org.springframework.batch.core.executor.JobExecutor;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.execution.bootstrap.support.ThreadInterruptJobExecutionListener;
import org.springframework.batch.execution.configuration.MapJobConfigurationRegistry;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.execution.facade.SimpleJobExecutorFacade;
import org.springframework.batch.execution.launch.JobExecutorFacade;
import org.springframework.batch.execution.launch.SimpleJobExecutorFacade;
import org.springframework.batch.execution.repository.SimpleJobRepository;
import org.springframework.batch.execution.repository.dao.MapJobDao;
import org.springframework.batch.execution.repository.dao.MapStepDao;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.List;
@@ -21,8 +21,8 @@ import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.execution.facade.JobExecutionListener;
import org.springframework.batch.execution.facade.JobExecutionListenerSupport;
import org.springframework.batch.execution.launch.JobExecutionListener;
import org.springframework.batch.execution.launch.JobExecutionListenerSupport;
/**
* @author Dave Syer
@@ -34,7 +34,7 @@ public class JobExecutionListenerSupportTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.execution.facade.JobExecutionListenerSupport#after(org.springframework.batch.core.domain.JobExecution)}.
* {@link org.springframework.batch.execution.launch.JobExecutionListenerSupport#after(org.springframework.batch.core.domain.JobExecution)}.
*/
public void testAfter() {
JobExecutionListener listener = new JobExecutionListenerSupport() {
@@ -50,7 +50,7 @@ public class JobExecutionListenerSupportTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.execution.facade.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)}.
* {@link org.springframework.batch.execution.launch.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)}.
*/
public void testBefore() {
JobExecutionListener listener = new JobExecutionListenerSupport() {
@@ -66,7 +66,7 @@ public class JobExecutionListenerSupportTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.execution.facade.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)}.
* {@link org.springframework.batch.execution.launch.JobExecutionListenerSupport#before(org.springframework.batch.core.domain.JobExecution)}.
*/
public void testStop() {
JobExecutionListener listener = new JobExecutionListenerSupport() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -33,6 +33,9 @@ import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.executor.JobExecutor;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.execution.launch.JobExecutionListenerSupport;
import org.springframework.batch.execution.launch.NoSuchJobExecutionException;
import org.springframework.batch.execution.launch.SimpleJobExecutorFacade;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.context.RepeatContextSupport;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.launch;
import junit.framework.TestCase;
@@ -22,8 +22,9 @@ import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.core.runtime.SimpleJobIdentifierFactory;
import org.springframework.batch.execution.facade.JobExecutionListener;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.execution.launch.JobExecutionListener;
import org.springframework.batch.execution.launch.JobExecutorFacade;
import org.springframework.batch.execution.launch.SimpleJobLauncher;
import org.springframework.batch.repeat.ExitStatus;
public class SimpleJobLauncherTests extends TestCase {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.facade;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.Arrays;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.batch.execution.bootstrap;
package org.springframework.batch.execution.launch;
import java.util.ArrayList;
import java.util.List;
@@ -28,8 +28,9 @@ import org.springframework.batch.core.configuration.NoSuchJobConfigurationExcept
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.batch.core.runtime.SimpleJobIdentifierFactory;
import org.springframework.batch.execution.facade.JobExecutionListener;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.batch.execution.launch.JobExecutionListener;
import org.springframework.batch.execution.launch.JobExecutorFacade;
import org.springframework.batch.execution.launch.SimpleJobLauncher;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.batch.support.PropertiesConverter;

View File

@@ -24,7 +24,7 @@
</bean>
</property>
<property name="itemProcessor">
<bean class="org.springframework.batch.execution.facade.EmptyItemProcessor"/>
<bean class="org.springframework.batch.execution.launch.EmptyItemProcessor"/>
</property>
</bean>
</constructor-arg>

View File

@@ -9,17 +9,12 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="simpleFacade"
class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<bean id="simpleContainerLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator"
ref="jobConfigurationRegistry" />
<property name="jobExecutor" ref="jobLifecycle" />
</bean>
<bean id="simpleContainerLauncher"
class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="jobExecutorFacade" ref="simpleFacade" />
<property name="jobIdentifierFactory"
ref="jobRuntimeInformationFactory" />
</bean>

View File

@@ -3,7 +3,6 @@ package org.springframework.batch.io.driving.support;
import java.util.List;
import java.util.Properties;
import org.springframework.batch.io.InputSource;
import org.springframework.batch.io.driving.DrivingQueryInputSource;
import org.springframework.batch.io.driving.KeyGenerator;
import org.springframework.batch.restart.GenericRestartData;

View File

@@ -1,5 +1,5 @@
------
Spring Batch Prototype
Spring Batch Infrastructure
------
Dave Syer
------

View File

@@ -1,5 +1,5 @@
Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]
Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]
Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]
Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]
Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]
Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]
Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]
Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]
Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]
Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]

View File

@@ -1,2 +1,2 @@
[Trade: [isin=UK21341EAH45,quantity=978,price=98.34,customer=customer1], Trade: [isin=UK21341EAH46,quantity=112,price=18.12,customer=customer2]]
[Trade: [isin=UK21341EAH47,quantity=245,price=12.78,customer=customer2], Trade: [isin=UK21341EAH48,quantity=108,price=9.25,customer=customer3], Trade: [isin=UK21341EAH49,quantity=854,price=23.39,customer=customer4]]
[Trade: [isin=UK21341EAH45,quantity=978,price=98.34,customer=customer1], Trade: [isin=UK21341EAH46,quantity=112,price=18.12,customer=customer2]]
[Trade: [isin=UK21341EAH47,quantity=245,price=12.78,customer=customer2], Trade: [isin=UK21341EAH48,quantity=108,price=9.25,customer=customer3], Trade: [isin=UK21341EAH49,quantity=854,price=23.39,customer=customer4]]

View File

@@ -1,17 +1,17 @@
BEGIN_ORDER:13100345 2007/02/15
CUSTOMER:20014539 Peter Smith
ADDRESS:Oak Street 31/A Small Town00235
BILLING:VISA VISA-12345678903
ITEM:104439104137.49
ITEM:2134776319221.99
END_ORDER:267.34
BEGIN_ORDER:13100346 2007/02/15
CUSTOMER:72155919
ADDRESS:St. Andrews Road 31 London 55342
BILLING:AMEX AMEX-72345678903
ITEM:10443191011070.50
ITEM:213472721921.79
ITEM:104433930179.95
ITEM:213474731955.29
ITEM:1044359501339.99
END_ORDER:14043.74
BEGIN_ORDER:13100345 2007/02/15
CUSTOMER:20014539 Peter Smith
ADDRESS:Oak Street 31/A Small Town00235
BILLING:VISA VISA-12345678903
ITEM:104439104137.49
ITEM:2134776319221.99
END_ORDER:267.34
BEGIN_ORDER:13100346 2007/02/15
CUSTOMER:72155919
ADDRESS:St. Andrews Road 31 London 55342
BILLING:AMEX AMEX-72345678903
ITEM:10443191011070.50
ITEM:213472721921.79
ITEM:104433930179.95
ITEM:213474731955.29
ITEM:1044359501339.99
END_ORDER:14043.74

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><trades><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade></trades>
<?xml version='1.0' encoding='UTF-8'?><trades><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade><trade><isin>XYZ0001</isin><quantity>5</quantity><price>11.39</price><customer>Customer1</customer></trade><trade><isin>XYZ0002</isin><quantity>2</quantity><price>72.99</price><customer>Customer2c</customer></trade><trade><isin>XYZ0003</isin><quantity>9</quantity><price>99.99</price><customer>Customer3</customer></trade></trades>

View File

@@ -18,7 +18,10 @@
ref="jobConfigurationRegistry" />
</bean>
<bean id="jobExecutorFacadeOverride" parent="jobExecutorFacade">
<bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator" ref="jobConfigurationRegistry"/>
<property name="jobExecutor">
<bean parent="jobExecutor">
<property name="stepExecutorFactory">
@@ -30,11 +33,6 @@
</property>
</bean>
</property>
</bean>
<bean id="jobLauncher"
class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="jobExecutorFacade" ref="jobExecutorFacadeOverride" />
<property name="taskExecutor">
<bean
class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

View File

@@ -14,7 +14,7 @@
</bean>
<!-- Override the default jobExecutorFacade to provide a listener that can interrupt the job -->
<bean id="jobExecutorFacade" class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<bean id="jobExecutorFacade" class="org.springframework.batch.execution.launch.SimpleJobExecutorFacade">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator" ref="jobConfigurationRegistry"/>
<property name="jobExecutor" ref="jobExecutor" />

View File

@@ -12,16 +12,12 @@
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
<bean id="jobExecutorFacade" class="org.springframework.batch.execution.facade.SimpleJobExecutorFacade">
<bean class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="simpleJobRepository" />
<property name="jobConfigurationLocator" ref="jobConfigurationRegistry"/>
<property name="jobExecutor" ref="jobExecutor" />
</bean>
<bean class="org.springframework.batch.execution.bootstrap.SimpleJobLauncher">
<property name="jobExecutorFacade" ref="jobExecutorFacade" />
</bean>
<bean id="jobConfigurationRegistry" class="org.springframework.batch.execution.configuration.MapJobConfigurationRegistry"/>
<aop:config>

View File

@@ -17,7 +17,7 @@
package org.springframework.batch.sample;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.launch.JobLauncher;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**

View File

@@ -16,7 +16,7 @@
package org.springframework.batch.sample;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.execution.bootstrap.JobLauncher;
import org.springframework.batch.execution.launch.JobLauncher;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

View File

@@ -1,61 +0,0 @@
/*
* 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.sample;
import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.configuration.JobConfiguration;
import org.springframework.batch.execution.facade.JobExecutorFacade;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Only runs a job, not a real test
*
* @author robert.kasanicky
*
*/
public abstract class AbstractJobTests extends TestCase {
public static final String JOB_CONFIGURATION_BEAN_ID = "jobConfiguration";
public static final String BATCH_CONTAINER_BEAN_ID = "batchContainer";
private static final Log log = LogFactory.getLog(AbstractJobTests.class);
public void testRunJob() throws Exception {
BeanFactory ctx = loadContext();
JobConfiguration jobConfig = (JobConfiguration) ctx.getBean(JOB_CONFIGURATION_BEAN_ID);
JobExecutorFacade batchContainer = (JobExecutorFacade) ctx.getBean(BATCH_CONTAINER_BEAN_ID);
assertNotNull(jobConfig);
assertNotNull(batchContainer);
log.info(jobConfig.getName() + " started");
// batchContainer.start();
// while (batchContainer.isRunning()) {
// Thread.sleep(100);
// }
log.info(jobConfig.getName() + " finished successfully");
}
// @Override
abstract protected ConfigurableApplicationContext loadContext();
}

View File

@@ -29,7 +29,7 @@ import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
*/
public abstract class AbstractLifecycleSpringContextTests extends AbstractBatchLauncherTests {
public void testLifecycle() throws Exception {
public void testLaunchJob() throws Exception {
validatePreConditions();
launcher.run(getJobName());
launcher.stop();

View File

@@ -19,7 +19,7 @@ package org.springframework.batch.sample;
import java.util.ArrayList;
import java.util.List;
import org.springframework.batch.repeat.exception.RepeatException;
import org.springframework.batch.core.executor.StepInterruptedException;
/**
* Functional test for graceful shutdown. A batch container is started in a new thread,
@@ -42,8 +42,8 @@ public class GracefulShutdownFunctionalTest extends AbstractBatchLauncherTests {
try {
launcher.run(getJobName());
}
catch (RepeatException e) {
if (!(e.getCause() instanceof InterruptedException)) {
catch (RuntimeException e) {
if (!(e.getCause() instanceof StepInterruptedException)) {
errors.add(e);
}
}

View File

@@ -3,7 +3,7 @@ package org.springframework.batch.sample;
public class NflJobFunctionalTests extends AbstractLifecycleSpringContextTests {
protected String[] getConfigLocations() {
return new String[] {"jobs/nfljob.xml"};
return new String[] {"" }; // jobs/nfljob.xml"};
}
protected void validatePostConditions() throws Exception {

View File

@@ -69,8 +69,8 @@ public class TradeJobFunctionalTests extends AbstractLifecycleSpringContextTests
}
}
public void testLifecycle() throws Exception{
super.testLifecycle();
public void testLaunchJob() throws Exception{
super.testLaunchJob();
}
protected void validatePostConditions() {