Change svn:eol-style to LF
This commit is contained in:
@@ -1,113 +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.configuration;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobLocator;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that registers {@link Job} beans
|
||||
* with a {@link JobRegistry}. Include a bean of this type along
|
||||
* with your job configuration, and use the same
|
||||
* {@link JobRegistry} as a {@link JobLocator} when
|
||||
* you need to locate a {@link JobLocator} to launch.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobRegistryBeanPostProcessor implements BeanPostProcessor, InitializingBean, DisposableBean {
|
||||
|
||||
// It doesn't make sense for this to have a default value...
|
||||
private JobRegistry jobConfigurationRegistry = null;
|
||||
|
||||
private Collection jobNames = new HashSet();
|
||||
|
||||
/**
|
||||
* Injection setter for {@link JobRegistry}.
|
||||
*
|
||||
* @param jobRegistry the jobConfigurationRegistry to set
|
||||
*/
|
||||
public void setJobRegistry(JobRegistry jobRegistry) {
|
||||
this.jobConfigurationRegistry = jobRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the registry is set before use.
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jobConfigurationRegistry, "JobConfigurationRegistry must not be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register all the {@link Job} instances that were
|
||||
* regsistered by this post processor.
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
for (Iterator iter = jobNames.iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
jobConfigurationRegistry.unregister(name);
|
||||
}
|
||||
jobNames.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the bean is an instance of {@link Job} then register it.
|
||||
* @throws FatalBeanException if there is a
|
||||
* {@link DuplicateJobException}.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof Job) {
|
||||
Job job = (Job) bean;
|
||||
try {
|
||||
jobConfigurationRegistry.register(new ReferenceJobFactory(job));
|
||||
jobNames.add(job.getName());
|
||||
}
|
||||
catch (DuplicateJobException e) {
|
||||
throw new FatalBeanException("Cannot register job configuration", e);
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobLocator;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that registers {@link Job} beans
|
||||
* with a {@link JobRegistry}. Include a bean of this type along
|
||||
* with your job configuration, and use the same
|
||||
* {@link JobRegistry} as a {@link JobLocator} when
|
||||
* you need to locate a {@link JobLocator} to launch.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobRegistryBeanPostProcessor implements BeanPostProcessor, InitializingBean, DisposableBean {
|
||||
|
||||
// It doesn't make sense for this to have a default value...
|
||||
private JobRegistry jobConfigurationRegistry = null;
|
||||
|
||||
private Collection jobNames = new HashSet();
|
||||
|
||||
/**
|
||||
* Injection setter for {@link JobRegistry}.
|
||||
*
|
||||
* @param jobRegistry the jobConfigurationRegistry to set
|
||||
*/
|
||||
public void setJobRegistry(JobRegistry jobRegistry) {
|
||||
this.jobConfigurationRegistry = jobRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the registry is set before use.
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jobConfigurationRegistry, "JobConfigurationRegistry must not be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register all the {@link Job} instances that were
|
||||
* regsistered by this post processor.
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
for (Iterator iter = jobNames.iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
jobConfigurationRegistry.unregister(name);
|
||||
}
|
||||
jobNames.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the bean is an instance of {@link Job} then register it.
|
||||
* @throws FatalBeanException if there is a
|
||||
* {@link DuplicateJobException}.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof Job) {
|
||||
Job job = (Job) bean;
|
||||
try {
|
||||
jobConfigurationRegistry.register(new ReferenceJobFactory(job));
|
||||
jobNames.add(job.getName());
|
||||
}
|
||||
catch (DuplicateJobException e) {
|
||||
throw new FatalBeanException("Cannot register job configuration", e);
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobFactory;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.ListableJobRegistry;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple map-based implementation of {@link JobRegistry}. Access to the map is
|
||||
* synchronized, guarded by an internal lock.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MapJobRegistry implements ListableJobRegistry {
|
||||
|
||||
private Map map = new HashMap();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#registerJobConfiguration(org.springframework.batch.container.common.configuration.JobConfiguration)
|
||||
*/
|
||||
public void register(JobFactory jobFactory) throws DuplicateJobException {
|
||||
Assert.notNull(jobFactory);
|
||||
String name = jobFactory.getJobName();
|
||||
Assert.notNull(name, "Job configuration must have a name.");
|
||||
synchronized (map) {
|
||||
if (map.containsKey(name)) {
|
||||
throw new DuplicateJobException("A job configuration with this name [" + name
|
||||
+ "] was already registered");
|
||||
}
|
||||
map.put(name, jobFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#unregister(org.springframework.batch.container.common.configuration.JobConfiguration)
|
||||
*/
|
||||
public void unregister(String name) {
|
||||
Assert.notNull(name, "Job configuration must have a name.");
|
||||
synchronized (map) {
|
||||
map.remove(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationLocator#getJobConfiguration(java.lang.String)
|
||||
*/
|
||||
public Job getJob(String name) throws NoSuchJobException {
|
||||
synchronized (map) {
|
||||
if (!map.containsKey(name)) {
|
||||
throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered");
|
||||
}
|
||||
return (Job) ((JobFactory) map.get(name)).createJob();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.ListableJobConfigurationRegistry#getJobConfigurations()
|
||||
*/
|
||||
public Collection getJobNames() {
|
||||
synchronized (map) {
|
||||
return Collections.unmodifiableCollection(new HashSet(map.keySet()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobFactory;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.ListableJobRegistry;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple map-based implementation of {@link JobRegistry}. Access to the map is
|
||||
* synchronized, guarded by an internal lock.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MapJobRegistry implements ListableJobRegistry {
|
||||
|
||||
private Map map = new HashMap();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#registerJobConfiguration(org.springframework.batch.container.common.configuration.JobConfiguration)
|
||||
*/
|
||||
public void register(JobFactory jobFactory) throws DuplicateJobException {
|
||||
Assert.notNull(jobFactory);
|
||||
String name = jobFactory.getJobName();
|
||||
Assert.notNull(name, "Job configuration must have a name.");
|
||||
synchronized (map) {
|
||||
if (map.containsKey(name)) {
|
||||
throw new DuplicateJobException("A job configuration with this name [" + name
|
||||
+ "] was already registered");
|
||||
}
|
||||
map.put(name, jobFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#unregister(org.springframework.batch.container.common.configuration.JobConfiguration)
|
||||
*/
|
||||
public void unregister(String name) {
|
||||
Assert.notNull(name, "Job configuration must have a name.");
|
||||
synchronized (map) {
|
||||
map.remove(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.JobConfigurationLocator#getJobConfiguration(java.lang.String)
|
||||
*/
|
||||
public Job getJob(String name) throws NoSuchJobException {
|
||||
synchronized (map) {
|
||||
if (!map.containsKey(name)) {
|
||||
throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered");
|
||||
}
|
||||
return (Job) ((JobFactory) map.get(name)).createJob();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.configuration.ListableJobConfigurationRegistry#getJobConfigurations()
|
||||
*/
|
||||
public Collection getJobNames() {
|
||||
synchronized (map) {
|
||||
return Collections.unmodifiableCollection(new HashSet(map.keySet()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/*
|
||||
* 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.launch;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
|
||||
/**
|
||||
* Simple interface for controlling jobs, including possible ad-hoc executions,
|
||||
* based on different runtime identifiers. It is extremely important to note
|
||||
* that this interface makes absolutely no guarantees about whether or not calls
|
||||
* to it are executed synchronously or asynchronously. The javadocs for specific
|
||||
* implementations should be checked to ensure callers fully understand how the
|
||||
* job will be run.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
public interface JobLauncher {
|
||||
|
||||
/**
|
||||
* Start a job execution for the given {@link Job} and {@link JobParameters}.
|
||||
*
|
||||
* @return the exit code from the job if it returns synchronously. If the
|
||||
* implementation is asynchronous, the status might well be unknown.
|
||||
*
|
||||
* @throws JobExecutionAlreadyRunningException if the JobInstance identified
|
||||
* by the properties already has an execution running.
|
||||
* @throws IllegalArgumentException if the job or jobInstanceProperties are
|
||||
* null.
|
||||
* @throws JobRestartException if the job has been run before and
|
||||
* circumstances that preclude a re-start.
|
||||
*/
|
||||
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
|
||||
JobRestartException;
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.launch;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
|
||||
/**
|
||||
* Simple interface for controlling jobs, including possible ad-hoc executions,
|
||||
* based on different runtime identifiers. It is extremely important to note
|
||||
* that this interface makes absolutely no guarantees about whether or not calls
|
||||
* to it are executed synchronously or asynchronously. The javadocs for specific
|
||||
* implementations should be checked to ensure callers fully understand how the
|
||||
* job will be run.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
public interface JobLauncher {
|
||||
|
||||
/**
|
||||
* Start a job execution for the given {@link Job} and {@link JobParameters}.
|
||||
*
|
||||
* @return the exit code from the job if it returns synchronously. If the
|
||||
* implementation is asynchronous, the status might well be unknown.
|
||||
*
|
||||
* @throws JobExecutionAlreadyRunningException if the JobInstance identified
|
||||
* by the properties already has an execution running.
|
||||
* @throws IllegalArgumentException if the job or jobInstanceProperties are
|
||||
* null.
|
||||
* @throws JobRestartException if the job has been run before and
|
||||
* circumstances that preclude a re-start.
|
||||
*/
|
||||
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
|
||||
JobRestartException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
package org.springframework.batch.execution.launch.support;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* This interface should be implemented when an environment calling the batch famework has specific
|
||||
* requirements regarding the process return codes.
|
||||
*
|
||||
* @param The type of returncode expected by the environment
|
||||
* @author Stijn Maller
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface ExitCodeMapper {
|
||||
|
||||
static int JVM_EXITCODE_COMPLETED = 0;
|
||||
static int JVM_EXITCODE_GENERIC_ERROR = 1;
|
||||
static int JVM_EXITCODE_JOB_ERROR = 2;
|
||||
public static final String NO_SUCH_JOB = "NO_SUCH_JOB";
|
||||
public static final String JOB_NOT_PROVIDED = "JOB_NOT_PROVIDED";
|
||||
|
||||
/**
|
||||
* Transform the exitcode known by the batchframework into an exitcode in the
|
||||
* format of the calling environment.
|
||||
* @param exitCode The exitcode which is used internally by the batch framework.
|
||||
* @return The corresponding exitcode as known by the calling environment.
|
||||
*/
|
||||
public int getExitCode(String exitCode);
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.launch.support;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* This interface should be implemented when an environment calling the batch famework has specific
|
||||
* requirements regarding the process return codes.
|
||||
*
|
||||
* @param The type of returncode expected by the environment
|
||||
* @author Stijn Maller
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface ExitCodeMapper {
|
||||
|
||||
static int JVM_EXITCODE_COMPLETED = 0;
|
||||
static int JVM_EXITCODE_GENERIC_ERROR = 1;
|
||||
static int JVM_EXITCODE_JOB_ERROR = 2;
|
||||
public static final String NO_SUCH_JOB = "NO_SUCH_JOB";
|
||||
public static final String JOB_NOT_PROVIDED = "JOB_NOT_PROVIDED";
|
||||
|
||||
/**
|
||||
* Transform the exitcode known by the batchframework into an exitcode in the
|
||||
* format of the calling environment.
|
||||
* @param exitCode The exitcode which is used internally by the batch framework.
|
||||
* @return The corresponding exitcode as known by the calling environment.
|
||||
*/
|
||||
public int getExitCode(String exitCode);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,74 +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.launch.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.execution.launch.JobLauncher;
|
||||
|
||||
/**
|
||||
* Interface to expose for remote management of jobs. Similar to
|
||||
* {@link JobLauncher}, but replaces {@link JobExecution} and
|
||||
* {@link JobIdentifier} with Strings in return types and method parameters, so
|
||||
* it can be inspected by remote clients like the jconsole from the JRE without
|
||||
* any links to Spring Batch.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ExportedJobLauncher {
|
||||
|
||||
/**
|
||||
* Launch a job with the given name.
|
||||
*
|
||||
* @param name the name of the job to launch
|
||||
* @return a representation of the {@link JobExecution} returned by a
|
||||
* {@link JobLauncher}.
|
||||
*/
|
||||
String run(String name);
|
||||
|
||||
/**
|
||||
* Launch a job with the given name and parameters.
|
||||
*
|
||||
* @param name the name of the job to launch
|
||||
* @return a representation of the {@link JobExecution} returned by a
|
||||
* {@link JobLauncher}.
|
||||
*/
|
||||
String run(String name, String params);
|
||||
|
||||
/**
|
||||
* Stop all running jobs.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Enquire if any jobs launched here are still running.
|
||||
*
|
||||
* @return true if any jobs are running.
|
||||
*/
|
||||
boolean isRunning();
|
||||
|
||||
/**
|
||||
* Query statistics of currently executing jobs.
|
||||
*
|
||||
* @return properties representing last known state of currently executing
|
||||
* jobs
|
||||
*/
|
||||
public Properties getStatistics();
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.execution.launch.JobLauncher;
|
||||
|
||||
/**
|
||||
* Interface to expose for remote management of jobs. Similar to
|
||||
* {@link JobLauncher}, but replaces {@link JobExecution} and
|
||||
* {@link JobIdentifier} with Strings in return types and method parameters, so
|
||||
* it can be inspected by remote clients like the jconsole from the JRE without
|
||||
* any links to Spring Batch.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ExportedJobLauncher {
|
||||
|
||||
/**
|
||||
* Launch a job with the given name.
|
||||
*
|
||||
* @param name the name of the job to launch
|
||||
* @return a representation of the {@link JobExecution} returned by a
|
||||
* {@link JobLauncher}.
|
||||
*/
|
||||
String run(String name);
|
||||
|
||||
/**
|
||||
* Launch a job with the given name and parameters.
|
||||
*
|
||||
* @param name the name of the job to launch
|
||||
* @return a representation of the {@link JobExecution} returned by a
|
||||
* {@link JobLauncher}.
|
||||
*/
|
||||
String run(String name, String params);
|
||||
|
||||
/**
|
||||
* Stop all running jobs.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Enquire if any jobs launched here are still running.
|
||||
*
|
||||
* @return true if any jobs are running.
|
||||
*/
|
||||
boolean isRunning();
|
||||
|
||||
/**
|
||||
* Query statistics of currently executing jobs.
|
||||
*
|
||||
* @return properties representing last known state of currently executing
|
||||
* jobs
|
||||
*/
|
||||
public Properties getStatistics();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link SystemExiter} interface that calls the standards
|
||||
* System.exit method. It should be noted that there will be no unit tests for
|
||||
* this class, since there is only one line of actual code, that would only be
|
||||
* testable by mocking System or Runtime.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JvmSystemExiter implements SystemExiter {
|
||||
|
||||
/**
|
||||
* Delegate call to System.exit() with the argument provided. Do not use
|
||||
* this at home children!
|
||||
*
|
||||
* @see org.springframework.batch.execution.launch.support.SystemExiter#exit(int)
|
||||
*/
|
||||
public void exit(int status) {
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link SystemExiter} interface that calls the standards
|
||||
* System.exit method. It should be noted that there will be no unit tests for
|
||||
* this class, since there is only one line of actual code, that would only be
|
||||
* testable by mocking System or Runtime.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JvmSystemExiter implements SystemExiter {
|
||||
|
||||
/**
|
||||
* Delegate call to System.exit() with the argument provided. Do not use
|
||||
* this at home children!
|
||||
*
|
||||
* @see org.springframework.batch.execution.launch.support.SystemExiter#exit(int)
|
||||
*/
|
||||
public void exit(int status) {
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of {@link ExitCodeMapper} that can be configured
|
||||
* through a map from batch exit codes (String) to integer results.
|
||||
*
|
||||
* @author Stijn Maller
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
public class SimpleJvmExitCodeMapper implements ExitCodeMapper {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Map mapping;
|
||||
|
||||
public SimpleJvmExitCodeMapper(){
|
||||
mapping = new HashMap();
|
||||
mapping.put(ExitStatus.FINISHED.getExitCode(),
|
||||
new Integer(JVM_EXITCODE_COMPLETED));
|
||||
mapping.put(ExitStatus.FAILED.getExitCode(),
|
||||
new Integer(JVM_EXITCODE_GENERIC_ERROR));
|
||||
mapping.put(ExitCodeMapper.JOB_NOT_PROVIDED,
|
||||
new Integer(JVM_EXITCODE_JOB_ERROR));
|
||||
mapping.put(ExitCodeMapper.NO_SUCH_JOB,
|
||||
new Integer(JVM_EXITCODE_JOB_ERROR));
|
||||
}
|
||||
|
||||
public Map getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply the ExitCodeMappings
|
||||
* @param exitCodeMap A set of mappings between environment specific exit codes
|
||||
* and batch framework internal exit codes
|
||||
*/
|
||||
public void setMapping(Map exitCodeMap) {
|
||||
mapping.putAll(exitCodeMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JVM exitcode that matches a certain Batch Framework Exitcode
|
||||
* @param exitCode The exitcode of the Batch Job as known by the Batch Framework
|
||||
* @return The exitCode of the Batch Job as known by the JVM
|
||||
*/
|
||||
public int getExitCode(String exitCode) {
|
||||
|
||||
Integer statusCode = null;
|
||||
|
||||
try{
|
||||
statusCode = (Integer)mapping.get(exitCode);
|
||||
}
|
||||
catch(RuntimeException ex){
|
||||
//We still need to return an exit code, even if there is an issue with
|
||||
//the mapper.
|
||||
logger.fatal("Error mapping exit code, generic exit code returned.", ex);
|
||||
}
|
||||
|
||||
return (statusCode != null) ? statusCode.intValue() : JVM_EXITCODE_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of {@link ExitCodeMapper} that can be configured
|
||||
* through a map from batch exit codes (String) to integer results.
|
||||
*
|
||||
* @author Stijn Maller
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
public class SimpleJvmExitCodeMapper implements ExitCodeMapper {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Map mapping;
|
||||
|
||||
public SimpleJvmExitCodeMapper(){
|
||||
mapping = new HashMap();
|
||||
mapping.put(ExitStatus.FINISHED.getExitCode(),
|
||||
new Integer(JVM_EXITCODE_COMPLETED));
|
||||
mapping.put(ExitStatus.FAILED.getExitCode(),
|
||||
new Integer(JVM_EXITCODE_GENERIC_ERROR));
|
||||
mapping.put(ExitCodeMapper.JOB_NOT_PROVIDED,
|
||||
new Integer(JVM_EXITCODE_JOB_ERROR));
|
||||
mapping.put(ExitCodeMapper.NO_SUCH_JOB,
|
||||
new Integer(JVM_EXITCODE_JOB_ERROR));
|
||||
}
|
||||
|
||||
public Map getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply the ExitCodeMappings
|
||||
* @param exitCodeMap A set of mappings between environment specific exit codes
|
||||
* and batch framework internal exit codes
|
||||
*/
|
||||
public void setMapping(Map exitCodeMap) {
|
||||
mapping.putAll(exitCodeMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JVM exitcode that matches a certain Batch Framework Exitcode
|
||||
* @param exitCode The exitcode of the Batch Job as known by the Batch Framework
|
||||
* @return The exitCode of the Batch Job as known by the JVM
|
||||
*/
|
||||
public int getExitCode(String exitCode) {
|
||||
|
||||
Integer statusCode = null;
|
||||
|
||||
try{
|
||||
statusCode = (Integer)mapping.get(exitCode);
|
||||
}
|
||||
catch(RuntimeException ex){
|
||||
//We still need to return an exit code, even if there is an issue with
|
||||
//the mapper.
|
||||
logger.fatal("Error mapping exit code, generic exit code returned.", ex);
|
||||
}
|
||||
|
||||
return (statusCode != null) ? statusCode.intValue() : JVM_EXITCODE_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
/**
|
||||
* Interface for exiting the JVM. This abstraction is only
|
||||
* useful in order to allow classes that make System.exit calls
|
||||
* to be testable, since calling System.exit during a unit
|
||||
* test would cause the entire jvm to finish.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public interface SystemExiter {
|
||||
|
||||
/**
|
||||
* Terminate the currently running Java Virtual Machine.
|
||||
*
|
||||
* @param status exit status.
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkExit</code>
|
||||
* method doesn't allow exit with the specified status.
|
||||
* @see System.exit
|
||||
*/
|
||||
void exit(int status);
|
||||
}
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
/**
|
||||
* Interface for exiting the JVM. This abstraction is only
|
||||
* useful in order to allow classes that make System.exit calls
|
||||
* to be testable, since calling System.exit during a unit
|
||||
* test would cause the entire jvm to finish.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public interface SystemExiter {
|
||||
|
||||
/**
|
||||
* Terminate the currently running Java Virtual Machine.
|
||||
*
|
||||
* @param status exit status.
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkExit</code>
|
||||
* method doesn't allow exit with the specified status.
|
||||
* @see System.exit
|
||||
*/
|
||||
void exit(int status);
|
||||
}
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Encapsulates common functionality needed by JDBC batch metadata DAOs -
|
||||
* provides jdbcTemplate for subclasses and handles table prefixes.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public abstract class AbstractJdbcBatchMetadataDao implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Default value for the table prefix property.
|
||||
*/
|
||||
public static final String DEFAULT_TABLE_PREFIX = "BATCH_";
|
||||
|
||||
private String tablePrefix = DEFAULT_TABLE_PREFIX;
|
||||
|
||||
private JdbcOperations jdbcTemplate;
|
||||
|
||||
protected String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%PREFIX%", tablePrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the table prefix property. This will be prefixed to all
|
||||
* the table names before queries are executed. Defaults to
|
||||
* {@value #DEFAULT_TABLE_PREFIX}.
|
||||
*
|
||||
* @param tablePrefix the tablePrefix to set
|
||||
*/
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
this.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
public void setJdbcTemplate(JdbcOperations jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
protected JdbcOperations getJdbcTemplate() {
|
||||
return jdbcTemplate;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jdbcTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Encapsulates common functionality needed by JDBC batch metadata DAOs -
|
||||
* provides jdbcTemplate for subclasses and handles table prefixes.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public abstract class AbstractJdbcBatchMetadataDao implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Default value for the table prefix property.
|
||||
*/
|
||||
public static final String DEFAULT_TABLE_PREFIX = "BATCH_";
|
||||
|
||||
private String tablePrefix = DEFAULT_TABLE_PREFIX;
|
||||
|
||||
private JdbcOperations jdbcTemplate;
|
||||
|
||||
protected String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%PREFIX%", tablePrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the table prefix property. This will be prefixed to all
|
||||
* the table names before queries are executed. Defaults to
|
||||
* {@value #DEFAULT_TABLE_PREFIX}.
|
||||
*
|
||||
* @param tablePrefix the tablePrefix to set
|
||||
*/
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
this.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
public void setJdbcTemplate(JdbcOperations jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
protected JdbcOperations getJdbcTemplate() {
|
||||
return jdbcTemplate;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jdbcTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,219 +1,219 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
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.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobExecutionDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class);
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION "
|
||||
+ "where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ? and START_TIME = (SELECT max(START_TIME) from %PREFIX%JOB_EXECUTION where JOB_INSTANCE_ID = ?)";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobExecutionIncrementer;
|
||||
|
||||
public List findJobExecutions(final JobInstance job) {
|
||||
|
||||
Assert.notNull(job, "Job cannot be null.");
|
||||
Assert.notNull(job.getId(), "Job Id cannot be null.");
|
||||
|
||||
return getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTIONS), new Object[] { job.getId() },
|
||||
new JobExecutionRowMapper(job));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#getJobExecutionCount(JobInstance)
|
||||
* @throws IllegalArgumentException if jobId is null.
|
||||
*/
|
||||
public int getJobExecutionCount(JobInstance jobInstance) {
|
||||
Long jobId = jobInstance.getId();
|
||||
Assert.notNull(jobId, "JobId cannot be null");
|
||||
|
||||
Object[] parameters = new Object[] { jobId };
|
||||
|
||||
return getJdbcTemplate().queryForInt(getQuery(GET_JOB_EXECUTION_COUNT), parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SQL implementation using Sequences via the Spring incrementer
|
||||
* abstraction. Once a new id has been obtained, the JobExecution is saved
|
||||
* via a SQL INSERT statement.
|
||||
*
|
||||
* @see JobDao#saveJobExecution(JobExecution)
|
||||
* @throws IllegalArgumentException if jobExecution is null, as well as any
|
||||
* of it's fields to be persisted.
|
||||
*/
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue()));
|
||||
Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(),
|
||||
jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N", jobExecution.getExitStatus().getExitCode(),
|
||||
jobExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(
|
||||
getQuery(SAVE_JOB_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR,
|
||||
Types.VARCHAR, Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and
|
||||
* Status cannot be null.
|
||||
*
|
||||
* @param jobExecution
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
Assert.notNull(jobExecution);
|
||||
Assert.notNull(jobExecution.getJobId(), "JobExecution Job-Id cannot be null.");
|
||||
Assert.notNull(jobExecution.getStatus(), "JobExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update given JobExecution using a SQL UPDATE statement. The JobExecution
|
||||
* is first checked to ensure all fields are not null, and that it has an
|
||||
* ID. The database is then queried to ensure that the ID exists, which
|
||||
* ensures that it is valid.
|
||||
*
|
||||
* @see JobDao#updateJobExecution(JobExecution)
|
||||
*/
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
String exitDescription = jobExecution.getExitStatus().getExitDescription();
|
||||
if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger.debug("Truncating long message before update of JobExecution: " + jobExecution);
|
||||
}
|
||||
Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(),
|
||||
jobExecution.getStatus().toString(), jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(), exitDescription, jobExecution.getId() };
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
throw new IllegalArgumentException("JobExecution ID cannot be null. JobExecution must be saved "
|
||||
+ "before it can be updated.");
|
||||
}
|
||||
|
||||
// Check if given JobExecution's Id already exists, if none is found it
|
||||
// is invalid and
|
||||
// an exception should be thrown.
|
||||
if (getJdbcTemplate().queryForInt(getQuery(CHECK_JOB_EXECUTION_EXISTS), new Object[] { jobExecution.getId() }) != 1) {
|
||||
throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId()
|
||||
+ " not found.");
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(
|
||||
getQuery(UPDATE_JOB_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR,
|
||||
Types.INTEGER });
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobExecution} instances.
|
||||
*
|
||||
* @param jobExecutionIncrementer the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobExecutionIncrementer(DataFieldMaxValueIncrementer jobExecutionIncrementer) {
|
||||
this.jobExecutionIncrementer = jobExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobExecutionIncrementer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-usable mapper for {@link JobExecution} instances.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
private static class JobExecutionRowMapper implements RowMapper {
|
||||
|
||||
private JobInstance job;
|
||||
|
||||
public JobExecutionRowMapper(JobInstance job) {
|
||||
super();
|
||||
this.job = job;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobExecution jobExecution = new JobExecution(job);
|
||||
jobExecution.setId(new Long(rs.getLong(1)));
|
||||
jobExecution.setStartTime(rs.getTimestamp(2));
|
||||
jobExecution.setEndTime(rs.getTimestamp(3));
|
||||
jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4)));
|
||||
jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7)));
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public JobExecution getLastJobExecution(JobInstance jobInstance) {
|
||||
|
||||
Long id = jobInstance.getId();
|
||||
|
||||
List executions = getJdbcTemplate().query(getQuery(GET_LAST_EXECUTION), new Object[] { id, id },
|
||||
new JobExecutionRowMapper(jobInstance));
|
||||
|
||||
Assert.state(executions.size() <= 1, "There must be at most one latest job execution");
|
||||
|
||||
if (executions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (JobExecution) executions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
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.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobExecutionDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class);
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION "
|
||||
+ "where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ? and START_TIME = (SELECT max(START_TIME) from %PREFIX%JOB_EXECUTION where JOB_INSTANCE_ID = ?)";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobExecutionIncrementer;
|
||||
|
||||
public List findJobExecutions(final JobInstance job) {
|
||||
|
||||
Assert.notNull(job, "Job cannot be null.");
|
||||
Assert.notNull(job.getId(), "Job Id cannot be null.");
|
||||
|
||||
return getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTIONS), new Object[] { job.getId() },
|
||||
new JobExecutionRowMapper(job));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#getJobExecutionCount(JobInstance)
|
||||
* @throws IllegalArgumentException if jobId is null.
|
||||
*/
|
||||
public int getJobExecutionCount(JobInstance jobInstance) {
|
||||
Long jobId = jobInstance.getId();
|
||||
Assert.notNull(jobId, "JobId cannot be null");
|
||||
|
||||
Object[] parameters = new Object[] { jobId };
|
||||
|
||||
return getJdbcTemplate().queryForInt(getQuery(GET_JOB_EXECUTION_COUNT), parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SQL implementation using Sequences via the Spring incrementer
|
||||
* abstraction. Once a new id has been obtained, the JobExecution is saved
|
||||
* via a SQL INSERT statement.
|
||||
*
|
||||
* @see JobDao#saveJobExecution(JobExecution)
|
||||
* @throws IllegalArgumentException if jobExecution is null, as well as any
|
||||
* of it's fields to be persisted.
|
||||
*/
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue()));
|
||||
Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(),
|
||||
jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N", jobExecution.getExitStatus().getExitCode(),
|
||||
jobExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(
|
||||
getQuery(SAVE_JOB_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR,
|
||||
Types.VARCHAR, Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and
|
||||
* Status cannot be null.
|
||||
*
|
||||
* @param jobExecution
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
Assert.notNull(jobExecution);
|
||||
Assert.notNull(jobExecution.getJobId(), "JobExecution Job-Id cannot be null.");
|
||||
Assert.notNull(jobExecution.getStatus(), "JobExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update given JobExecution using a SQL UPDATE statement. The JobExecution
|
||||
* is first checked to ensure all fields are not null, and that it has an
|
||||
* ID. The database is then queried to ensure that the ID exists, which
|
||||
* ensures that it is valid.
|
||||
*
|
||||
* @see JobDao#updateJobExecution(JobExecution)
|
||||
*/
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
String exitDescription = jobExecution.getExitStatus().getExitDescription();
|
||||
if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger.debug("Truncating long message before update of JobExecution: " + jobExecution);
|
||||
}
|
||||
Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(),
|
||||
jobExecution.getStatus().toString(), jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(), exitDescription, jobExecution.getId() };
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
throw new IllegalArgumentException("JobExecution ID cannot be null. JobExecution must be saved "
|
||||
+ "before it can be updated.");
|
||||
}
|
||||
|
||||
// Check if given JobExecution's Id already exists, if none is found it
|
||||
// is invalid and
|
||||
// an exception should be thrown.
|
||||
if (getJdbcTemplate().queryForInt(getQuery(CHECK_JOB_EXECUTION_EXISTS), new Object[] { jobExecution.getId() }) != 1) {
|
||||
throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId()
|
||||
+ " not found.");
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(
|
||||
getQuery(UPDATE_JOB_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR,
|
||||
Types.INTEGER });
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobExecution} instances.
|
||||
*
|
||||
* @param jobExecutionIncrementer the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobExecutionIncrementer(DataFieldMaxValueIncrementer jobExecutionIncrementer) {
|
||||
this.jobExecutionIncrementer = jobExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobExecutionIncrementer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-usable mapper for {@link JobExecution} instances.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
private static class JobExecutionRowMapper implements RowMapper {
|
||||
|
||||
private JobInstance job;
|
||||
|
||||
public JobExecutionRowMapper(JobInstance job) {
|
||||
super();
|
||||
this.job = job;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobExecution jobExecution = new JobExecution(job);
|
||||
jobExecution.setId(new Long(rs.getLong(1)));
|
||||
jobExecution.setStartTime(rs.getTimestamp(2));
|
||||
jobExecution.setEndTime(rs.getTimestamp(3));
|
||||
jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4)));
|
||||
jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7)));
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public JobExecution getLastJobExecution(JobInstance jobInstance) {
|
||||
|
||||
Long id = jobInstance.getId();
|
||||
|
||||
List executions = getJdbcTemplate().query(getQuery(GET_LAST_EXECUTION), new Object[] { id, id },
|
||||
new JobExecutionRowMapper(jobInstance));
|
||||
|
||||
Assert.state(executions.size() <= 1, "There must be at most one latest job execution");
|
||||
|
||||
if (executions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (JobExecution) executions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,236 +1,236 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobInstanceDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean {
|
||||
|
||||
private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)"
|
||||
+ " values (?, ?, ?)";
|
||||
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, "
|
||||
+ "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL) values (?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobIncrementer;
|
||||
|
||||
/**
|
||||
* In this jdbc implementation a job id is obtained by asking the
|
||||
* jobIncrementer (which is likely a sequence) for the nextLong, and then
|
||||
* passing the Id and parameter values into an INSERT statement.
|
||||
*
|
||||
* @see JobDao#createJob(JobIdentifier)
|
||||
* @throws IllegalArgumentException if any {@link JobIdentifier} fields are
|
||||
* null.
|
||||
*/
|
||||
public JobInstance createJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(job, "Job must not be null.");
|
||||
Assert.hasLength(job.getName(), "Job must have a name");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist");
|
||||
|
||||
Long jobId = new Long(jobIncrementer.nextLongValue());
|
||||
Object[] parameters = new Object[] { jobId, job.getName(), createJobKey(jobParameters) };
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_INSTANCE), parameters,
|
||||
new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR });
|
||||
|
||||
insertJobParameters(jobId, jobParameters);
|
||||
|
||||
JobInstance jobInstance = new JobInstance(jobId, jobParameters, job);
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
private String createJobKey(JobParameters jobParameters) {
|
||||
|
||||
Map props = jobParameters.getParameters();
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
for (Iterator it = props.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
stringBuffer.append(entry.toString() + ";");
|
||||
}
|
||||
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts all parameters from the provided
|
||||
* JobParameters.
|
||||
*
|
||||
*/
|
||||
private void insertJobParameters(Long jobId, JobParameters jobParameters) {
|
||||
|
||||
Map parameters = jobParameters.getStringParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getLongParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDoubleParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.DOUBLE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDateParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts an individual records into the
|
||||
* JobParameters table.
|
||||
*/
|
||||
private void insertParameter(Long jobId, ParameterType type, String key, Object value) {
|
||||
|
||||
Object[] args = new Object[0];
|
||||
int[] argTypes = new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP,
|
||||
Types.INTEGER, Types.DOUBLE };
|
||||
|
||||
if (type == ParameterType.STRING) {
|
||||
args = new Object[] { jobId, key, type, value, new Timestamp(0L), new Long(0), new Double(0) };
|
||||
}
|
||||
else if (type == ParameterType.LONG) {
|
||||
args = new Object[] { jobId, key, type, "", new Timestamp(0L), value, new Double(0) };
|
||||
}
|
||||
else if (type == ParameterType.DOUBLE) {
|
||||
args = new Object[] { jobId, key, type, "", new Timestamp(0L), new Long(0), value };
|
||||
}
|
||||
else if (type == ParameterType.DATE) {
|
||||
args = new Object[] { jobId, key, type, "", value, new Long(0), new Double(0) };
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The job table is queried for <strong>any</strong> jobs that match the
|
||||
* given identifier, adding them to a list via the RowMapper callback.
|
||||
*
|
||||
* @see JobDao#findJobInstances(JobIdentifier)
|
||||
* @throws IllegalArgumentException if any {@link JobIdentifier} fields are
|
||||
* null.
|
||||
*/
|
||||
public JobInstance getJobInstance(final Job job, final JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(job, "Job must not be null.");
|
||||
Assert.hasLength(job.getName(), "Job must have a name");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Object[] parameters = new Object[] { job.getName(), createJobKey(jobParameters) };
|
||||
|
||||
RowMapper rowMapper = new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters, job);
|
||||
return jobInstance;
|
||||
}
|
||||
};
|
||||
|
||||
List instances = getJdbcTemplate().query(getQuery(FIND_JOBS), parameters, rowMapper);
|
||||
|
||||
if (instances.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
Assert.state(instances.size() == 1);
|
||||
return (JobInstance) instances.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobInstance} instances.
|
||||
*
|
||||
* @param jobIncrementer the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) {
|
||||
this.jobIncrementer = jobIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobIncrementer);
|
||||
}
|
||||
|
||||
private static class ParameterType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private ParameterType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final ParameterType STRING = new ParameterType("STRING");
|
||||
|
||||
public static final ParameterType DATE = new ParameterType("DATE");
|
||||
|
||||
public static final ParameterType LONG = new ParameterType("LONG");
|
||||
|
||||
public static final ParameterType DOUBLE = new ParameterType("DOUBLE");
|
||||
|
||||
private static final ParameterType[] VALUES = { STRING, DATE, LONG, DOUBLE };
|
||||
|
||||
public static ParameterType getType(String typeAsString) {
|
||||
|
||||
for (int i = 0; i < VALUES.length; i++) {
|
||||
if (VALUES[i].toString().equals(typeAsString)) {
|
||||
return (ParameterType) VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobInstanceDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean {
|
||||
|
||||
private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)"
|
||||
+ " values (?, ?, ?)";
|
||||
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, "
|
||||
+ "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL) values (?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobIncrementer;
|
||||
|
||||
/**
|
||||
* In this jdbc implementation a job id is obtained by asking the
|
||||
* jobIncrementer (which is likely a sequence) for the nextLong, and then
|
||||
* passing the Id and parameter values into an INSERT statement.
|
||||
*
|
||||
* @see JobDao#createJob(JobIdentifier)
|
||||
* @throws IllegalArgumentException if any {@link JobIdentifier} fields are
|
||||
* null.
|
||||
*/
|
||||
public JobInstance createJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(job, "Job must not be null.");
|
||||
Assert.hasLength(job.getName(), "Job must have a name");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist");
|
||||
|
||||
Long jobId = new Long(jobIncrementer.nextLongValue());
|
||||
Object[] parameters = new Object[] { jobId, job.getName(), createJobKey(jobParameters) };
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_INSTANCE), parameters,
|
||||
new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR });
|
||||
|
||||
insertJobParameters(jobId, jobParameters);
|
||||
|
||||
JobInstance jobInstance = new JobInstance(jobId, jobParameters, job);
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
private String createJobKey(JobParameters jobParameters) {
|
||||
|
||||
Map props = jobParameters.getParameters();
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
for (Iterator it = props.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
stringBuffer.append(entry.toString() + ";");
|
||||
}
|
||||
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts all parameters from the provided
|
||||
* JobParameters.
|
||||
*
|
||||
*/
|
||||
private void insertJobParameters(Long jobId, JobParameters jobParameters) {
|
||||
|
||||
Map parameters = jobParameters.getStringParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getLongParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDoubleParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.DOUBLE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDateParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts an individual records into the
|
||||
* JobParameters table.
|
||||
*/
|
||||
private void insertParameter(Long jobId, ParameterType type, String key, Object value) {
|
||||
|
||||
Object[] args = new Object[0];
|
||||
int[] argTypes = new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP,
|
||||
Types.INTEGER, Types.DOUBLE };
|
||||
|
||||
if (type == ParameterType.STRING) {
|
||||
args = new Object[] { jobId, key, type, value, new Timestamp(0L), new Long(0), new Double(0) };
|
||||
}
|
||||
else if (type == ParameterType.LONG) {
|
||||
args = new Object[] { jobId, key, type, "", new Timestamp(0L), value, new Double(0) };
|
||||
}
|
||||
else if (type == ParameterType.DOUBLE) {
|
||||
args = new Object[] { jobId, key, type, "", new Timestamp(0L), new Long(0), value };
|
||||
}
|
||||
else if (type == ParameterType.DATE) {
|
||||
args = new Object[] { jobId, key, type, "", value, new Long(0), new Double(0) };
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The job table is queried for <strong>any</strong> jobs that match the
|
||||
* given identifier, adding them to a list via the RowMapper callback.
|
||||
*
|
||||
* @see JobDao#findJobInstances(JobIdentifier)
|
||||
* @throws IllegalArgumentException if any {@link JobIdentifier} fields are
|
||||
* null.
|
||||
*/
|
||||
public JobInstance getJobInstance(final Job job, final JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(job, "Job must not be null.");
|
||||
Assert.hasLength(job.getName(), "Job must have a name");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Object[] parameters = new Object[] { job.getName(), createJobKey(jobParameters) };
|
||||
|
||||
RowMapper rowMapper = new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters, job);
|
||||
return jobInstance;
|
||||
}
|
||||
};
|
||||
|
||||
List instances = getJdbcTemplate().query(getQuery(FIND_JOBS), parameters, rowMapper);
|
||||
|
||||
if (instances.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
Assert.state(instances.size() == 1);
|
||||
return (JobInstance) instances.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobInstance} instances.
|
||||
*
|
||||
* @param jobIncrementer the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) {
|
||||
this.jobIncrementer = jobIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobIncrementer);
|
||||
}
|
||||
|
||||
private static class ParameterType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private ParameterType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final ParameterType STRING = new ParameterType("STRING");
|
||||
|
||||
public static final ParameterType DATE = new ParameterType("DATE");
|
||||
|
||||
public static final ParameterType LONG = new ParameterType("LONG");
|
||||
|
||||
public static final ParameterType DOUBLE = new ParameterType("DOUBLE");
|
||||
|
||||
private static final ParameterType[] VALUES = { STRING, DATE, LONG, DOUBLE };
|
||||
|
||||
public static ParameterType getType(String typeAsString) {
|
||||
|
||||
for (int i = 0; i < VALUES.length; i++) {
|
||||
if (VALUES[i].toString().equals(typeAsString)) {
|
||||
return (ParameterType) VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,425 +1,425 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.SerializationUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.jdbc.core.PreparedStatementCallback;
|
||||
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link StepExecutionDao}.<br/>
|
||||
*
|
||||
* Allows customization of the tables names used by Spring Batch for step meta
|
||||
* data via a prefix property.<br/>
|
||||
*
|
||||
* Uses sequences or tables (via Spring's {@link DataFieldMaxValueIncrementer}
|
||||
* abstraction) to create all primary keys before inserting a new row. All
|
||||
* objects are checked to ensure all fields to be stored are not null. If any
|
||||
* are found to be null, an IllegalArgumentException will be thrown. This could
|
||||
* be left to JdbcTemplate, however, the exception will be fairly vague, and
|
||||
* fails to highlight which field caused the exception.<br/>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*
|
||||
* @see StepExecutionDao
|
||||
*/
|
||||
public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implements StepExecutionDao, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcStepExecutionDao.class);
|
||||
|
||||
private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT TYPE_CD, KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL "
|
||||
+ "from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID = ?";
|
||||
|
||||
private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT into %PREFIX%STEP_EXECUTION_CONTEXT(STEP_EXECUTION_ID, TYPE_CD,"
|
||||
+ " KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL) values(?,?,?,?,?,?,?)";
|
||||
|
||||
private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) "
|
||||
+ "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT set "
|
||||
+ "TYPE_CD = ?, STRING_VAL = ?, DOUBLE_VAL = ?, LONG_VAL = ?, OBJECT_VAL = ? where STEP_EXECUTION_ID = ? and KEY_NAME = ?";
|
||||
|
||||
private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, CONTINUABLE = ? , EXIT_CODE = ?, "
|
||||
+ "EXIT_MESSAGE = ?, VERSION = ? where STEP_EXECUTION_ID = ? and VERSION = ?";
|
||||
|
||||
private static final String GET_STEP_EXECUTION = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT,"
|
||||
+ " TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_NAME = ? and JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE STEP_EXECUTION_ID=?";
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private LobHandler lobHandler = new DefaultLobHandler();
|
||||
|
||||
private DataFieldMaxValueIncrementer stepExecutionIncrementer;
|
||||
|
||||
public ExecutionContext findExecutionContext(final StepExecution stepExecution) {
|
||||
|
||||
final Long executionId = stepExecution.getId();
|
||||
Assert.notNull(executionId, "ExecutionId must not be null.");
|
||||
|
||||
final ExecutionContext executionContext = new ExecutionContext();
|
||||
|
||||
RowCallbackHandler callback = new RowCallbackHandler() {
|
||||
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
|
||||
String typeCd = rs.getString("TYPE_CD");
|
||||
AttributeType type = AttributeType.getType(typeCd);
|
||||
String key = rs.getString("KEY_NAME");
|
||||
if (type == AttributeType.STRING) {
|
||||
executionContext.putString(key, rs.getString("STRING_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
executionContext.putLong(key, rs.getLong("LONG_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
executionContext.putDouble(key, rs.getDouble("DOUBLE_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.OBJECT) {
|
||||
executionContext.put(key, rs.getObject("OBJECT_VAL"));
|
||||
}
|
||||
else {
|
||||
throw new InfrastructureException("Invalid type found: [" + typeCd + "] for execution id: ["
|
||||
+ executionId + "]");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT), new Object[] { executionId }, callback);
|
||||
|
||||
return executionContext;
|
||||
}
|
||||
|
||||
private void insertExecutionAttribute(final Long executionId, final String key, final Object value,
|
||||
final AttributeType type) {
|
||||
PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
|
||||
|
||||
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
|
||||
DataAccessException {
|
||||
|
||||
ps.setLong(1, executionId.longValue());
|
||||
ps.setString(3, key);
|
||||
if (type == AttributeType.STRING) {
|
||||
ps.setString(2, AttributeType.STRING.toString());
|
||||
ps.setString(4, value.toString());
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
ps.setString(2, AttributeType.DOUBLE.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, ((Double) value).doubleValue());
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
ps.setString(2, AttributeType.LONG.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, ((Long) value).longValue());
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else {
|
||||
ps.setString(2, AttributeType.OBJECT.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, SerializationUtils.serialize((Serializable) value));
|
||||
}
|
||||
}
|
||||
};
|
||||
getJdbcTemplate().execute(getQuery(INSERT_STEP_EXECUTION_CONTEXT), callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a StepExecution. A unique id will be generated by the
|
||||
* stepExecutionIncrementor, and then set in the StepExecution. All values
|
||||
* will then be stored via an INSERT statement.
|
||||
*
|
||||
* @see StepDao#saveStepExecution(StepExecution)
|
||||
*/
|
||||
public void saveStepExecution(StepExecution stepExecution) {
|
||||
|
||||
validateStepExecution(stepExecution);
|
||||
|
||||
stepExecution.setId(new Long(stepExecutionIncrementer.nextLongValue()));
|
||||
stepExecution.incrementVersion(); // should be 0 now
|
||||
Object[] parameters = new Object[] { stepExecution.getId(), stepExecution.getVersion(),
|
||||
stepExecution.getStepName(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(),
|
||||
stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(),
|
||||
stepExecution.getTaskCount(), stepExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
stepExecution.getExitStatus().getExitCode(), stepExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(
|
||||
getQuery(SAVE_STEP_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP,
|
||||
Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.CHAR, Types.VARCHAR,
|
||||
Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot
|
||||
* be null. EndTime can be null for an unfinished job.
|
||||
*
|
||||
* @param jobExecution
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateStepExecution(StepExecution stepExecution) {
|
||||
Assert.notNull(stepExecution);
|
||||
Assert.notNull(stepExecution.getStepName(), "StepExecution step name cannot be null.");
|
||||
Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null.");
|
||||
Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Save or update execution attributes. A lob creator must be used, since
|
||||
* any attributes that don't match a provided type must be serialized into a
|
||||
* blob.
|
||||
*
|
||||
* @see {@link LobCreator}
|
||||
*/
|
||||
public void saveOrUpdateExecutionContext(final StepExecution stepExecution) {
|
||||
|
||||
Long executionId = stepExecution.getId();
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
Assert.notNull(executionId, "ExecutionId must not be null.");
|
||||
Assert.notNull(executionContext, "The ExecutionContext must not be null.");
|
||||
|
||||
for (Iterator it = executionContext.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
final String key = entry.getKey().toString();
|
||||
final Object value = entry.getValue();
|
||||
|
||||
if (value instanceof String) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.STRING);
|
||||
}
|
||||
else if (value instanceof Double) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.DOUBLE);
|
||||
}
|
||||
else if (value instanceof Long) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.LONG);
|
||||
}
|
||||
else {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateExecutionAttribute(final Long executionId, final String key, final Object value,
|
||||
final AttributeType type) {
|
||||
|
||||
PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
|
||||
|
||||
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
|
||||
DataAccessException {
|
||||
|
||||
ps.setLong(6, executionId.longValue());
|
||||
ps.setString(7, key);
|
||||
if (type == AttributeType.STRING) {
|
||||
ps.setString(1, AttributeType.STRING.toString());
|
||||
ps.setString(2, value.toString());
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
ps.setString(1, AttributeType.DOUBLE.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, ((Double) value).doubleValue());
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
ps.setString(1, AttributeType.LONG.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, ((Long) value).longValue());
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else {
|
||||
ps.setString(1, AttributeType.OBJECT.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, SerializationUtils.serialize((Serializable) value));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// LobCreating callbacks always return the affect row count for SQL DML
|
||||
// statements, if less than 1 row
|
||||
// is affected, then this row is new and should be inserted.
|
||||
Integer affectedRows = (Integer) getJdbcTemplate().execute(getQuery(UPDATE_STEP_EXECUTION_CONTEXT), callback);
|
||||
if (affectedRows.intValue() < 1) {
|
||||
insertExecutionAttribute(executionId, key, value, type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.execution.repository.dao.StepExecutionDao#updateStepExecution(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void updateStepExecution(StepExecution stepExecution) {
|
||||
|
||||
validateStepExecution(stepExecution);
|
||||
Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved"
|
||||
+ " before it can be updated.");
|
||||
|
||||
// Do not check for existence of step execution considering
|
||||
// it is saved at every commit point.
|
||||
|
||||
String exitDescription = stepExecution.getExitStatus().getExitDescription();
|
||||
if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger.debug("Truncating long message before update of StepExecution: " + stepExecution);
|
||||
}
|
||||
|
||||
// Attempt to prevent concurrent modification errors by blocking here if
|
||||
// someone is already trying to do it.
|
||||
synchronized (stepExecution) {
|
||||
|
||||
Integer version = new Integer(stepExecution.getVersion().intValue() + 1);
|
||||
Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(),
|
||||
stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(),
|
||||
stepExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getId(),
|
||||
stepExecution.getVersion() };
|
||||
int count = getJdbcTemplate().update(
|
||||
getQuery(UPDATE_STEP_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER,
|
||||
Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER });
|
||||
|
||||
// Avoid concurrent modifications...
|
||||
if (count == 0) {
|
||||
int curentVersion = getJdbcTemplate().queryForInt(
|
||||
getQuery(CURRENT_VERSION_STEP_EXECUTION),
|
||||
new Object[] { stepExecution.getId() });
|
||||
throw new OptimisticLockingFailureException("Attempt to update step execution id="
|
||||
+ stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is "+curentVersion);
|
||||
}
|
||||
|
||||
stepExecution.incrementVersion();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class StepExecutionRowMapper implements RowMapper {
|
||||
|
||||
private final JobExecution jobExecution;
|
||||
|
||||
private final Step step;
|
||||
|
||||
public StepExecutionRowMapper(JobExecution jobExecution, Step step) {
|
||||
this.jobExecution = jobExecution;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
StepExecution stepExecution = new StepExecution(step, jobExecution, new Long(rs.getLong(1)));
|
||||
stepExecution.setStartTime(rs.getTimestamp(3));
|
||||
stepExecution.setEndTime(rs.getTimestamp(4));
|
||||
stepExecution.setStatus(BatchStatus.getStatus(rs.getString(5)));
|
||||
stepExecution.setCommitCount(rs.getInt(6));
|
||||
stepExecution.setTaskCount(rs.getInt(7));
|
||||
stepExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(8)), rs.getString(9), rs.getString(10)));
|
||||
stepExecution.setExecutionContext(findExecutionContext(stepExecution));
|
||||
return stepExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setLobHandler(LobHandler lobHandler) {
|
||||
this.lobHandler = lobHandler;
|
||||
}
|
||||
|
||||
public void setStepExecutionIncrementer(DataFieldMaxValueIncrementer stepExecutionIncrementer) {
|
||||
this.stepExecutionIncrementer = stepExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer cannot be null.");
|
||||
}
|
||||
|
||||
public static class AttributeType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private AttributeType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final AttributeType STRING = new AttributeType("STRING");
|
||||
|
||||
public static final AttributeType LONG = new AttributeType("LONG");
|
||||
|
||||
public static final AttributeType OBJECT = new AttributeType("OBJECT");
|
||||
|
||||
public static final AttributeType DOUBLE = new AttributeType("DOUBLE");
|
||||
|
||||
private static final AttributeType[] VALUES = { STRING, OBJECT, LONG, DOUBLE };
|
||||
|
||||
public static AttributeType getType(String typeAsString) {
|
||||
|
||||
for (int i = 0; i < VALUES.length; i++) {
|
||||
if (VALUES[i].toString().equals(typeAsString)) {
|
||||
return (AttributeType) VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public StepExecution getStepExecution(JobExecution jobExecution, Step step) {
|
||||
List executions = getJdbcTemplate().query(getQuery(GET_STEP_EXECUTION),
|
||||
new Object[] { step.getName(), jobExecution.getId() }, new StepExecutionRowMapper(jobExecution, step));
|
||||
|
||||
Assert.state(executions.size() <= 1,
|
||||
"There can be at most one step execution with given name for single job execution");
|
||||
if (executions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (StepExecution) executions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.SerializationUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.jdbc.core.PreparedStatementCallback;
|
||||
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
import org.springframework.jdbc.support.lob.LobCreator;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link StepExecutionDao}.<br/>
|
||||
*
|
||||
* Allows customization of the tables names used by Spring Batch for step meta
|
||||
* data via a prefix property.<br/>
|
||||
*
|
||||
* Uses sequences or tables (via Spring's {@link DataFieldMaxValueIncrementer}
|
||||
* abstraction) to create all primary keys before inserting a new row. All
|
||||
* objects are checked to ensure all fields to be stored are not null. If any
|
||||
* are found to be null, an IllegalArgumentException will be thrown. This could
|
||||
* be left to JdbcTemplate, however, the exception will be fairly vague, and
|
||||
* fails to highlight which field caused the exception.<br/>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*
|
||||
* @see StepExecutionDao
|
||||
*/
|
||||
public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implements StepExecutionDao, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcStepExecutionDao.class);
|
||||
|
||||
private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT TYPE_CD, KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL "
|
||||
+ "from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID = ?";
|
||||
|
||||
private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT into %PREFIX%STEP_EXECUTION_CONTEXT(STEP_EXECUTION_ID, TYPE_CD,"
|
||||
+ " KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL) values(?,?,?,?,?,?,?)";
|
||||
|
||||
private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) "
|
||||
+ "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT set "
|
||||
+ "TYPE_CD = ?, STRING_VAL = ?, DOUBLE_VAL = ?, LONG_VAL = ?, OBJECT_VAL = ? where STEP_EXECUTION_ID = ? and KEY_NAME = ?";
|
||||
|
||||
private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, CONTINUABLE = ? , EXIT_CODE = ?, "
|
||||
+ "EXIT_MESSAGE = ?, VERSION = ? where STEP_EXECUTION_ID = ? and VERSION = ?";
|
||||
|
||||
private static final String GET_STEP_EXECUTION = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT,"
|
||||
+ " TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_NAME = ? and JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE STEP_EXECUTION_ID=?";
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private LobHandler lobHandler = new DefaultLobHandler();
|
||||
|
||||
private DataFieldMaxValueIncrementer stepExecutionIncrementer;
|
||||
|
||||
public ExecutionContext findExecutionContext(final StepExecution stepExecution) {
|
||||
|
||||
final Long executionId = stepExecution.getId();
|
||||
Assert.notNull(executionId, "ExecutionId must not be null.");
|
||||
|
||||
final ExecutionContext executionContext = new ExecutionContext();
|
||||
|
||||
RowCallbackHandler callback = new RowCallbackHandler() {
|
||||
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
|
||||
String typeCd = rs.getString("TYPE_CD");
|
||||
AttributeType type = AttributeType.getType(typeCd);
|
||||
String key = rs.getString("KEY_NAME");
|
||||
if (type == AttributeType.STRING) {
|
||||
executionContext.putString(key, rs.getString("STRING_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
executionContext.putLong(key, rs.getLong("LONG_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
executionContext.putDouble(key, rs.getDouble("DOUBLE_VAL"));
|
||||
}
|
||||
else if (type == AttributeType.OBJECT) {
|
||||
executionContext.put(key, rs.getObject("OBJECT_VAL"));
|
||||
}
|
||||
else {
|
||||
throw new InfrastructureException("Invalid type found: [" + typeCd + "] for execution id: ["
|
||||
+ executionId + "]");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT), new Object[] { executionId }, callback);
|
||||
|
||||
return executionContext;
|
||||
}
|
||||
|
||||
private void insertExecutionAttribute(final Long executionId, final String key, final Object value,
|
||||
final AttributeType type) {
|
||||
PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
|
||||
|
||||
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
|
||||
DataAccessException {
|
||||
|
||||
ps.setLong(1, executionId.longValue());
|
||||
ps.setString(3, key);
|
||||
if (type == AttributeType.STRING) {
|
||||
ps.setString(2, AttributeType.STRING.toString());
|
||||
ps.setString(4, value.toString());
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
ps.setString(2, AttributeType.DOUBLE.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, ((Double) value).doubleValue());
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
ps.setString(2, AttributeType.LONG.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, ((Long) value).longValue());
|
||||
lobCreator.setBlobAsBytes(ps, 7, null);
|
||||
}
|
||||
else {
|
||||
ps.setString(2, AttributeType.OBJECT.toString());
|
||||
ps.setString(4, null);
|
||||
ps.setDouble(5, 0.0);
|
||||
ps.setLong(6, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 7, SerializationUtils.serialize((Serializable) value));
|
||||
}
|
||||
}
|
||||
};
|
||||
getJdbcTemplate().execute(getQuery(INSERT_STEP_EXECUTION_CONTEXT), callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a StepExecution. A unique id will be generated by the
|
||||
* stepExecutionIncrementor, and then set in the StepExecution. All values
|
||||
* will then be stored via an INSERT statement.
|
||||
*
|
||||
* @see StepDao#saveStepExecution(StepExecution)
|
||||
*/
|
||||
public void saveStepExecution(StepExecution stepExecution) {
|
||||
|
||||
validateStepExecution(stepExecution);
|
||||
|
||||
stepExecution.setId(new Long(stepExecutionIncrementer.nextLongValue()));
|
||||
stepExecution.incrementVersion(); // should be 0 now
|
||||
Object[] parameters = new Object[] { stepExecution.getId(), stepExecution.getVersion(),
|
||||
stepExecution.getStepName(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(),
|
||||
stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(),
|
||||
stepExecution.getTaskCount(), stepExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
stepExecution.getExitStatus().getExitCode(), stepExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(
|
||||
getQuery(SAVE_STEP_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP,
|
||||
Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.CHAR, Types.VARCHAR,
|
||||
Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot
|
||||
* be null. EndTime can be null for an unfinished job.
|
||||
*
|
||||
* @param jobExecution
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateStepExecution(StepExecution stepExecution) {
|
||||
Assert.notNull(stepExecution);
|
||||
Assert.notNull(stepExecution.getStepName(), "StepExecution step name cannot be null.");
|
||||
Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null.");
|
||||
Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Save or update execution attributes. A lob creator must be used, since
|
||||
* any attributes that don't match a provided type must be serialized into a
|
||||
* blob.
|
||||
*
|
||||
* @see {@link LobCreator}
|
||||
*/
|
||||
public void saveOrUpdateExecutionContext(final StepExecution stepExecution) {
|
||||
|
||||
Long executionId = stepExecution.getId();
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
Assert.notNull(executionId, "ExecutionId must not be null.");
|
||||
Assert.notNull(executionContext, "The ExecutionContext must not be null.");
|
||||
|
||||
for (Iterator it = executionContext.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
final String key = entry.getKey().toString();
|
||||
final Object value = entry.getValue();
|
||||
|
||||
if (value instanceof String) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.STRING);
|
||||
}
|
||||
else if (value instanceof Double) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.DOUBLE);
|
||||
}
|
||||
else if (value instanceof Long) {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.LONG);
|
||||
}
|
||||
else {
|
||||
updateExecutionAttribute(executionId, key, value, AttributeType.OBJECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateExecutionAttribute(final Long executionId, final String key, final Object value,
|
||||
final AttributeType type) {
|
||||
|
||||
PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
|
||||
|
||||
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
|
||||
DataAccessException {
|
||||
|
||||
ps.setLong(6, executionId.longValue());
|
||||
ps.setString(7, key);
|
||||
if (type == AttributeType.STRING) {
|
||||
ps.setString(1, AttributeType.STRING.toString());
|
||||
ps.setString(2, value.toString());
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else if (type == AttributeType.DOUBLE) {
|
||||
ps.setString(1, AttributeType.DOUBLE.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, ((Double) value).doubleValue());
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else if (type == AttributeType.LONG) {
|
||||
ps.setString(1, AttributeType.LONG.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, ((Long) value).longValue());
|
||||
lobCreator.setBlobAsBytes(ps, 5, null);
|
||||
}
|
||||
else {
|
||||
ps.setString(1, AttributeType.OBJECT.toString());
|
||||
ps.setString(2, null);
|
||||
ps.setDouble(3, 0.0);
|
||||
ps.setLong(4, 0);
|
||||
lobCreator.setBlobAsBytes(ps, 5, SerializationUtils.serialize((Serializable) value));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// LobCreating callbacks always return the affect row count for SQL DML
|
||||
// statements, if less than 1 row
|
||||
// is affected, then this row is new and should be inserted.
|
||||
Integer affectedRows = (Integer) getJdbcTemplate().execute(getQuery(UPDATE_STEP_EXECUTION_CONTEXT), callback);
|
||||
if (affectedRows.intValue() < 1) {
|
||||
insertExecutionAttribute(executionId, key, value, type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.execution.repository.dao.StepExecutionDao#updateStepExecution(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void updateStepExecution(StepExecution stepExecution) {
|
||||
|
||||
validateStepExecution(stepExecution);
|
||||
Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved"
|
||||
+ " before it can be updated.");
|
||||
|
||||
// Do not check for existence of step execution considering
|
||||
// it is saved at every commit point.
|
||||
|
||||
String exitDescription = stepExecution.getExitStatus().getExitDescription();
|
||||
if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger.debug("Truncating long message before update of StepExecution: " + stepExecution);
|
||||
}
|
||||
|
||||
// Attempt to prevent concurrent modification errors by blocking here if
|
||||
// someone is already trying to do it.
|
||||
synchronized (stepExecution) {
|
||||
|
||||
Integer version = new Integer(stepExecution.getVersion().intValue() + 1);
|
||||
Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(),
|
||||
stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(),
|
||||
stepExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getId(),
|
||||
stepExecution.getVersion() };
|
||||
int count = getJdbcTemplate().update(
|
||||
getQuery(UPDATE_STEP_EXECUTION),
|
||||
parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER,
|
||||
Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER });
|
||||
|
||||
// Avoid concurrent modifications...
|
||||
if (count == 0) {
|
||||
int curentVersion = getJdbcTemplate().queryForInt(
|
||||
getQuery(CURRENT_VERSION_STEP_EXECUTION),
|
||||
new Object[] { stepExecution.getId() });
|
||||
throw new OptimisticLockingFailureException("Attempt to update step execution id="
|
||||
+ stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is "+curentVersion);
|
||||
}
|
||||
|
||||
stepExecution.incrementVersion();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class StepExecutionRowMapper implements RowMapper {
|
||||
|
||||
private final JobExecution jobExecution;
|
||||
|
||||
private final Step step;
|
||||
|
||||
public StepExecutionRowMapper(JobExecution jobExecution, Step step) {
|
||||
this.jobExecution = jobExecution;
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
StepExecution stepExecution = new StepExecution(step, jobExecution, new Long(rs.getLong(1)));
|
||||
stepExecution.setStartTime(rs.getTimestamp(3));
|
||||
stepExecution.setEndTime(rs.getTimestamp(4));
|
||||
stepExecution.setStatus(BatchStatus.getStatus(rs.getString(5)));
|
||||
stepExecution.setCommitCount(rs.getInt(6));
|
||||
stepExecution.setTaskCount(rs.getInt(7));
|
||||
stepExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(8)), rs.getString(9), rs.getString(10)));
|
||||
stepExecution.setExecutionContext(findExecutionContext(stepExecution));
|
||||
return stepExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setLobHandler(LobHandler lobHandler) {
|
||||
this.lobHandler = lobHandler;
|
||||
}
|
||||
|
||||
public void setStepExecutionIncrementer(DataFieldMaxValueIncrementer stepExecutionIncrementer) {
|
||||
this.stepExecutionIncrementer = stepExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer cannot be null.");
|
||||
}
|
||||
|
||||
public static class AttributeType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private AttributeType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final AttributeType STRING = new AttributeType("STRING");
|
||||
|
||||
public static final AttributeType LONG = new AttributeType("LONG");
|
||||
|
||||
public static final AttributeType OBJECT = new AttributeType("OBJECT");
|
||||
|
||||
public static final AttributeType DOUBLE = new AttributeType("DOUBLE");
|
||||
|
||||
private static final AttributeType[] VALUES = { STRING, OBJECT, LONG, DOUBLE };
|
||||
|
||||
public static AttributeType getType(String typeAsString) {
|
||||
|
||||
for (int i = 0; i < VALUES.length; i++) {
|
||||
if (VALUES[i].toString().equals(typeAsString)) {
|
||||
return (AttributeType) VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public StepExecution getStepExecution(JobExecution jobExecution, Step step) {
|
||||
List executions = getJdbcTemplate().query(getQuery(GET_STEP_EXECUTION),
|
||||
new Object[] { step.getName(), jobExecution.getId() }, new StepExecutionRowMapper(jobExecution, step));
|
||||
|
||||
Assert.state(executions.size() <= 1,
|
||||
"There can be at most one step execution with given name for single job execution");
|
||||
if (executions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (StepExecution) executions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
|
||||
/**
|
||||
* Data Access Object for job executions.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public interface JobExecutionDao {
|
||||
|
||||
/**
|
||||
* Save a new JobExecution.
|
||||
*
|
||||
* Preconditions: jobInstance the jobExecution belongs to must have a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void saveJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Update and existing JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have an Id (which can be obtained by the
|
||||
* save method) and a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void updateJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Return the number of JobExecutions for the given JobInstance
|
||||
*
|
||||
* Preconditions: jobInstance must have an id.
|
||||
*/
|
||||
int getJobExecutionCount(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* Return list of JobExecutions for given JobInstance.
|
||||
*
|
||||
* @param jobInstance
|
||||
* @return list of jobExecutions.
|
||||
*/
|
||||
List findJobExecutions(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* @return last JobExecution for given JobInstance.
|
||||
*/
|
||||
JobExecution getLastJobExecution(JobInstance jobInstance);
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
|
||||
/**
|
||||
* Data Access Object for job executions.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public interface JobExecutionDao {
|
||||
|
||||
/**
|
||||
* Save a new JobExecution.
|
||||
*
|
||||
* Preconditions: jobInstance the jobExecution belongs to must have a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void saveJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Update and existing JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have an Id (which can be obtained by the
|
||||
* save method) and a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void updateJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Return the number of JobExecutions for the given JobInstance
|
||||
*
|
||||
* Preconditions: jobInstance must have an id.
|
||||
*/
|
||||
int getJobExecutionCount(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* Return list of JobExecutions for given JobInstance.
|
||||
*
|
||||
* @param jobInstance
|
||||
* @return list of jobExecutions.
|
||||
*/
|
||||
List findJobExecutions(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* @return last JobExecution for given JobInstance.
|
||||
*/
|
||||
JobExecution getLastJobExecution(JobInstance jobInstance);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
|
||||
/**
|
||||
* Data Access Object for job instances.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*
|
||||
*/
|
||||
public interface JobInstanceDao {
|
||||
|
||||
/**
|
||||
* Create a JobInstance with given name and parameters.
|
||||
*
|
||||
* PreConditions: JobInstance for given name and parameters must not already exist
|
||||
*
|
||||
* PostConditions: A valid job instancewill be returned which has been persisted and
|
||||
* contains an unique Id.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return JobInstance
|
||||
*/
|
||||
JobInstance createJobInstance(Job job, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Find all job instances that match the given name and parameters. If no
|
||||
* matching job instances are found, then a list of size 0 will be
|
||||
* returned.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return List of {@link JobInstance} objects matching
|
||||
* {@link JobIdentifier}
|
||||
*/
|
||||
JobInstance getJobInstance(Job job, JobParameters jobParameters);
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
|
||||
/**
|
||||
* Data Access Object for job instances.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*
|
||||
*/
|
||||
public interface JobInstanceDao {
|
||||
|
||||
/**
|
||||
* Create a JobInstance with given name and parameters.
|
||||
*
|
||||
* PreConditions: JobInstance for given name and parameters must not already exist
|
||||
*
|
||||
* PostConditions: A valid job instancewill be returned which has been persisted and
|
||||
* contains an unique Id.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return JobInstance
|
||||
*/
|
||||
JobInstance createJobInstance(Job job, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Find all job instances that match the given name and parameters. If no
|
||||
* matching job instances are found, then a list of size 0 will be
|
||||
* returned.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return List of {@link JobInstance} objects matching
|
||||
* {@link JobIdentifier}
|
||||
*/
|
||||
JobInstance getJobInstance(Job job, JobParameters jobParameters);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
|
||||
|
||||
/**
|
||||
* In-memory implementation of {@link JobExecutionDao}.
|
||||
*
|
||||
*/
|
||||
public class MapJobExecutionDao implements JobExecutionDao {
|
||||
|
||||
private static Map executionsByJobInstanceId = TransactionAwareProxyFactory.createTransactionalMap();
|
||||
|
||||
private static long currentId;
|
||||
|
||||
public static void clear() {
|
||||
executionsByJobInstanceId.clear();
|
||||
}
|
||||
|
||||
public int getJobExecutionCount(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return 0;
|
||||
}
|
||||
return executions.size();
|
||||
}
|
||||
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobExecution.getJobId());
|
||||
if (executions == null) {
|
||||
executions = TransactionAwareProxyFactory.createTransactionalSet();
|
||||
executionsByJobInstanceId.put(jobExecution.getJobId(), executions);
|
||||
}
|
||||
executions.add(jobExecution);
|
||||
jobExecution.setId(new Long(currentId++));
|
||||
}
|
||||
|
||||
public List findJobExecutions(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return new ArrayList();
|
||||
}
|
||||
else {
|
||||
return new ArrayList(executions);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public JobExecution getLastJobExecution(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return null;
|
||||
}
|
||||
JobExecution lastExec = null;
|
||||
for (Iterator iterator = executions.iterator(); iterator.hasNext();) {
|
||||
JobExecution exec = (JobExecution) iterator.next();
|
||||
if (lastExec == null) {
|
||||
lastExec = exec;
|
||||
}
|
||||
if (lastExec.getStartTime().getTime() < exec.getStartTime().getTime()) {
|
||||
lastExec = exec;
|
||||
}
|
||||
}
|
||||
return lastExec;
|
||||
}
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
|
||||
|
||||
/**
|
||||
* In-memory implementation of {@link JobExecutionDao}.
|
||||
*
|
||||
*/
|
||||
public class MapJobExecutionDao implements JobExecutionDao {
|
||||
|
||||
private static Map executionsByJobInstanceId = TransactionAwareProxyFactory.createTransactionalMap();
|
||||
|
||||
private static long currentId;
|
||||
|
||||
public static void clear() {
|
||||
executionsByJobInstanceId.clear();
|
||||
}
|
||||
|
||||
public int getJobExecutionCount(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return 0;
|
||||
}
|
||||
return executions.size();
|
||||
}
|
||||
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobExecution.getJobId());
|
||||
if (executions == null) {
|
||||
executions = TransactionAwareProxyFactory.createTransactionalSet();
|
||||
executionsByJobInstanceId.put(jobExecution.getJobId(), executions);
|
||||
}
|
||||
executions.add(jobExecution);
|
||||
jobExecution.setId(new Long(currentId++));
|
||||
}
|
||||
|
||||
public List findJobExecutions(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return new ArrayList();
|
||||
}
|
||||
else {
|
||||
return new ArrayList(executions);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public JobExecution getLastJobExecution(JobInstance jobInstance) {
|
||||
Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId());
|
||||
if (executions == null) {
|
||||
return null;
|
||||
}
|
||||
JobExecution lastExec = null;
|
||||
for (Iterator iterator = executions.iterator(); iterator.hasNext();) {
|
||||
JobExecution exec = (JobExecution) iterator.next();
|
||||
if (lastExec == null) {
|
||||
lastExec = exec;
|
||||
}
|
||||
if (lastExec.getStartTime().getTime() < exec.getStartTime().getTime()) {
|
||||
lastExec = exec;
|
||||
}
|
||||
}
|
||||
return lastExec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class MapJobInstanceDao implements JobInstanceDao {
|
||||
|
||||
private static Collection jobInstances = TransactionAwareProxyFactory.createTransactionalList();
|
||||
|
||||
private long currentId = 0;
|
||||
|
||||
public static void clear() {
|
||||
jobInstances.clear();
|
||||
}
|
||||
|
||||
public JobInstance createJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist");
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(currentId++), jobParameters, job);
|
||||
jobInstances.add(jobInstance);
|
||||
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
public JobInstance getJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
for (Iterator iterator = jobInstances.iterator(); iterator.hasNext();) {
|
||||
JobInstance instance = (JobInstance) iterator.next();
|
||||
if (instance.getJobName().equals(job.getName()) && instance.getJobParameters().equals(jobParameters)) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class MapJobInstanceDao implements JobInstanceDao {
|
||||
|
||||
private static Collection jobInstances = TransactionAwareProxyFactory.createTransactionalList();
|
||||
|
||||
private long currentId = 0;
|
||||
|
||||
public static void clear() {
|
||||
jobInstances.clear();
|
||||
}
|
||||
|
||||
public JobInstance createJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist");
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(currentId++), jobParameters, job);
|
||||
jobInstances.add(jobInstance);
|
||||
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
public JobInstance getJobInstance(Job job, JobParameters jobParameters) {
|
||||
|
||||
for (Iterator iterator = jobInstances.iterator(); iterator.hasNext();) {
|
||||
JobInstance instance = (JobInstance) iterator.next();
|
||||
if (instance.getJobName().equals(job.getName()) && instance.getJobParameters().equals(jobParameters)) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
public interface StepExecutionDao {
|
||||
|
||||
/**
|
||||
* Save the given StepExecution.
|
||||
*
|
||||
* Preconditions: Id must be null.
|
||||
*
|
||||
* Postconditions: Id will be set to a unique Long.
|
||||
*
|
||||
* @param stepExecution
|
||||
*/
|
||||
void saveStepExecution(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Update the given StepExecution
|
||||
*
|
||||
* Preconditions: Id must not be null.
|
||||
*
|
||||
* @param stepExecution
|
||||
*/
|
||||
void updateStepExecution(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Find all {@link ExecutionContext} for the given {@link StepExecution}.
|
||||
*
|
||||
* @throws IllegalArgumentException if the id is null.
|
||||
*/
|
||||
ExecutionContext findExecutionContext(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Save the {@link ExecutionContext} of the given {@link StepExecution}.
|
||||
*
|
||||
* @param stepExecution the {@link StepExecution} containing the
|
||||
* {@link ExecutionContext} to be saved.
|
||||
* @throws IllegalArgumentException if the attributes are null.
|
||||
*/
|
||||
void saveOrUpdateExecutionContext(StepExecution stepExecution);
|
||||
|
||||
StepExecution getStepExecution(JobExecution jobExecution, Step step);
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
public interface StepExecutionDao {
|
||||
|
||||
/**
|
||||
* Save the given StepExecution.
|
||||
*
|
||||
* Preconditions: Id must be null.
|
||||
*
|
||||
* Postconditions: Id will be set to a unique Long.
|
||||
*
|
||||
* @param stepExecution
|
||||
*/
|
||||
void saveStepExecution(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Update the given StepExecution
|
||||
*
|
||||
* Preconditions: Id must not be null.
|
||||
*
|
||||
* @param stepExecution
|
||||
*/
|
||||
void updateStepExecution(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Find all {@link ExecutionContext} for the given {@link StepExecution}.
|
||||
*
|
||||
* @throws IllegalArgumentException if the id is null.
|
||||
*/
|
||||
ExecutionContext findExecutionContext(StepExecution stepExecution);
|
||||
|
||||
/**
|
||||
* Save the {@link ExecutionContext} of the given {@link StepExecution}.
|
||||
*
|
||||
* @param stepExecution the {@link StepExecution} containing the
|
||||
* {@link ExecutionContext} to be saved.
|
||||
* @throws IllegalArgumentException if the attributes are null.
|
||||
*/
|
||||
void saveOrUpdateExecutionContext(StepExecution stepExecution);
|
||||
|
||||
StepExecution getStepExecution(JobExecution jobExecution, Step step);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,94 +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.step;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
|
||||
/**
|
||||
* A {@link Step} implementation that provides common behaviour to subclasses.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public abstract class AbstractStep implements Step {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
protected boolean allowStartIfComplete;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractStep() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property. Always overrides the default value if this object
|
||||
* is a Spring bean.
|
||||
*
|
||||
* @see #setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getStartLimit() {
|
||||
return this.startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
public boolean isAllowStartIfComplete() {
|
||||
return this.allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor for setting only the name property.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public AbstractStep(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException;
|
||||
/*
|
||||
* 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 org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
|
||||
/**
|
||||
* A {@link Step} implementation that provides common behaviour to subclasses.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Ben Hale
|
||||
*/
|
||||
public abstract class AbstractStep implements Step {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
protected boolean allowStartIfComplete;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractStep() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property. Always overrides the default value if this object
|
||||
* is a Spring bean.
|
||||
*
|
||||
* @see #setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getStartLimit() {
|
||||
return this.startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
public boolean isAllowStartIfComplete() {
|
||||
return this.allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor for setting only the name property.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public AbstractStep(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException;
|
||||
}
|
||||
@@ -1,78 +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.step;
|
||||
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
import org.springframework.batch.item.exception.FlushFailedException;
|
||||
import org.springframework.batch.item.exception.MarkFailedException;
|
||||
import org.springframework.batch.item.exception.ResetFailedException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* Strategy for processing a single item in an item-oriented step. Extends
|
||||
* {@link ItemReader} and {@link ItemWriter} because part of the contract of the
|
||||
* processor is that it should delegate calls to those interfaces.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemHandler {
|
||||
|
||||
/**
|
||||
* Given the current context in the form of a step contribution, do whatever
|
||||
* is necessary to process this unit inside a chunk. Implementations obtain
|
||||
* the item and return {@link ExitStatus#FINISHED} if it is null. If it is
|
||||
* not null process the item and return {@link ExitStatus#CONTINUABLE}. On
|
||||
* failure throws an exception.
|
||||
*
|
||||
* @param contribution the current step context
|
||||
* @return an {@link ExitStatus} indicating whether processing is
|
||||
* continuable.
|
||||
*/
|
||||
ExitStatus handle(StepContribution contribution) throws Exception;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemReader}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemReader#mark()
|
||||
*/
|
||||
void mark() throws MarkFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemReader}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemReader#reset()
|
||||
*/
|
||||
void reset() throws ResetFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#flush()
|
||||
*/
|
||||
public void flush() throws FlushFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#clear()
|
||||
*/
|
||||
public void clear() throws ClearFailedException;
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
import org.springframework.batch.item.exception.FlushFailedException;
|
||||
import org.springframework.batch.item.exception.MarkFailedException;
|
||||
import org.springframework.batch.item.exception.ResetFailedException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* Strategy for processing a single item in an item-oriented step. Extends
|
||||
* {@link ItemReader} and {@link ItemWriter} because part of the contract of the
|
||||
* processor is that it should delegate calls to those interfaces.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ItemHandler {
|
||||
|
||||
/**
|
||||
* Given the current context in the form of a step contribution, do whatever
|
||||
* is necessary to process this unit inside a chunk. Implementations obtain
|
||||
* the item and return {@link ExitStatus#FINISHED} if it is null. If it is
|
||||
* not null process the item and return {@link ExitStatus#CONTINUABLE}. On
|
||||
* failure throws an exception.
|
||||
*
|
||||
* @param contribution the current step context
|
||||
* @return an {@link ExitStatus} indicating whether processing is
|
||||
* continuable.
|
||||
*/
|
||||
ExitStatus handle(StepContribution contribution) throws Exception;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemReader}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemReader#mark()
|
||||
*/
|
||||
void mark() throws MarkFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemReader}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemReader#reset()
|
||||
*/
|
||||
void reset() throws ResetFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#flush()
|
||||
*/
|
||||
public void flush() throws FlushFailedException;
|
||||
|
||||
/**
|
||||
* Implementations should delegate to an {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.item.ItemWriter#clear()
|
||||
*/
|
||||
public void clear() throws ClearFailedException;
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,198 +1,198 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for factory beans for {@link ItemOrientedStep}. Ensures that all
|
||||
* the mandatory properties are set, and provides basic support for the
|
||||
* {@link Step} interface responsibilities like start limit.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
private int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
private boolean allowStartIfComplete;
|
||||
|
||||
private ItemReader itemReader;
|
||||
|
||||
private ItemWriter itemWriter;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private boolean singleton = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AbstractStepFactoryBean() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name property, which will become the name of the
|
||||
* {@link Step} when it is created.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the String.
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemReader the itemReader to set
|
||||
*/
|
||||
public void setItemReader(ItemReader itemReader) {
|
||||
this.itemReader = itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemWriter the itemWriter to set
|
||||
*/
|
||||
public void setItemWriter(ItemWriter itemWriter) {
|
||||
this.itemWriter = itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected getter for the {@link ItemReader} for subclasses to use.
|
||||
* @return the itemReader
|
||||
*/
|
||||
protected ItemReader getItemReader() {
|
||||
return itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected getter for the {@link ItemWriter} for subclasses to use
|
||||
* @return the itemWriter
|
||||
*/
|
||||
protected ItemWriter getItemWriter() {
|
||||
return itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for {@link JobRepository}.
|
||||
*
|
||||
* @param jobRepository is a mandatory dependence (no default).
|
||||
*/
|
||||
public void setJobRepository(JobRepository jobRepository) {
|
||||
this.jobRepository = jobRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link PlatformTransactionManager}.
|
||||
*
|
||||
* @param transactionManager the transaction manager to set
|
||||
*/
|
||||
public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Step} from the configuration provided.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
public final Object getObject() throws Exception {
|
||||
ItemOrientedStep step = new ItemOrientedStep(getName());
|
||||
applyConfiguration(step);
|
||||
return step;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
Assert.notNull(getItemReader(), "ItemReader must be provided");
|
||||
Assert.notNull(getItemWriter(), "ItemWriter must be provided");
|
||||
Assert.notNull(jobRepository, "JobRepository must be provided");
|
||||
Assert.notNull(transactionManager, "TransactionManager must be provided");
|
||||
|
||||
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
|
||||
step.setTransactionManager(transactionManager);
|
||||
step.setJobRepository(jobRepository);
|
||||
step.setStartLimit(startLimit);
|
||||
step.setAllowStartIfComplete(allowStartIfComplete);
|
||||
|
||||
}
|
||||
|
||||
public Class getObjectType() {
|
||||
return Step.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true by default, but in most cases a {@link Step} should not be
|
||||
* treated as thread safe. Clients are recommended to create a new step for
|
||||
* each job execution.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the singleton flag.
|
||||
* @param singleton the value to set. Defaults to true.
|
||||
*/
|
||||
public void setSingleton(boolean singleton) {
|
||||
this.singleton = singleton;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for factory beans for {@link ItemOrientedStep}. Ensures that all
|
||||
* the mandatory properties are set, and provides basic support for the
|
||||
* {@link Step} interface responsibilities like start limit.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
private int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
private boolean allowStartIfComplete;
|
||||
|
||||
private ItemReader itemReader;
|
||||
|
||||
private ItemWriter itemWriter;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private boolean singleton = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AbstractStepFactoryBean() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name property, which will become the name of the
|
||||
* {@link Step} when it is created.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the String.
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemReader the itemReader to set
|
||||
*/
|
||||
public void setItemReader(ItemReader itemReader) {
|
||||
this.itemReader = itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemWriter the itemWriter to set
|
||||
*/
|
||||
public void setItemWriter(ItemWriter itemWriter) {
|
||||
this.itemWriter = itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected getter for the {@link ItemReader} for subclasses to use.
|
||||
* @return the itemReader
|
||||
*/
|
||||
protected ItemReader getItemReader() {
|
||||
return itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected getter for the {@link ItemWriter} for subclasses to use
|
||||
* @return the itemWriter
|
||||
*/
|
||||
protected ItemWriter getItemWriter() {
|
||||
return itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for {@link JobRepository}.
|
||||
*
|
||||
* @param jobRepository is a mandatory dependence (no default).
|
||||
*/
|
||||
public void setJobRepository(JobRepository jobRepository) {
|
||||
this.jobRepository = jobRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link PlatformTransactionManager}.
|
||||
*
|
||||
* @param transactionManager the transaction manager to set
|
||||
*/
|
||||
public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Step} from the configuration provided.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
public final Object getObject() throws Exception {
|
||||
ItemOrientedStep step = new ItemOrientedStep(getName());
|
||||
applyConfiguration(step);
|
||||
return step;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
Assert.notNull(getItemReader(), "ItemReader must be provided");
|
||||
Assert.notNull(getItemWriter(), "ItemWriter must be provided");
|
||||
Assert.notNull(jobRepository, "JobRepository must be provided");
|
||||
Assert.notNull(transactionManager, "TransactionManager must be provided");
|
||||
|
||||
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
|
||||
step.setTransactionManager(transactionManager);
|
||||
step.setJobRepository(jobRepository);
|
||||
step.setStartLimit(startLimit);
|
||||
step.setAllowStartIfComplete(allowStartIfComplete);
|
||||
|
||||
}
|
||||
|
||||
public Class getObjectType() {
|
||||
return Step.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true by default, but in most cases a {@link Step} should not be
|
||||
* treated as thread safe. Clients are recommended to create a new step for
|
||||
* each job execution.
|
||||
*
|
||||
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the singleton flag.
|
||||
* @param singleton the value to set. Defaults to true.
|
||||
*/
|
||||
public void setSingleton(boolean singleton) {
|
||||
this.singleton = singleton;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,102 +1,102 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.ItemSkipPolicy;
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
|
||||
|
||||
private ItemSkipPolicy itemSkipPolicy = new NeverSkipItemSkipPolicy();
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
*/
|
||||
public ItemSkipPolicyItemHandler(ItemReader itemReader, ItemWriter itemWriter) {
|
||||
super(itemReader, itemWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemSkipPolicy
|
||||
*/
|
||||
public void setItemSkipPolicy(ItemSkipPolicy itemSkipPolicy) {
|
||||
this.itemSkipPolicy = itemSkipPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the business logic, delegating to the reader and writer.
|
||||
* Subclasses could extend the behaviour as long as they always return the
|
||||
* value of this method call in their superclass.<br/>
|
||||
*
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}.<br/>
|
||||
*
|
||||
* If there is an exception and the reader or writer implements
|
||||
* {@link Skippable} then the skip method is called.
|
||||
*
|
||||
* @param contribution the current step
|
||||
* @return {@link ExitStatus#CONTINUABLE} if there is more processing to do
|
||||
* @throws Exception if there is an error
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
ExitStatus exitStatus = ExitStatus.CONTINUABLE;
|
||||
|
||||
try {
|
||||
|
||||
exitStatus = super.handle(contribution);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
if (itemSkipPolicy.shouldSkip(e, contribution.getSkipCount())) {
|
||||
contribution.incrementSkipCount();
|
||||
skip();
|
||||
}
|
||||
else {
|
||||
// Rethrow so that outer transaction is rolled back properly
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current item as skipped if possible. If the reader and / or
|
||||
* writer are {@link Skippable} then delegate to them in that order.
|
||||
*
|
||||
* @see org.springframework.batch.io.Skippable#skip()
|
||||
*/
|
||||
private void skip() {
|
||||
if (getItemReader() instanceof Skippable) {
|
||||
((Skippable) getItemReader()).skip();
|
||||
}
|
||||
if (getItemWriter() instanceof Skippable) {
|
||||
((Skippable) getItemWriter()).skip();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.ItemSkipPolicy;
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
|
||||
|
||||
private ItemSkipPolicy itemSkipPolicy = new NeverSkipItemSkipPolicy();
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
*/
|
||||
public ItemSkipPolicyItemHandler(ItemReader itemReader, ItemWriter itemWriter) {
|
||||
super(itemReader, itemWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemSkipPolicy
|
||||
*/
|
||||
public void setItemSkipPolicy(ItemSkipPolicy itemSkipPolicy) {
|
||||
this.itemSkipPolicy = itemSkipPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the business logic, delegating to the reader and writer.
|
||||
* Subclasses could extend the behaviour as long as they always return the
|
||||
* value of this method call in their superclass.<br/>
|
||||
*
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}.<br/>
|
||||
*
|
||||
* If there is an exception and the reader or writer implements
|
||||
* {@link Skippable} then the skip method is called.
|
||||
*
|
||||
* @param contribution the current step
|
||||
* @return {@link ExitStatus#CONTINUABLE} if there is more processing to do
|
||||
* @throws Exception if there is an error
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
ExitStatus exitStatus = ExitStatus.CONTINUABLE;
|
||||
|
||||
try {
|
||||
|
||||
exitStatus = super.handle(contribution);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
if (itemSkipPolicy.shouldSkip(e, contribution.getSkipCount())) {
|
||||
contribution.incrementSkipCount();
|
||||
skip();
|
||||
}
|
||||
else {
|
||||
// Rethrow so that outer transaction is rolled back properly
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current item as skipped if possible. If the reader and / or
|
||||
* writer are {@link Skippable} then delegate to them in that order.
|
||||
*
|
||||
* @see org.springframework.batch.io.Skippable#skip()
|
||||
*/
|
||||
private void skip() {
|
||||
if (getItemReader() instanceof Skippable) {
|
||||
((Skippable) getItemReader()).skip();
|
||||
}
|
||||
if (getItemWriter() instanceof Skippable) {
|
||||
((Skippable) getItemWriter()).skip();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,140 +1,140 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.BatchListener;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepListener;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.support.RepeatTemplate;
|
||||
|
||||
/**
|
||||
* Factory bean for {@link Step} implementations allowing registration of
|
||||
* listeners and also direct injection of the {@link RepeatOperations} needed at
|
||||
* step and chunk level.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class RepeatOperationsStepFactoryBean extends AbstractStepFactoryBean {
|
||||
|
||||
private ItemStream[] streams = new ItemStream[0];
|
||||
|
||||
private BatchListener[] listeners = new BatchListener[0];
|
||||
|
||||
private RepeatOperations chunkOperations = new RepeatTemplate();
|
||||
|
||||
private RepeatOperations stepOperations = new RepeatTemplate();
|
||||
|
||||
/**
|
||||
* The streams to inject into the {@link Step}. Any instance of
|
||||
* {@link ItemStream} can be used, and will then receive callbacks at the
|
||||
* appropriate stage in the step.
|
||||
*
|
||||
* @param streams an array of listeners
|
||||
*/
|
||||
public void setStreams(ItemStream[] streams) {
|
||||
this.streams = streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* The listeners to inject into the {@link Step}. Any instance of
|
||||
* {@link BatchListener} can be used, and will then receive callbacks at the
|
||||
* appropriate stage in the step.
|
||||
*
|
||||
* @param listeners an array of listeners
|
||||
*/
|
||||
public void setListeners(BatchListener[] listeners) {
|
||||
this.listeners = listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link RepeatOperations} to use for the outer loop of the batch
|
||||
* processing. Should be set up by the caller through a factory. Defaults to
|
||||
* a plain {@link RepeatTemplate}.
|
||||
*
|
||||
* @param stepOperations a {@link RepeatOperations} instance.
|
||||
*/
|
||||
public void setStepOperations(RepeatOperations stepOperations) {
|
||||
this.stepOperations = stepOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link RepeatOperations} to use for the inner loop of the batch
|
||||
* processing. should be set up by the caller through a factory. defaults to
|
||||
* a plain {@link RepeatTemplate}.
|
||||
*
|
||||
* @param chunkOperations a {@link RepeatOperations} instance.
|
||||
*/
|
||||
public void setChunkOperations(RepeatOperations chunkOperations) {
|
||||
this.chunkOperations = chunkOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
super.applyConfiguration(step);
|
||||
|
||||
step.setStreams(streams);
|
||||
|
||||
ItemReader itemReader = getItemReader();
|
||||
ItemWriter itemWriter = getItemWriter();
|
||||
|
||||
/*
|
||||
* Since we are going to wrap these things with listener callbacks we
|
||||
* need to register them here because the step will not know we did
|
||||
* that.
|
||||
*/
|
||||
if (itemReader instanceof ItemStream) {
|
||||
step.registerStream((ItemStream) itemReader);
|
||||
}
|
||||
if (itemReader instanceof StepListener) {
|
||||
step.registerStepListener((StepListener) itemReader);
|
||||
}
|
||||
if (itemWriter instanceof ItemStream) {
|
||||
step.registerStream((ItemStream) itemWriter);
|
||||
}
|
||||
if (itemWriter instanceof StepListener) {
|
||||
step.registerStepListener((StepListener) itemWriter);
|
||||
}
|
||||
|
||||
BatchListenerFactoryHelper helper = new BatchListenerFactoryHelper();
|
||||
|
||||
StepListener[] stepListeners = helper.getStepListeners(listeners);
|
||||
itemReader = helper.getItemReader(itemReader, listeners);
|
||||
itemWriter = helper.getItemWriter(itemWriter, listeners);
|
||||
RepeatOperations stepOperations = helper.addChunkListeners(this.stepOperations, listeners);
|
||||
|
||||
// In case they are used by subclasses:
|
||||
setItemReader(itemReader);
|
||||
setItemWriter(itemWriter);
|
||||
|
||||
step.setStepListeners(stepListeners);
|
||||
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
|
||||
|
||||
step.setChunkOperations(chunkOperations);
|
||||
step.setStepOperations(stepOperations);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.BatchListener;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepListener;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.support.RepeatTemplate;
|
||||
|
||||
/**
|
||||
* Factory bean for {@link Step} implementations allowing registration of
|
||||
* listeners and also direct injection of the {@link RepeatOperations} needed at
|
||||
* step and chunk level.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class RepeatOperationsStepFactoryBean extends AbstractStepFactoryBean {
|
||||
|
||||
private ItemStream[] streams = new ItemStream[0];
|
||||
|
||||
private BatchListener[] listeners = new BatchListener[0];
|
||||
|
||||
private RepeatOperations chunkOperations = new RepeatTemplate();
|
||||
|
||||
private RepeatOperations stepOperations = new RepeatTemplate();
|
||||
|
||||
/**
|
||||
* The streams to inject into the {@link Step}. Any instance of
|
||||
* {@link ItemStream} can be used, and will then receive callbacks at the
|
||||
* appropriate stage in the step.
|
||||
*
|
||||
* @param streams an array of listeners
|
||||
*/
|
||||
public void setStreams(ItemStream[] streams) {
|
||||
this.streams = streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* The listeners to inject into the {@link Step}. Any instance of
|
||||
* {@link BatchListener} can be used, and will then receive callbacks at the
|
||||
* appropriate stage in the step.
|
||||
*
|
||||
* @param listeners an array of listeners
|
||||
*/
|
||||
public void setListeners(BatchListener[] listeners) {
|
||||
this.listeners = listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link RepeatOperations} to use for the outer loop of the batch
|
||||
* processing. Should be set up by the caller through a factory. Defaults to
|
||||
* a plain {@link RepeatTemplate}.
|
||||
*
|
||||
* @param stepOperations a {@link RepeatOperations} instance.
|
||||
*/
|
||||
public void setStepOperations(RepeatOperations stepOperations) {
|
||||
this.stepOperations = stepOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link RepeatOperations} to use for the inner loop of the batch
|
||||
* processing. should be set up by the caller through a factory. defaults to
|
||||
* a plain {@link RepeatTemplate}.
|
||||
*
|
||||
* @param chunkOperations a {@link RepeatOperations} instance.
|
||||
*/
|
||||
public void setChunkOperations(RepeatOperations chunkOperations) {
|
||||
this.chunkOperations = chunkOperations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
super.applyConfiguration(step);
|
||||
|
||||
step.setStreams(streams);
|
||||
|
||||
ItemReader itemReader = getItemReader();
|
||||
ItemWriter itemWriter = getItemWriter();
|
||||
|
||||
/*
|
||||
* Since we are going to wrap these things with listener callbacks we
|
||||
* need to register them here because the step will not know we did
|
||||
* that.
|
||||
*/
|
||||
if (itemReader instanceof ItemStream) {
|
||||
step.registerStream((ItemStream) itemReader);
|
||||
}
|
||||
if (itemReader instanceof StepListener) {
|
||||
step.registerStepListener((StepListener) itemReader);
|
||||
}
|
||||
if (itemWriter instanceof ItemStream) {
|
||||
step.registerStream((ItemStream) itemWriter);
|
||||
}
|
||||
if (itemWriter instanceof StepListener) {
|
||||
step.registerStepListener((StepListener) itemWriter);
|
||||
}
|
||||
|
||||
BatchListenerFactoryHelper helper = new BatchListenerFactoryHelper();
|
||||
|
||||
StepListener[] stepListeners = helper.getStepListeners(listeners);
|
||||
itemReader = helper.getItemReader(itemReader, listeners);
|
||||
itemWriter = helper.getItemWriter(itemWriter, listeners);
|
||||
RepeatOperations stepOperations = helper.addChunkListeners(this.stepOperations, listeners);
|
||||
|
||||
// In case they are used by subclasses:
|
||||
setItemReader(itemReader);
|
||||
setItemWriter(itemWriter);
|
||||
|
||||
step.setStepListeners(stepListeners);
|
||||
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
|
||||
|
||||
step.setChunkOperations(chunkOperations);
|
||||
step.setStepOperations(stepOperations);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Simple implementation of {@link ExitStatusExceptionClassifier} that returns
|
||||
* basic String exit codes, and defaults to the class name of the throwable for
|
||||
* the message. Most users will want to write their own implementation that
|
||||
* creates more specific exit codes for different exception types.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class SimpleExitStatusExceptionClassifier implements
|
||||
ExitStatusExceptionClassifier {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable)
|
||||
*/
|
||||
public ExitStatus classifyForExitCode(Throwable throwable) {
|
||||
return (ExitStatus) classify(throwable);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable)
|
||||
*/
|
||||
public Object classify(Throwable throwable) {
|
||||
|
||||
ExitStatus exitStatus = ExitStatus.FAILED;
|
||||
|
||||
if (throwable instanceof JobInterruptedException) {
|
||||
exitStatus = new ExitStatus(false, JOB_INTERRUPTED,
|
||||
JobInterruptedException.class.getName());
|
||||
} else {
|
||||
String message = "";
|
||||
if (throwable!=null) {
|
||||
StringWriter writer = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(writer));
|
||||
message = writer.toString();
|
||||
}
|
||||
exitStatus = new ExitStatus(false, FATAL_EXCEPTION, message);
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.common.ExceptionClassifier#getDefault()
|
||||
*/
|
||||
public Object getDefault() {
|
||||
// return without message since we don't know what the exception is
|
||||
return new ExitStatus(false, FATAL_EXCEPTION);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Simple implementation of {@link ExitStatusExceptionClassifier} that returns
|
||||
* basic String exit codes, and defaults to the class name of the throwable for
|
||||
* the message. Most users will want to write their own implementation that
|
||||
* creates more specific exit codes for different exception types.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class SimpleExitStatusExceptionClassifier implements
|
||||
ExitStatusExceptionClassifier {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable)
|
||||
*/
|
||||
public ExitStatus classifyForExitCode(Throwable throwable) {
|
||||
return (ExitStatus) classify(throwable);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable)
|
||||
*/
|
||||
public Object classify(Throwable throwable) {
|
||||
|
||||
ExitStatus exitStatus = ExitStatus.FAILED;
|
||||
|
||||
if (throwable instanceof JobInterruptedException) {
|
||||
exitStatus = new ExitStatus(false, JOB_INTERRUPTED,
|
||||
JobInterruptedException.class.getName());
|
||||
} else {
|
||||
String message = "";
|
||||
if (throwable!=null) {
|
||||
StringWriter writer = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(writer));
|
||||
message = writer.toString();
|
||||
}
|
||||
exitStatus = new ExitStatus(false, FATAL_EXCEPTION, message);
|
||||
}
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.common.ExceptionClassifier#getDefault()
|
||||
*/
|
||||
public Object getDefault() {
|
||||
// return without message since we don't know what the exception is
|
||||
return new ExitStatus(false, FATAL_EXCEPTION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,115 +1,115 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.execution.step.ItemHandler;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
import org.springframework.batch.item.exception.FlushFailedException;
|
||||
import org.springframework.batch.item.exception.MarkFailedException;
|
||||
import org.springframework.batch.item.exception.ResetFailedException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* Simplest possible implementation of {@link ItemHandler} with no skipping or
|
||||
* recovering. Just delegates all calls to the provided {@link ItemReader} and
|
||||
* {@link ItemWriter}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SimpleItemHandler implements ItemHandler {
|
||||
|
||||
private ItemReader itemReader;
|
||||
|
||||
private ItemWriter itemWriter;
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
*/
|
||||
public SimpleItemHandler(ItemReader itemReader, ItemWriter itemWriter) {
|
||||
super();
|
||||
this.itemReader = itemReader;
|
||||
this.itemWriter = itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the ItemReader.
|
||||
* @return the itemReader
|
||||
*/
|
||||
public ItemReader getItemReader() {
|
||||
return itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the ItemWriter.
|
||||
* @return the itemWriter
|
||||
*/
|
||||
public ItemWriter getItemWriter() {
|
||||
return itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.execution.step.ItemHandler#handle(org.springframework.batch.core.domain.StepContribution)
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
Object item = itemReader.read();
|
||||
if (item == null) {
|
||||
return ExitStatus.FINISHED;
|
||||
}
|
||||
itemWriter.write(item);
|
||||
return ExitStatus.CONTINUABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MarkFailedException
|
||||
* @see org.springframework.batch.item.ItemReader#mark()
|
||||
*/
|
||||
public void mark() throws MarkFailedException {
|
||||
itemReader.mark();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ResetFailedException
|
||||
* @see org.springframework.batch.item.ItemReader#reset()
|
||||
*/
|
||||
public void reset() throws ResetFailedException {
|
||||
itemReader.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClearFailedException
|
||||
* @see org.springframework.batch.item.ItemWriter#clear()
|
||||
*/
|
||||
public void clear() throws ClearFailedException {
|
||||
itemWriter.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FlushFailedException
|
||||
* @see org.springframework.batch.item.ItemWriter#flush()
|
||||
*/
|
||||
public void flush() throws FlushFailedException {
|
||||
itemWriter.flush();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.execution.step.ItemHandler;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
import org.springframework.batch.item.exception.FlushFailedException;
|
||||
import org.springframework.batch.item.exception.MarkFailedException;
|
||||
import org.springframework.batch.item.exception.ResetFailedException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
/**
|
||||
* Simplest possible implementation of {@link ItemHandler} with no skipping or
|
||||
* recovering. Just delegates all calls to the provided {@link ItemReader} and
|
||||
* {@link ItemWriter}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SimpleItemHandler implements ItemHandler {
|
||||
|
||||
private ItemReader itemReader;
|
||||
|
||||
private ItemWriter itemWriter;
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
*/
|
||||
public SimpleItemHandler(ItemReader itemReader, ItemWriter itemWriter) {
|
||||
super();
|
||||
this.itemReader = itemReader;
|
||||
this.itemWriter = itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the ItemReader.
|
||||
* @return the itemReader
|
||||
*/
|
||||
public ItemReader getItemReader() {
|
||||
return itemReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public getter for the ItemWriter.
|
||||
* @return the itemWriter
|
||||
*/
|
||||
public ItemWriter getItemWriter() {
|
||||
return itemWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}.
|
||||
*
|
||||
* @see org.springframework.batch.execution.step.ItemHandler#handle(org.springframework.batch.core.domain.StepContribution)
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
Object item = itemReader.read();
|
||||
if (item == null) {
|
||||
return ExitStatus.FINISHED;
|
||||
}
|
||||
itemWriter.write(item);
|
||||
return ExitStatus.CONTINUABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MarkFailedException
|
||||
* @see org.springframework.batch.item.ItemReader#mark()
|
||||
*/
|
||||
public void mark() throws MarkFailedException {
|
||||
itemReader.mark();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ResetFailedException
|
||||
* @see org.springframework.batch.item.ItemReader#reset()
|
||||
*/
|
||||
public void reset() throws ResetFailedException {
|
||||
itemReader.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClearFailedException
|
||||
* @see org.springframework.batch.item.ItemWriter#clear()
|
||||
*/
|
||||
public void clear() throws ClearFailedException {
|
||||
itemWriter.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FlushFailedException
|
||||
* @see org.springframework.batch.item.ItemWriter#flush()
|
||||
*/
|
||||
public void flush() throws FlushFailedException {
|
||||
itemWriter.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,197 +1,197 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemKeyGenerator;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemRecoverer;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.batch.retry.RetryOperations;
|
||||
import org.springframework.batch.retry.RetryPolicy;
|
||||
import org.springframework.batch.retry.backoff.BackOffPolicy;
|
||||
import org.springframework.batch.retry.callback.ItemReaderRetryCallback;
|
||||
import org.springframework.batch.retry.policy.ItemReaderRetryPolicy;
|
||||
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.batch.retry.support.RetryTemplate;
|
||||
|
||||
/**
|
||||
* Factory bean for step that executes its item processing with a stateful
|
||||
* retry. Failed items are never skipped, but always cause a rollback. Before a
|
||||
* rollback, the {@link Step} makes a record of the failed item, caching it
|
||||
* under a key given by the {@link ItemKeyGenerator}. Then when it is
|
||||
* re-presented by the {@link ItemReader} it is recognised and retried up to a
|
||||
* limit given by the {@link RetryPolicy}. When the retry is exhausted instead
|
||||
* of the item being skipped it is handled by an {@link ItemRecoverer}.<br/>
|
||||
*
|
||||
* The skipLimit property is still used to control the overall exception
|
||||
* handling policy. Only exhausted retries count against the exception handler,
|
||||
* instead of counting all exceptions.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
|
||||
private ItemKeyGenerator itemKeyGenerator;
|
||||
|
||||
private ItemRecoverer itemRecoverer;
|
||||
|
||||
private int retryLimit;
|
||||
|
||||
private Class[] retryableExceptionClasses;
|
||||
|
||||
private BackOffPolicy backOffPolicy;
|
||||
|
||||
/**
|
||||
* Public setter for the retry limit. Each item can be retried up to this
|
||||
* limit.
|
||||
* @param retryLimit the retry limit to set
|
||||
*/
|
||||
public void setRetryLimit(int retryLimit) {
|
||||
this.retryLimit = retryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the Class[].
|
||||
* @param retryableExceptionClasses the retryableExceptionClasses to set
|
||||
*/
|
||||
public void setRetryableExceptionClasses(Class[] retryableExceptionClasses) {
|
||||
this.retryableExceptionClasses = retryableExceptionClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link BackOffPolicy}.
|
||||
* @param backOffPolicy the {@link BackOffPolicy} to set
|
||||
*/
|
||||
public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
|
||||
this.backOffPolicy = backOffPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemKeyGenerator} which will be used to
|
||||
* cache failed items between transactions. If it is not injected but the
|
||||
* reader or writer implement {@link ItemKeyGenerator}, one of those will
|
||||
* be used instead (preferring the reader to the writer if both would be
|
||||
* appropriate). If neither can be used, then the default will be to just
|
||||
* use the item itself as a cache key.
|
||||
*
|
||||
* @param itemKeyGenerator the {@link ItemKeyGenerator} to set
|
||||
*/
|
||||
public void setItemKeyGenerator(ItemKeyGenerator itemKeyGenerator) {
|
||||
this.itemKeyGenerator = itemKeyGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemRecoverer}. If this is set the
|
||||
* {@link ItemRecoverer#recover(Object, Throwable)} will be called when
|
||||
* retry is exhausted, and within the business transaction (which will not
|
||||
* roll back because of any other item-related errors).
|
||||
*
|
||||
* @param itemRecoverer the {@link ItemRecoverer} to set
|
||||
*/
|
||||
public void setItemRecoverer(ItemRecoverer itemRecoverer) {
|
||||
this.itemRecoverer = itemRecoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
super.applyConfiguration(step);
|
||||
|
||||
if (retryLimit > 0) {
|
||||
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit);
|
||||
if (retryableExceptionClasses != null) {
|
||||
retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses);
|
||||
}
|
||||
|
||||
// Co-ordinate the retry policy with the exception handler:
|
||||
getStepOperations()
|
||||
.setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler()));
|
||||
|
||||
ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), itemKeyGenerator,
|
||||
getItemWriter());
|
||||
retryCallback.setRecoverer(itemRecoverer);
|
||||
ItemReaderRetryPolicy itemProviderRetryPolicy = new ItemReaderRetryPolicy(retryPolicy);
|
||||
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(itemProviderRetryPolicy);
|
||||
if (backOffPolicy != null) {
|
||||
retryTemplate.setBackOffPolicy(backOffPolicy);
|
||||
}
|
||||
|
||||
StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(),
|
||||
retryTemplate, retryCallback);
|
||||
|
||||
step.setItemHandler(itemProcessor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class StatefulRetryItemHandler extends SimpleItemHandler {
|
||||
|
||||
final private RetryOperations retryOperations;
|
||||
|
||||
final private ItemReaderRetryCallback retryCallback;
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
* @param retryCallback
|
||||
* @param retryTemplate
|
||||
*/
|
||||
public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate,
|
||||
ItemReaderRetryCallback retryCallback) {
|
||||
super(itemReader, itemWriter);
|
||||
this.retryOperations = retryTemplate;
|
||||
this.retryCallback = retryCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the business logic, delegating to the reader and writer.
|
||||
* Subclasses could extend the behaviour as long as they always return
|
||||
* the value of this method call in their superclass.<br/>
|
||||
*
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}. The call to {@link ItemWriter} is wrapped in a
|
||||
* stateful retry. In that case the {@link ItemRecoverer} is used (if
|
||||
* provided) in the case of an exception to apply alternate processing
|
||||
* to the item. If the stateful retry is in place then the recovery will
|
||||
* happen in the next transaction automatically, otherwise it might be
|
||||
* necessary for clients to make the recover method transactional with
|
||||
* appropriate propagation behaviour (probably REQUIRES_NEW because the
|
||||
* call will happen in the context of a transaction that is about to
|
||||
* rollback).<br/>
|
||||
*
|
||||
* @param contribution the current step
|
||||
* @return {@link ExitStatus#CONTINUABLE} if there is more processing to
|
||||
* do
|
||||
* @throws Exception if there is an error
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
return new ExitStatus(retryOperations.execute(retryCallback) != null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepContribution;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemKeyGenerator;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemRecoverer;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.batch.retry.RetryOperations;
|
||||
import org.springframework.batch.retry.RetryPolicy;
|
||||
import org.springframework.batch.retry.backoff.BackOffPolicy;
|
||||
import org.springframework.batch.retry.callback.ItemReaderRetryCallback;
|
||||
import org.springframework.batch.retry.policy.ItemReaderRetryPolicy;
|
||||
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
|
||||
import org.springframework.batch.retry.support.RetryTemplate;
|
||||
|
||||
/**
|
||||
* Factory bean for step that executes its item processing with a stateful
|
||||
* retry. Failed items are never skipped, but always cause a rollback. Before a
|
||||
* rollback, the {@link Step} makes a record of the failed item, caching it
|
||||
* under a key given by the {@link ItemKeyGenerator}. Then when it is
|
||||
* re-presented by the {@link ItemReader} it is recognised and retried up to a
|
||||
* limit given by the {@link RetryPolicy}. When the retry is exhausted instead
|
||||
* of the item being skipped it is handled by an {@link ItemRecoverer}.<br/>
|
||||
*
|
||||
* The skipLimit property is still used to control the overall exception
|
||||
* handling policy. Only exhausted retries count against the exception handler,
|
||||
* instead of counting all exceptions.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean {
|
||||
|
||||
private ItemKeyGenerator itemKeyGenerator;
|
||||
|
||||
private ItemRecoverer itemRecoverer;
|
||||
|
||||
private int retryLimit;
|
||||
|
||||
private Class[] retryableExceptionClasses;
|
||||
|
||||
private BackOffPolicy backOffPolicy;
|
||||
|
||||
/**
|
||||
* Public setter for the retry limit. Each item can be retried up to this
|
||||
* limit.
|
||||
* @param retryLimit the retry limit to set
|
||||
*/
|
||||
public void setRetryLimit(int retryLimit) {
|
||||
this.retryLimit = retryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the Class[].
|
||||
* @param retryableExceptionClasses the retryableExceptionClasses to set
|
||||
*/
|
||||
public void setRetryableExceptionClasses(Class[] retryableExceptionClasses) {
|
||||
this.retryableExceptionClasses = retryableExceptionClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link BackOffPolicy}.
|
||||
* @param backOffPolicy the {@link BackOffPolicy} to set
|
||||
*/
|
||||
public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
|
||||
this.backOffPolicy = backOffPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemKeyGenerator} which will be used to
|
||||
* cache failed items between transactions. If it is not injected but the
|
||||
* reader or writer implement {@link ItemKeyGenerator}, one of those will
|
||||
* be used instead (preferring the reader to the writer if both would be
|
||||
* appropriate). If neither can be used, then the default will be to just
|
||||
* use the item itself as a cache key.
|
||||
*
|
||||
* @param itemKeyGenerator the {@link ItemKeyGenerator} to set
|
||||
*/
|
||||
public void setItemKeyGenerator(ItemKeyGenerator itemKeyGenerator) {
|
||||
this.itemKeyGenerator = itemKeyGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link ItemRecoverer}. If this is set the
|
||||
* {@link ItemRecoverer#recover(Object, Throwable)} will be called when
|
||||
* retry is exhausted, and within the business transaction (which will not
|
||||
* roll back because of any other item-related errors).
|
||||
*
|
||||
* @param itemRecoverer the {@link ItemRecoverer} to set
|
||||
*/
|
||||
public void setItemRecoverer(ItemRecoverer itemRecoverer) {
|
||||
this.itemRecoverer = itemRecoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step
|
||||
*
|
||||
*/
|
||||
protected void applyConfiguration(ItemOrientedStep step) {
|
||||
|
||||
super.applyConfiguration(step);
|
||||
|
||||
if (retryLimit > 0) {
|
||||
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit);
|
||||
if (retryableExceptionClasses != null) {
|
||||
retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses);
|
||||
}
|
||||
|
||||
// Co-ordinate the retry policy with the exception handler:
|
||||
getStepOperations()
|
||||
.setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler()));
|
||||
|
||||
ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), itemKeyGenerator,
|
||||
getItemWriter());
|
||||
retryCallback.setRecoverer(itemRecoverer);
|
||||
ItemReaderRetryPolicy itemProviderRetryPolicy = new ItemReaderRetryPolicy(retryPolicy);
|
||||
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(itemProviderRetryPolicy);
|
||||
if (backOffPolicy != null) {
|
||||
retryTemplate.setBackOffPolicy(backOffPolicy);
|
||||
}
|
||||
|
||||
StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(),
|
||||
retryTemplate, retryCallback);
|
||||
|
||||
step.setItemHandler(itemProcessor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class StatefulRetryItemHandler extends SimpleItemHandler {
|
||||
|
||||
final private RetryOperations retryOperations;
|
||||
|
||||
final private ItemReaderRetryCallback retryCallback;
|
||||
|
||||
/**
|
||||
* @param itemReader
|
||||
* @param itemWriter
|
||||
* @param retryCallback
|
||||
* @param retryTemplate
|
||||
*/
|
||||
public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate,
|
||||
ItemReaderRetryCallback retryCallback) {
|
||||
super(itemReader, itemWriter);
|
||||
this.retryOperations = retryTemplate;
|
||||
this.retryCallback = retryCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the business logic, delegating to the reader and writer.
|
||||
* Subclasses could extend the behaviour as long as they always return
|
||||
* the value of this method call in their superclass.<br/>
|
||||
*
|
||||
* Read from the {@link ItemReader} and process (if not null) with the
|
||||
* {@link ItemWriter}. The call to {@link ItemWriter} is wrapped in a
|
||||
* stateful retry. In that case the {@link ItemRecoverer} is used (if
|
||||
* provided) in the case of an exception to apply alternate processing
|
||||
* to the item. If the stateful retry is in place then the recovery will
|
||||
* happen in the next transaction automatically, otherwise it might be
|
||||
* necessary for clients to make the recover method transactional with
|
||||
* appropriate propagation behaviour (probably REQUIRES_NEW because the
|
||||
* call will happen in the context of a transaction that is about to
|
||||
* rollback).<br/>
|
||||
*
|
||||
* @param contribution the current step
|
||||
* @return {@link ExitStatus#CONTINUABLE} if there is more processing to
|
||||
* do
|
||||
* @throws Exception if there is an error
|
||||
*/
|
||||
public ExitStatus handle(StepContribution contribution) throws Exception {
|
||||
return new ExitStatus(retryOperations.execute(retryCallback) != null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
platform=db2
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
platform=db2
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
platform=db2
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
GENERATED = GENERATED BY DEFAULT AS IDENTITY
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
platform=db2
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
GENERATED = GENERATED BY DEFAULT AS IDENTITY
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1));
|
||||
#end
|
||||
#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1));
|
||||
#end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
platform=hsqldb
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY = IDENTITY
|
||||
IFEXISTS = IF EXISTS
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = LONGVARBINARY
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
platform=hsqldb
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY = IDENTITY
|
||||
IFEXISTS = IF EXISTS
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = LONGVARBINARY
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#macro (sequence $name)CREATE TABLE ${name} (
|
||||
ID BIGINT IDENTITY
|
||||
);
|
||||
#end
|
||||
#macro (sequence $name)CREATE TABLE ${name} (
|
||||
ID BIGINT IDENTITY
|
||||
);
|
||||
#end
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
platform=oracle10g
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY = unsigned
|
||||
GENERATED =
|
||||
IFEXISTSBEFORE = IF EXISTS
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
platform=oracle10g
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY = unsigned
|
||||
GENERATED =
|
||||
IFEXISTSBEFORE = IF EXISTS
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = TABLE
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM;
|
||||
INSERT INTO ${name} values(0);
|
||||
#end
|
||||
#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM;
|
||||
INSERT INTO ${name} values(0);
|
||||
#end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
platform=oracle10g
|
||||
# SQL language oddities
|
||||
BIGINT = NUMBER(38)
|
||||
IDENTITY =
|
||||
GENERATED =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
platform=oracle10g
|
||||
# SQL language oddities
|
||||
BIGINT = NUMBER(38)
|
||||
IDENTITY =
|
||||
GENERATED =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BLOB
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
platform=postgresql
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
GENERATED =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BYTEA
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
platform=postgresql
|
||||
# SQL language oddities
|
||||
BIGINT = BIGINT
|
||||
IDENTITY =
|
||||
GENERATED =
|
||||
DOUBLE = DOUBLE PRECISION
|
||||
BLOB = BYTEA
|
||||
# for generating drop statements...
|
||||
SEQUENCE = SEQUENCE
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
#macro (sequence $name)CREATE SEQUENCE ${name};
|
||||
#end
|
||||
|
||||
@@ -1,131 +1,131 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobRegistryBeanPostProcessorTests extends TestCase {
|
||||
|
||||
private JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor();
|
||||
|
||||
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 {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
assertEquals(configuration, processor.postProcessAfterInitialization(
|
||||
configuration, "bar"));
|
||||
assertEquals(configuration, registry.getJob("foo"));
|
||||
}
|
||||
|
||||
public void testAfterInitializationWithDuplicate() throws Exception {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
processor.postProcessAfterInitialization(configuration, "bar");
|
||||
try {
|
||||
processor.postProcessAfterInitialization(configuration, "spam");
|
||||
fail("Expected FatalBeanException");
|
||||
} catch (FatalBeanException e) {
|
||||
// Expected
|
||||
assertTrue(e.getCause() instanceof DuplicateJobException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnregisterOnDestroy() throws Exception {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
assertEquals(configuration, processor.postProcessAfterInitialization(
|
||||
configuration, "bar"));
|
||||
processor.destroy();
|
||||
try {
|
||||
assertEquals(null, registry.getJob("foo"));
|
||||
fail("Expected NoSuchJobConfigurationException");
|
||||
} catch (NoSuchJobException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExecutionWithApplicationContext() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"test-context.xml", getClass());
|
||||
MapJobRegistry registry = (MapJobRegistry) context
|
||||
.getBean("registry");
|
||||
Collection configurations = registry.getJobNames();
|
||||
// System.err.println(configurations);
|
||||
String[] names = context.getBeanNamesForType(JobSupport.class);
|
||||
int count = names.length;
|
||||
// Each concrete bean of type JobConfiguration is registered...
|
||||
assertEquals(count, configurations.size());
|
||||
// N.B. there is a failure / wonky mode where a parent bean is given an
|
||||
// explicit name or beanName (using property setter): in this case then
|
||||
// child beans will have the same name and will be re-registered (and
|
||||
// override, if the registry supports that).
|
||||
assertNotNull(registry.getJob("test-job"));
|
||||
assertEquals(context.getBean("test-job-with-name"), registry
|
||||
.getJob("foo"));
|
||||
assertEquals(context.getBean("test-job-with-bean-name"), registry
|
||||
.getJob("bar"));
|
||||
assertEquals(context.getBean("test-job-with-parent-and-name"), registry
|
||||
.getJob("spam"));
|
||||
assertEquals(context.getBean("test-job-with-parent-and-bean-name"),
|
||||
registry.getJob("bucket"));
|
||||
assertEquals(context.getBean("test-job-with-concrete-parent"), registry
|
||||
.getJob("maps"));
|
||||
assertEquals(context.getBean("test-job-with-concrete-parent-and-name"),
|
||||
registry.getJob("oof"));
|
||||
assertEquals(context
|
||||
.getBean("test-job-with-concrete-parent-and-bean-name"),
|
||||
registry.getJob("rab"));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobRegistryBeanPostProcessorTests extends TestCase {
|
||||
|
||||
private JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor();
|
||||
|
||||
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 {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
assertEquals(configuration, processor.postProcessAfterInitialization(
|
||||
configuration, "bar"));
|
||||
assertEquals(configuration, registry.getJob("foo"));
|
||||
}
|
||||
|
||||
public void testAfterInitializationWithDuplicate() throws Exception {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
processor.postProcessAfterInitialization(configuration, "bar");
|
||||
try {
|
||||
processor.postProcessAfterInitialization(configuration, "spam");
|
||||
fail("Expected FatalBeanException");
|
||||
} catch (FatalBeanException e) {
|
||||
// Expected
|
||||
assertTrue(e.getCause() instanceof DuplicateJobException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnregisterOnDestroy() throws Exception {
|
||||
MapJobRegistry registry = new MapJobRegistry();
|
||||
processor.setJobRegistry(registry);
|
||||
JobSupport configuration = new JobSupport();
|
||||
configuration.setBeanName("foo");
|
||||
assertEquals(configuration, processor.postProcessAfterInitialization(
|
||||
configuration, "bar"));
|
||||
processor.destroy();
|
||||
try {
|
||||
assertEquals(null, registry.getJob("foo"));
|
||||
fail("Expected NoSuchJobConfigurationException");
|
||||
} catch (NoSuchJobException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExecutionWithApplicationContext() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"test-context.xml", getClass());
|
||||
MapJobRegistry registry = (MapJobRegistry) context
|
||||
.getBean("registry");
|
||||
Collection configurations = registry.getJobNames();
|
||||
// System.err.println(configurations);
|
||||
String[] names = context.getBeanNamesForType(JobSupport.class);
|
||||
int count = names.length;
|
||||
// Each concrete bean of type JobConfiguration is registered...
|
||||
assertEquals(count, configurations.size());
|
||||
// N.B. there is a failure / wonky mode where a parent bean is given an
|
||||
// explicit name or beanName (using property setter): in this case then
|
||||
// child beans will have the same name and will be re-registered (and
|
||||
// override, if the registry supports that).
|
||||
assertNotNull(registry.getJob("test-job"));
|
||||
assertEquals(context.getBean("test-job-with-name"), registry
|
||||
.getJob("foo"));
|
||||
assertEquals(context.getBean("test-job-with-bean-name"), registry
|
||||
.getJob("bar"));
|
||||
assertEquals(context.getBean("test-job-with-parent-and-name"), registry
|
||||
.getJob("spam"));
|
||||
assertEquals(context.getBean("test-job-with-parent-and-bean-name"),
|
||||
registry.getJob("bucket"));
|
||||
assertEquals(context.getBean("test-job-with-concrete-parent"), registry
|
||||
.getJob("maps"));
|
||||
assertEquals(context.getBean("test-job-with-concrete-parent-and-name"),
|
||||
registry.getJob("oof"));
|
||||
assertEquals(context
|
||||
.getBean("test-job-with-concrete-parent-and-bean-name"),
|
||||
registry.getJob("rab"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobFactory;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MapJobRegistryTests extends TestCase {
|
||||
|
||||
private MapJobRegistry registry = new MapJobRegistry();
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#unregister(String)}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testUnregister() throws Exception {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
assertNotNull(registry.getJob("foo"));
|
||||
registry.unregister("foo");
|
||||
try {
|
||||
assertNull(registry.getJob("foo"));
|
||||
fail("Expected NoSuchJobConfigurationException");
|
||||
}
|
||||
catch (NoSuchJobException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}.
|
||||
*/
|
||||
public void testReplaceDuplicateConfiguration() throws Exception {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
try {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
fail("Expected DuplicateJobConfigurationException");
|
||||
} catch (DuplicateJobException e) {
|
||||
// unexpected: even if the job is different we want a DuplicateJobException
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}.
|
||||
*/
|
||||
public void testRealDuplicateConfiguration() throws Exception {
|
||||
JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo"));
|
||||
registry.register(jobFactory);
|
||||
try {
|
||||
registry.register(jobFactory);
|
||||
fail("Unexpected DuplicateJobConfigurationException");
|
||||
} catch (DuplicateJobException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJobNames()}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testGetJobConfigurations() throws Exception {
|
||||
JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo"));
|
||||
registry.register(jobFactory);
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("bar")));
|
||||
Collection configurations = registry.getJobNames();
|
||||
assertEquals(2, configurations.size());
|
||||
assertTrue(configurations.contains(jobFactory.getJobName()));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.configuration.JobFactory;
|
||||
import org.springframework.batch.core.repository.DuplicateJobException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MapJobRegistryTests extends TestCase {
|
||||
|
||||
private MapJobRegistry registry = new MapJobRegistry();
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#unregister(String)}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testUnregister() throws Exception {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
assertNotNull(registry.getJob("foo"));
|
||||
registry.unregister("foo");
|
||||
try {
|
||||
assertNull(registry.getJob("foo"));
|
||||
fail("Expected NoSuchJobConfigurationException");
|
||||
}
|
||||
catch (NoSuchJobException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}.
|
||||
*/
|
||||
public void testReplaceDuplicateConfiguration() throws Exception {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
try {
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("foo")));
|
||||
fail("Expected DuplicateJobConfigurationException");
|
||||
} catch (DuplicateJobException e) {
|
||||
// unexpected: even if the job is different we want a DuplicateJobException
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}.
|
||||
*/
|
||||
public void testRealDuplicateConfiguration() throws Exception {
|
||||
JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo"));
|
||||
registry.register(jobFactory);
|
||||
try {
|
||||
registry.register(jobFactory);
|
||||
fail("Unexpected DuplicateJobConfigurationException");
|
||||
} catch (DuplicateJobException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("foo")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJobNames()}.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testGetJobConfigurations() throws Exception {
|
||||
JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo"));
|
||||
registry.register(jobFactory);
|
||||
registry.register(new ReferenceJobFactory(new JobSupport("bar")));
|
||||
Collection configurations = registry.getJobNames();
|
||||
assertEquals(2, configurations.size());
|
||||
assertTrue(configurations.contains(jobFactory.getJobName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,115 +1,115 @@
|
||||
/*
|
||||
* 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.Collections;
|
||||
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class AbstractJobTests extends TestCase {
|
||||
|
||||
JobSupport job = new JobSupport("job");
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#JobConfiguration()}.
|
||||
*/
|
||||
public void testJobConfiguration() {
|
||||
job = new JobSupport();
|
||||
assertNull(job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}.
|
||||
*/
|
||||
public void testSetBeanName() {
|
||||
job.setBeanName("foo");
|
||||
assertEquals("job", job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}.
|
||||
*/
|
||||
public void testSetBeanNameWithNullName() {
|
||||
job = new JobSupport(null);
|
||||
assertEquals(null, job.getName());
|
||||
job.setBeanName("foo");
|
||||
assertEquals("foo", job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setStepNames(java.util.List)}.
|
||||
*/
|
||||
public void testSetSteps() {
|
||||
job.setSteps(Collections.singletonList(new StepSupport("step")));
|
||||
assertEquals(1, job.getSteps().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#addStepName(org.springframework.batch.core.configuration.StepConfiguration)}.
|
||||
*/
|
||||
public void testAddStep() {
|
||||
job.addStep(new StepSupport("step"));
|
||||
assertEquals(1, job.getSteps().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setStartLimit(int)}.
|
||||
*/
|
||||
public void testSetStartLimit() {
|
||||
assertEquals(Integer.MAX_VALUE, job.getStartLimit());
|
||||
job.setStartLimit(10);
|
||||
assertEquals(10, job.getStartLimit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setRestartable(boolean)}.
|
||||
*/
|
||||
public void testSetRestartable() {
|
||||
assertFalse(job.isRestartable());
|
||||
job.setRestartable(true);
|
||||
assertTrue(job.isRestartable());
|
||||
}
|
||||
|
||||
public void testToString() throws Exception {
|
||||
String value = job.toString();
|
||||
assertTrue("Should contain name: "+value, value.indexOf("name=")>=0);
|
||||
}
|
||||
|
||||
public void testRunNotSupported() throws Exception {
|
||||
try {
|
||||
job.execute(null);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// expected
|
||||
String message = e.getMessage();
|
||||
assertTrue("Message should contain JobSupport: "+message, message.contains("JobSupport"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.Collections;
|
||||
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class AbstractJobTests extends TestCase {
|
||||
|
||||
JobSupport job = new JobSupport("job");
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#JobConfiguration()}.
|
||||
*/
|
||||
public void testJobConfiguration() {
|
||||
job = new JobSupport();
|
||||
assertNull(job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}.
|
||||
*/
|
||||
public void testSetBeanName() {
|
||||
job.setBeanName("foo");
|
||||
assertEquals("job", job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}.
|
||||
*/
|
||||
public void testSetBeanNameWithNullName() {
|
||||
job = new JobSupport(null);
|
||||
assertEquals(null, job.getName());
|
||||
job.setBeanName("foo");
|
||||
assertEquals("foo", job.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setStepNames(java.util.List)}.
|
||||
*/
|
||||
public void testSetSteps() {
|
||||
job.setSteps(Collections.singletonList(new StepSupport("step")));
|
||||
assertEquals(1, job.getSteps().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#addStepName(org.springframework.batch.core.configuration.StepConfiguration)}.
|
||||
*/
|
||||
public void testAddStep() {
|
||||
job.addStep(new StepSupport("step"));
|
||||
assertEquals(1, job.getSteps().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setStartLimit(int)}.
|
||||
*/
|
||||
public void testSetStartLimit() {
|
||||
assertEquals(Integer.MAX_VALUE, job.getStartLimit());
|
||||
job.setStartLimit(10);
|
||||
assertEquals(10, job.getStartLimit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.springframework.batch.execution.job.AbstractJob#setRestartable(boolean)}.
|
||||
*/
|
||||
public void testSetRestartable() {
|
||||
assertFalse(job.isRestartable());
|
||||
job.setRestartable(true);
|
||||
assertTrue(job.isRestartable());
|
||||
}
|
||||
|
||||
public void testToString() throws Exception {
|
||||
String value = job.toString();
|
||||
assertTrue("Should contain name: "+value, value.indexOf("name=")>=0);
|
||||
}
|
||||
|
||||
public void testRunNotSupported() throws Exception {
|
||||
try {
|
||||
job.execute(null);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// expected
|
||||
String message = e.getMessage();
|
||||
assertTrue("Message should contain JobSupport: "+message, message.contains("JobSupport"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,90 +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.launch.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.execution.launch.support.ExitCodeMapper;
|
||||
import org.springframework.batch.execution.launch.support.SimpleJvmExitCodeMapper;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class SimpleJvmExitCodeMapperTests extends TestCase {
|
||||
|
||||
private SimpleJvmExitCodeMapper ecm;
|
||||
private SimpleJvmExitCodeMapper ecm2;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
ecm = new SimpleJvmExitCodeMapper();
|
||||
Map ecmMap = new HashMap();
|
||||
ecmMap.put("MY_CUSTOM_CODE", new Integer(3));
|
||||
ecm.setMapping(ecmMap);
|
||||
|
||||
ecm2 = new SimpleJvmExitCodeMapper();
|
||||
Map ecm2Map = new HashMap();
|
||||
ecm2Map.put(ExitStatus.FINISHED.getExitCode(), new Integer(-1));
|
||||
ecm2Map.put(ExitStatus.FAILED.getExitCode(), new Integer(-2));
|
||||
ecm2Map.put(ExitCodeMapper.JOB_NOT_PROVIDED, new Integer(-3));
|
||||
ecm2Map.put(ExitCodeMapper.NO_SUCH_JOB, new Integer(-3));
|
||||
ecm2.setMapping(ecm2Map);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithpPredefinedCodes() {
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitStatus.FINISHED.getExitCode()),
|
||||
ExitCodeMapper.JVM_EXITCODE_COMPLETED);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitStatus.FAILED.getExitCode()),
|
||||
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED),
|
||||
ExitCodeMapper.JVM_EXITCODE_JOB_ERROR);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitCodeMapper.NO_SUCH_JOB),
|
||||
ExitCodeMapper.JVM_EXITCODE_JOB_ERROR);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithPredefinedCodesOverridden() {
|
||||
System.out.println(ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()));
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()), -1);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitStatus.FAILED.getExitCode()), -2);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), -3);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitCodeMapper.NO_SUCH_JOB), -3);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithCustomCode() {
|
||||
assertEquals(ecm.getExitCode("MY_CUSTOM_CODE"),3);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithDefaultCode() {
|
||||
assertEquals(
|
||||
ecm.getExitCode("UNDEFINED_CUSTOM_CODE"),
|
||||
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.launch.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.execution.launch.support.ExitCodeMapper;
|
||||
import org.springframework.batch.execution.launch.support.SimpleJvmExitCodeMapper;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class SimpleJvmExitCodeMapperTests extends TestCase {
|
||||
|
||||
private SimpleJvmExitCodeMapper ecm;
|
||||
private SimpleJvmExitCodeMapper ecm2;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
ecm = new SimpleJvmExitCodeMapper();
|
||||
Map ecmMap = new HashMap();
|
||||
ecmMap.put("MY_CUSTOM_CODE", new Integer(3));
|
||||
ecm.setMapping(ecmMap);
|
||||
|
||||
ecm2 = new SimpleJvmExitCodeMapper();
|
||||
Map ecm2Map = new HashMap();
|
||||
ecm2Map.put(ExitStatus.FINISHED.getExitCode(), new Integer(-1));
|
||||
ecm2Map.put(ExitStatus.FAILED.getExitCode(), new Integer(-2));
|
||||
ecm2Map.put(ExitCodeMapper.JOB_NOT_PROVIDED, new Integer(-3));
|
||||
ecm2Map.put(ExitCodeMapper.NO_SUCH_JOB, new Integer(-3));
|
||||
ecm2.setMapping(ecm2Map);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithpPredefinedCodes() {
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitStatus.FINISHED.getExitCode()),
|
||||
ExitCodeMapper.JVM_EXITCODE_COMPLETED);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitStatus.FAILED.getExitCode()),
|
||||
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED),
|
||||
ExitCodeMapper.JVM_EXITCODE_JOB_ERROR);
|
||||
assertEquals(
|
||||
ecm.getExitCode(ExitCodeMapper.NO_SUCH_JOB),
|
||||
ExitCodeMapper.JVM_EXITCODE_JOB_ERROR);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithPredefinedCodesOverridden() {
|
||||
System.out.println(ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()));
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()), -1);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitStatus.FAILED.getExitCode()), -2);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), -3);
|
||||
assertEquals(
|
||||
ecm2.getExitCode(ExitCodeMapper.NO_SUCH_JOB), -3);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithCustomCode() {
|
||||
assertEquals(ecm.getExitCode("MY_CUSTOM_CODE"),3);
|
||||
}
|
||||
|
||||
public void testGetExitCodeWithDefaultCode() {
|
||||
assertEquals(
|
||||
ecm.getExitCode("UNDEFINED_CUSTOM_CODE"),
|
||||
ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
package org.springframework.batch.execution.launch.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.execution.launch.JobLauncher;
|
||||
|
||||
/**
|
||||
* Mock Job Launcher. Normally, something like EasyMock would
|
||||
* be used to mock an interface, however, because of the nature
|
||||
* of launching a batch job from the command line, the mocked
|
||||
* class cannot be injected.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class StubJobLauncher implements JobLauncher {
|
||||
|
||||
public static final int RUN_NO_ARGS = 0;
|
||||
public static final int RUN_JOB_NAME = 1;
|
||||
public static final int RUN_JOB_IDENTIFIER =2 ;
|
||||
|
||||
private int lastRunCalled = RUN_NO_ARGS;
|
||||
private JobExecution returnValue = null;
|
||||
|
||||
private boolean isRunning = false;
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
public JobExecution run(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException {
|
||||
lastRunCalled = RUN_JOB_IDENTIFIER;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
public void setReturnValue(JobExecution returnValue){
|
||||
this.returnValue = returnValue;
|
||||
}
|
||||
|
||||
public void setIsRunning(boolean isRunning){
|
||||
this.isRunning = isRunning;
|
||||
}
|
||||
|
||||
public int getLastRunCalled(){
|
||||
return lastRunCalled;
|
||||
}
|
||||
}
|
||||
package org.springframework.batch.execution.launch.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.execution.launch.JobLauncher;
|
||||
|
||||
/**
|
||||
* Mock Job Launcher. Normally, something like EasyMock would
|
||||
* be used to mock an interface, however, because of the nature
|
||||
* of launching a batch job from the command line, the mocked
|
||||
* class cannot be injected.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class StubJobLauncher implements JobLauncher {
|
||||
|
||||
public static final int RUN_NO_ARGS = 0;
|
||||
public static final int RUN_JOB_NAME = 1;
|
||||
public static final int RUN_JOB_IDENTIFIER =2 ;
|
||||
|
||||
private int lastRunCalled = RUN_NO_ARGS;
|
||||
private JobExecution returnValue = null;
|
||||
|
||||
private boolean isRunning = false;
|
||||
|
||||
public boolean isRunning() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
public JobExecution run(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException {
|
||||
lastRunCalled = RUN_JOB_IDENTIFIER;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
public void setReturnValue(JobExecution returnValue){
|
||||
this.returnValue = returnValue;
|
||||
}
|
||||
|
||||
public void setIsRunning(boolean isRunning){
|
||||
this.isRunning = isRunning;
|
||||
}
|
||||
|
||||
public int getLastRunCalled(){
|
||||
return lastRunCalled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +1,224 @@
|
||||
/*
|
||||
* 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.Date;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Tests for step persistence (StepInstanceDao and StepExecutionDao). 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
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected JobInstanceDao jobInstanceDao;
|
||||
|
||||
protected StepExecutionDao stepExecutionDao;
|
||||
|
||||
protected JobExecutionDao jobExecutionDao;
|
||||
|
||||
protected JobInstance jobInstance;
|
||||
|
||||
protected Step step1;
|
||||
|
||||
protected Step step2;
|
||||
|
||||
protected StepExecution stepExecution;
|
||||
|
||||
protected JobExecution jobExecution;
|
||||
|
||||
protected JobParameters jobParameters = new JobParameters();
|
||||
|
||||
protected ExecutionContext executionContext;
|
||||
|
||||
public void setJobInstanceDao(JobInstanceDao jobInstanceDao) {
|
||||
this.jobInstanceDao = jobInstanceDao;
|
||||
}
|
||||
|
||||
public void setStepExecutionDao(StepExecutionDao stepExecutionDao) {
|
||||
this.stepExecutionDao = stepExecutionDao;
|
||||
}
|
||||
|
||||
public void setJobExecutionDao(JobExecutionDao jobExecutionDao) {
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
}
|
||||
|
||||
/*
|
||||
* (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 {
|
||||
Job job = new JobSupport("TestJob");
|
||||
jobInstance = jobInstanceDao.createJobInstance(job, jobParameters);
|
||||
step1 = new StepSupport("TestStep1");
|
||||
step2 = new StepSupport("TestStep2");
|
||||
jobExecution = new JobExecution(jobInstance);
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
|
||||
stepExecution = new StepExecution(step1, jobExecution, new Long(1));
|
||||
stepExecution.setStatus(BatchStatus.STARTED);
|
||||
stepExecution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
|
||||
executionContext = new ExecutionContext();
|
||||
executionContext.putString("1", "testString1");
|
||||
executionContext.putString("2", "testString2");
|
||||
executionContext.putLong("3", 3);
|
||||
executionContext.putDouble("4", 4.4);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testVersionIsNotNullForStepExecution() throws Exception {
|
||||
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where STEP_EXECUTION_ID="
|
||||
+ stepExecution.getId());
|
||||
assertEquals(0, version);
|
||||
}
|
||||
|
||||
public void testUpdateStepWithExecutionContext() {
|
||||
stepExecution.setExecutionContext(executionContext);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, tempAttributes);
|
||||
}
|
||||
|
||||
public void testSaveStepExecution() {
|
||||
StepExecution execution = new StepExecution(step2, jobExecution, null);
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
execution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.saveStepExecution(execution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(execution, retrievedExecution);
|
||||
assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testSaveStepExecutionAndExecutionContext() {
|
||||
StepExecution execution = new StepExecution(step2, jobExecution, null);
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
execution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
execution.setExecutionContext(executionContext);
|
||||
execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.saveStepExecution(execution);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(execution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(execution, retrievedExecution);
|
||||
assertEquals(execution.getExecutionContext().getString("1"), retrievedExecution.getExecutionContext().getString("1"));
|
||||
assertEquals(execution.getExecutionContext().getLong("3"), retrievedExecution.getExecutionContext().getLong("3"));
|
||||
assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testUpdateStepExecution() {
|
||||
|
||||
stepExecution.setStatus(BatchStatus.COMPLETED);
|
||||
stepExecution.setEndTime(new Date(System.currentTimeMillis()));
|
||||
stepExecution.setCommitCount(5);
|
||||
stepExecution.setTaskCount(5);
|
||||
stepExecution.setExecutionContext(new ExecutionContext());
|
||||
stepExecution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step1);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(stepExecution, retrievedExecution);
|
||||
assertEquals(stepExecution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionWithNullId() {
|
||||
StepExecution stepExecution = new StepExecution(new StepSupport("testStep"), null, null);
|
||||
try {
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionVersion() throws Exception {
|
||||
int before = stepExecution.getVersion().intValue();
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
int after = stepExecution.getVersion().intValue();
|
||||
assertEquals("StepExecution version not updated", before + 1, after);
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionOptimisticLocking() throws Exception {
|
||||
stepExecution.incrementVersion(); // not really allowed outside dao
|
||||
// code
|
||||
try {
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
fail("Expected OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException e) {
|
||||
// expected
|
||||
assertTrue("Exception message should contain step execution id: " + e.getMessage(), e.getMessage().indexOf(
|
||||
"" + stepExecution.getId()) >= 0);
|
||||
assertTrue("Exception message should contain step execution version: " + e.getMessage(), e.getMessage()
|
||||
.indexOf("" + stepExecution.getVersion()) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaveExecutionContext(){
|
||||
|
||||
stepExecution.setExecutionContext(executionContext);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, attributes);
|
||||
executionContext.putString("newString", "newString");
|
||||
executionContext.putLong("newLong", 1);
|
||||
executionContext.putDouble("newDouble", 2.5);
|
||||
executionContext.put("newSerializable", "serializableValue");
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
attributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, attributes);
|
||||
}
|
||||
|
||||
public void testGetStepExecution() {
|
||||
assertEquals(stepExecution, stepExecutionDao.getStepExecution(jobExecution, step1));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.Date;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Tests for step persistence (StepInstanceDao and StepExecutionDao). 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
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected JobInstanceDao jobInstanceDao;
|
||||
|
||||
protected StepExecutionDao stepExecutionDao;
|
||||
|
||||
protected JobExecutionDao jobExecutionDao;
|
||||
|
||||
protected JobInstance jobInstance;
|
||||
|
||||
protected Step step1;
|
||||
|
||||
protected Step step2;
|
||||
|
||||
protected StepExecution stepExecution;
|
||||
|
||||
protected JobExecution jobExecution;
|
||||
|
||||
protected JobParameters jobParameters = new JobParameters();
|
||||
|
||||
protected ExecutionContext executionContext;
|
||||
|
||||
public void setJobInstanceDao(JobInstanceDao jobInstanceDao) {
|
||||
this.jobInstanceDao = jobInstanceDao;
|
||||
}
|
||||
|
||||
public void setStepExecutionDao(StepExecutionDao stepExecutionDao) {
|
||||
this.stepExecutionDao = stepExecutionDao;
|
||||
}
|
||||
|
||||
public void setJobExecutionDao(JobExecutionDao jobExecutionDao) {
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
}
|
||||
|
||||
/*
|
||||
* (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 {
|
||||
Job job = new JobSupport("TestJob");
|
||||
jobInstance = jobInstanceDao.createJobInstance(job, jobParameters);
|
||||
step1 = new StepSupport("TestStep1");
|
||||
step2 = new StepSupport("TestStep2");
|
||||
jobExecution = new JobExecution(jobInstance);
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
|
||||
stepExecution = new StepExecution(step1, jobExecution, new Long(1));
|
||||
stepExecution.setStatus(BatchStatus.STARTED);
|
||||
stepExecution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
|
||||
executionContext = new ExecutionContext();
|
||||
executionContext.putString("1", "testString1");
|
||||
executionContext.putString("2", "testString2");
|
||||
executionContext.putLong("3", 3);
|
||||
executionContext.putDouble("4", 4.4);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testVersionIsNotNullForStepExecution() throws Exception {
|
||||
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where STEP_EXECUTION_ID="
|
||||
+ stepExecution.getId());
|
||||
assertEquals(0, version);
|
||||
}
|
||||
|
||||
public void testUpdateStepWithExecutionContext() {
|
||||
stepExecution.setExecutionContext(executionContext);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, tempAttributes);
|
||||
}
|
||||
|
||||
public void testSaveStepExecution() {
|
||||
StepExecution execution = new StepExecution(step2, jobExecution, null);
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
execution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.saveStepExecution(execution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(execution, retrievedExecution);
|
||||
assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testSaveStepExecutionAndExecutionContext() {
|
||||
StepExecution execution = new StepExecution(step2, jobExecution, null);
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
execution.setStartTime(new Date(System.currentTimeMillis()));
|
||||
execution.setExecutionContext(executionContext);
|
||||
execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.saveStepExecution(execution);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(execution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(execution, retrievedExecution);
|
||||
assertEquals(execution.getExecutionContext().getString("1"), retrievedExecution.getExecutionContext().getString("1"));
|
||||
assertEquals(execution.getExecutionContext().getLong("3"), retrievedExecution.getExecutionContext().getLong("3"));
|
||||
assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testUpdateStepExecution() {
|
||||
|
||||
stepExecution.setStatus(BatchStatus.COMPLETED);
|
||||
stepExecution.setEndTime(new Date(System.currentTimeMillis()));
|
||||
stepExecution.setCommitCount(5);
|
||||
stepExecution.setTaskCount(5);
|
||||
stepExecution.setExecutionContext(new ExecutionContext());
|
||||
stepExecution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION,
|
||||
"java.lang.Exception"));
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step1);
|
||||
assertNotNull(retrievedExecution);
|
||||
assertEquals(stepExecution, retrievedExecution);
|
||||
assertEquals(stepExecution.getExitStatus(), retrievedExecution.getExitStatus());
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionWithNullId() {
|
||||
StepExecution stepExecution = new StepExecution(new StepSupport("testStep"), null, null);
|
||||
try {
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
fail("Expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionVersion() throws Exception {
|
||||
int before = stepExecution.getVersion().intValue();
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
int after = stepExecution.getVersion().intValue();
|
||||
assertEquals("StepExecution version not updated", before + 1, after);
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionOptimisticLocking() throws Exception {
|
||||
stepExecution.incrementVersion(); // not really allowed outside dao
|
||||
// code
|
||||
try {
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
fail("Expected OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException e) {
|
||||
// expected
|
||||
assertTrue("Exception message should contain step execution id: " + e.getMessage(), e.getMessage().indexOf(
|
||||
"" + stepExecution.getId()) >= 0);
|
||||
assertTrue("Exception message should contain step execution version: " + e.getMessage(), e.getMessage()
|
||||
.indexOf("" + stepExecution.getVersion()) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaveExecutionContext(){
|
||||
|
||||
stepExecution.setExecutionContext(executionContext);
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, attributes);
|
||||
executionContext.putString("newString", "newString");
|
||||
executionContext.putLong("newLong", 1);
|
||||
executionContext.putDouble("newDouble", 2.5);
|
||||
executionContext.put("newSerializable", "serializableValue");
|
||||
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
|
||||
attributes = stepExecutionDao.findExecutionContext(stepExecution);
|
||||
assertEquals(executionContext, attributes);
|
||||
}
|
||||
|
||||
public void testGetStepExecution() {
|
||||
assertEquals(stepExecution, stepExecutionDao.getStepExecution(jobExecution, step1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
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.domain.JobParameters;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JdbcJobDaoQueryTests extends TestCase {
|
||||
|
||||
JdbcJobExecutionDao jobExecutionDao;
|
||||
|
||||
List list = new ArrayList();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
jobExecutionDao = new JdbcJobExecutionDao();
|
||||
jobExecutionDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() {
|
||||
|
||||
public int nextIntValue() throws DataAccessException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long nextLongValue() throws DataAccessException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String nextStringValue() throws DataAccessException {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
jobExecutionDao.setTablePrefix("FOO_");
|
||||
jobExecutionDao.setJdbcTemplate(new JdbcTemplate() {
|
||||
public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
list.add(sql);
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
JobExecution jobExecution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport(
|
||||
"testJob")));
|
||||
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
assertEquals(1, list.size());
|
||||
String query = (String) list.get(0);
|
||||
assertTrue("Query did not contain FOO_:" + query, query.indexOf("FOO_") >= 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.execution.repository.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.domain.JobParameters;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JdbcJobDaoQueryTests extends TestCase {
|
||||
|
||||
JdbcJobExecutionDao jobExecutionDao;
|
||||
|
||||
List list = new ArrayList();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
jobExecutionDao = new JdbcJobExecutionDao();
|
||||
jobExecutionDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() {
|
||||
|
||||
public int nextIntValue() throws DataAccessException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long nextLongValue() throws DataAccessException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String nextStringValue() throws DataAccessException {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
jobExecutionDao.setTablePrefix("FOO_");
|
||||
jobExecutionDao.setJdbcTemplate(new JdbcTemplate() {
|
||||
public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
list.add(sql);
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
JobExecution jobExecution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport(
|
||||
"testJob")));
|
||||
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
assertEquals(1, list.size());
|
||||
String query = (String) list.get(0);
|
||||
assertTrue("Query did not contain FOO_:" + query, query.indexOf("FOO_") >= 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class JdbcJobDaoTests extends AbstractJobDaoTests {
|
||||
|
||||
public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String ";
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcJobInstanceDao) jobInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testUpdateJobExecutionWithLongExitCode() {
|
||||
|
||||
assertTrue(LONG_STRING.length() > 250);
|
||||
jobExecution.setExitStatus(ExitStatus.FINISHED
|
||||
.addExitDescription(LONG_STRING));
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
|
||||
List executions = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?",
|
||||
new Object[] { jobInstance.getId() });
|
||||
assertEquals(1, executions.size());
|
||||
assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0))
|
||||
.get("EXIT_MESSAGE"));
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class JdbcJobDaoTests extends AbstractJobDaoTests {
|
||||
|
||||
public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String ";
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcJobInstanceDao) jobInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testUpdateJobExecutionWithLongExitCode() {
|
||||
|
||||
assertTrue(LONG_STRING.length() > 250);
|
||||
jobExecution.setExitStatus(ExitStatus.FINISHED
|
||||
.addExitDescription(LONG_STRING));
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
|
||||
List executions = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?",
|
||||
new Object[] { jobInstance.getId() });
|
||||
assertEquals(1, executions.size());
|
||||
assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0))
|
||||
.get("EXIT_MESSAGE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
|
||||
/**
|
||||
* Unit Test of SqlStepDao that only tests prefix matching. A
|
||||
* separate test is needed because all other tests hit hsql,
|
||||
* while this test needs to mock JdbcTemplate to analyze the
|
||||
* Sql passed in.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class JdbcStepDaoPrefixTests extends TestCase {
|
||||
|
||||
private JdbcStepExecutionDao stepExecutionDao;
|
||||
|
||||
MockJdbcTemplate jdbcTemplate = new MockJdbcTemplate();
|
||||
|
||||
JobInstance job = new JobInstance(new Long(1), new JobParameters(), new JobSupport("testJob"));
|
||||
Step step = new StepSupport("foo");
|
||||
StepExecution stepExecution = new StepExecution(step, new JobExecution(job), null);
|
||||
|
||||
MockControl stepExecutionIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class);
|
||||
DataFieldMaxValueIncrementer stepExecutionIncrementer;
|
||||
MockControl stepIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class);
|
||||
DataFieldMaxValueIncrementer stepIncrementer;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
stepExecutionDao = new JdbcStepExecutionDao();
|
||||
stepExecutionIncrementer = (DataFieldMaxValueIncrementer)stepExecutionIncrementerControl.getMock();
|
||||
stepIncrementer = (DataFieldMaxValueIncrementer)stepIncrementerControl.getMock();
|
||||
|
||||
stepExecutionDao.setJdbcTemplate(jdbcTemplate);
|
||||
stepExecutionDao.setStepExecutionIncrementer(stepExecutionIncrementer);
|
||||
stepExecution.setId(new Long(1));
|
||||
stepExecution.incrementVersion();
|
||||
|
||||
}
|
||||
|
||||
public void testModifiedUpdateStepExecution(){
|
||||
stepExecutionDao.setTablePrefix("FOO_");
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testModifiedSaveStepExecution(){
|
||||
stepExecutionDao.setTablePrefix("FOO_");
|
||||
stepExecutionIncrementer.nextLongValue();
|
||||
stepExecutionIncrementerControl.setReturnValue(1);
|
||||
stepExecutionIncrementerControl.replay();
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testDefaultSaveStepExecution(){
|
||||
stepExecutionIncrementer.nextLongValue();
|
||||
stepExecutionIncrementerControl.setReturnValue(1);
|
||||
stepExecutionIncrementerControl.replay();
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testDefaultUpdateStepExecution(){
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
private class MockJdbcTemplate extends JdbcTemplate {
|
||||
|
||||
private String sql;
|
||||
|
||||
public int update(String sql, Object[] args) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public List query(String sql, Object[] args, RowMapper rowMapper) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSqlStatement() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
import org.springframework.batch.execution.step.StepSupport;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
|
||||
/**
|
||||
* Unit Test of SqlStepDao that only tests prefix matching. A
|
||||
* separate test is needed because all other tests hit hsql,
|
||||
* while this test needs to mock JdbcTemplate to analyze the
|
||||
* Sql passed in.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class JdbcStepDaoPrefixTests extends TestCase {
|
||||
|
||||
private JdbcStepExecutionDao stepExecutionDao;
|
||||
|
||||
MockJdbcTemplate jdbcTemplate = new MockJdbcTemplate();
|
||||
|
||||
JobInstance job = new JobInstance(new Long(1), new JobParameters(), new JobSupport("testJob"));
|
||||
Step step = new StepSupport("foo");
|
||||
StepExecution stepExecution = new StepExecution(step, new JobExecution(job), null);
|
||||
|
||||
MockControl stepExecutionIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class);
|
||||
DataFieldMaxValueIncrementer stepExecutionIncrementer;
|
||||
MockControl stepIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class);
|
||||
DataFieldMaxValueIncrementer stepIncrementer;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
stepExecutionDao = new JdbcStepExecutionDao();
|
||||
stepExecutionIncrementer = (DataFieldMaxValueIncrementer)stepExecutionIncrementerControl.getMock();
|
||||
stepIncrementer = (DataFieldMaxValueIncrementer)stepIncrementerControl.getMock();
|
||||
|
||||
stepExecutionDao.setJdbcTemplate(jdbcTemplate);
|
||||
stepExecutionDao.setStepExecutionIncrementer(stepExecutionIncrementer);
|
||||
stepExecution.setId(new Long(1));
|
||||
stepExecution.incrementVersion();
|
||||
|
||||
}
|
||||
|
||||
public void testModifiedUpdateStepExecution(){
|
||||
stepExecutionDao.setTablePrefix("FOO_");
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testModifiedSaveStepExecution(){
|
||||
stepExecutionDao.setTablePrefix("FOO_");
|
||||
stepExecutionIncrementer.nextLongValue();
|
||||
stepExecutionIncrementerControl.setReturnValue(1);
|
||||
stepExecutionIncrementerControl.replay();
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testDefaultSaveStepExecution(){
|
||||
stepExecutionIncrementer.nextLongValue();
|
||||
stepExecutionIncrementerControl.setReturnValue(1);
|
||||
stepExecutionIncrementerControl.replay();
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
public void testDefaultUpdateStepExecution(){
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1);
|
||||
}
|
||||
|
||||
private class MockJdbcTemplate extends JdbcTemplate {
|
||||
|
||||
private String sql;
|
||||
|
||||
public int update(String sql, Object[] args) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public List query(String sql, Object[] args, RowMapper rowMapper) throws DataAccessException {
|
||||
this.sql = sql;
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSqlStatement() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class JdbcStepDaoTests extends AbstractStepDaoTests {
|
||||
|
||||
private static final String LONG_STRING = JdbcJobDaoTests.LONG_STRING;
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
// ((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix("FOO_");
|
||||
// ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix("FOO_");
|
||||
// try {
|
||||
// testCreateStep();
|
||||
// fail("Expected DataAccessException");
|
||||
// } catch (DataAccessException e) {
|
||||
// // expected
|
||||
// }
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionWithLongExitCode() {
|
||||
|
||||
assertTrue(LONG_STRING.length()>250);
|
||||
stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING));
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
|
||||
List executions = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_STEP_EXECUTION where STEP_NAME=?",
|
||||
new Object[] { step1.getName() });
|
||||
assertEquals(1, executions.size());
|
||||
assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0))
|
||||
.get("EXIT_MESSAGE"));
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
public class JdbcStepDaoTests extends AbstractStepDaoTests {
|
||||
|
||||
private static final String LONG_STRING = JdbcJobDaoTests.LONG_STRING;
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
// ((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix("FOO_");
|
||||
// ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix("FOO_");
|
||||
// try {
|
||||
// testCreateStep();
|
||||
// fail("Expected DataAccessException");
|
||||
// } catch (DataAccessException e) {
|
||||
// // expected
|
||||
// }
|
||||
}
|
||||
|
||||
public void testUpdateStepExecutionWithLongExitCode() {
|
||||
|
||||
assertTrue(LONG_STRING.length()>250);
|
||||
stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING));
|
||||
stepExecutionDao.updateStepExecution(stepExecution);
|
||||
|
||||
List executions = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_STEP_EXECUTION where STEP_NAME=?",
|
||||
new Object[] { step1.getName() });
|
||||
assertEquals(1, executions.size());
|
||||
assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0))
|
||||
.get("EXIT_MESSAGE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.JobParameters;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
public class MapJobExecutionDaoTests extends TestCase {
|
||||
|
||||
JobExecutionDao dao = new MapJobExecutionDao();
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("execTestJob"));
|
||||
|
||||
JobExecution execution = new JobExecution(jobInstance);
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
MapJobExecutionDao.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save and find a job execution.
|
||||
*/
|
||||
public void testSaveAndFind() {
|
||||
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
List executions = dao.findJobExecutions(jobInstance);
|
||||
assertTrue(executions.size() == 1);
|
||||
assertEquals(execution, executions.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saving sets id to the entity.
|
||||
*/
|
||||
public void testSaveAddsId() {
|
||||
|
||||
assertNull(execution.getId());
|
||||
dao.saveJobExecution(execution);
|
||||
assertNotNull(execution.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution count increases by one with every save for the same job
|
||||
* instance.
|
||||
*/
|
||||
public void testGetExecutionCount() {
|
||||
|
||||
JobExecution exec1 = new JobExecution(jobInstance);
|
||||
JobExecution exec2 = new JobExecution(jobInstance);
|
||||
|
||||
dao.saveJobExecution(exec1);
|
||||
assertEquals(1, dao.getJobExecutionCount(jobInstance));
|
||||
|
||||
dao.saveJobExecution(exec2);
|
||||
assertEquals(2, dao.getJobExecutionCount(jobInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update and retrieve job execution - check attributes have changed as
|
||||
* expected.
|
||||
*/
|
||||
public void testUpdateExecution() {
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
execution.setStatus(BatchStatus.COMPLETED);
|
||||
dao.updateJobExecution(execution);
|
||||
|
||||
JobExecution updated = (JobExecution) dao.findJobExecutions(jobInstance).get(0);
|
||||
assertEquals(execution, updated);
|
||||
assertEquals(BatchStatus.COMPLETED, updated.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the execution with most recent start time is returned
|
||||
*/
|
||||
public void testGetLastExecution() {
|
||||
JobExecution exec1 = new JobExecution(jobInstance);
|
||||
exec1.setStartTime(new Date(0));
|
||||
JobExecution exec2 = new JobExecution(jobInstance);
|
||||
exec2.setStartTime(new Date(1));
|
||||
|
||||
dao.saveJobExecution(exec1);
|
||||
dao.saveJobExecution(exec2);
|
||||
|
||||
assertEquals(exec2, dao.getLastJobExecution(jobInstance));
|
||||
}
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.JobParameters;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
public class MapJobExecutionDaoTests extends TestCase {
|
||||
|
||||
JobExecutionDao dao = new MapJobExecutionDao();
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("execTestJob"));
|
||||
|
||||
JobExecution execution = new JobExecution(jobInstance);
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
MapJobExecutionDao.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save and find a job execution.
|
||||
*/
|
||||
public void testSaveAndFind() {
|
||||
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
List executions = dao.findJobExecutions(jobInstance);
|
||||
assertTrue(executions.size() == 1);
|
||||
assertEquals(execution, executions.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saving sets id to the entity.
|
||||
*/
|
||||
public void testSaveAddsId() {
|
||||
|
||||
assertNull(execution.getId());
|
||||
dao.saveJobExecution(execution);
|
||||
assertNotNull(execution.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution count increases by one with every save for the same job
|
||||
* instance.
|
||||
*/
|
||||
public void testGetExecutionCount() {
|
||||
|
||||
JobExecution exec1 = new JobExecution(jobInstance);
|
||||
JobExecution exec2 = new JobExecution(jobInstance);
|
||||
|
||||
dao.saveJobExecution(exec1);
|
||||
assertEquals(1, dao.getJobExecutionCount(jobInstance));
|
||||
|
||||
dao.saveJobExecution(exec2);
|
||||
assertEquals(2, dao.getJobExecutionCount(jobInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update and retrieve job execution - check attributes have changed as
|
||||
* expected.
|
||||
*/
|
||||
public void testUpdateExecution() {
|
||||
execution.setStatus(BatchStatus.STARTED);
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
execution.setStatus(BatchStatus.COMPLETED);
|
||||
dao.updateJobExecution(execution);
|
||||
|
||||
JobExecution updated = (JobExecution) dao.findJobExecutions(jobInstance).get(0);
|
||||
assertEquals(execution, updated);
|
||||
assertEquals(BatchStatus.COMPLETED, updated.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the execution with most recent start time is returned
|
||||
*/
|
||||
public void testGetLastExecution() {
|
||||
JobExecution exec1 = new JobExecution(jobInstance);
|
||||
exec1.setStartTime(new Date(0));
|
||||
JobExecution exec2 = new JobExecution(jobInstance);
|
||||
exec2.setStartTime(new Date(1));
|
||||
|
||||
dao.saveJobExecution(exec1);
|
||||
dao.saveJobExecution(exec2);
|
||||
|
||||
assertEquals(exec2, dao.getLastJobExecution(jobInstance));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.JobParametersBuilder;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
public class MapJobInstanceDaoTests extends TestCase {
|
||||
|
||||
private JobInstanceDao dao = new MapJobInstanceDao();
|
||||
|
||||
private Job fooJob = new JobSupport("foo");
|
||||
|
||||
private JobParameters fooParams = new JobParametersBuilder().addString("fooKey", "fooValue").toJobParameters();
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
MapJobInstanceDao.clear();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
MapJobInstanceDao.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and retrieve a job instance.
|
||||
*/
|
||||
public void testCreateAndRetrieve() throws Exception {
|
||||
|
||||
JobInstance fooInstance = dao.createJobInstance(fooJob, fooParams);
|
||||
assertNotNull(fooInstance.getId());
|
||||
assertEquals(fooJob, fooInstance.getJob());
|
||||
assertEquals(fooParams, fooInstance.getJobParameters());
|
||||
|
||||
JobInstance retrievedInstance = dao.getJobInstance(fooJob, fooParams);
|
||||
assertEquals(fooInstance, retrievedInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trying to create instance twice for the same job+parameters causes error
|
||||
*/
|
||||
public void testCreateDuplicateInstance() {
|
||||
|
||||
dao.createJobInstance(fooJob, fooParams);
|
||||
|
||||
try {
|
||||
dao.createJobInstance(fooJob, fooParams);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.JobParametersBuilder;
|
||||
import org.springframework.batch.execution.job.JobSupport;
|
||||
|
||||
public class MapJobInstanceDaoTests extends TestCase {
|
||||
|
||||
private JobInstanceDao dao = new MapJobInstanceDao();
|
||||
|
||||
private Job fooJob = new JobSupport("foo");
|
||||
|
||||
private JobParameters fooParams = new JobParametersBuilder().addString("fooKey", "fooValue").toJobParameters();
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
MapJobInstanceDao.clear();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
MapJobInstanceDao.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and retrieve a job instance.
|
||||
*/
|
||||
public void testCreateAndRetrieve() throws Exception {
|
||||
|
||||
JobInstance fooInstance = dao.createJobInstance(fooJob, fooParams);
|
||||
assertNotNull(fooInstance.getId());
|
||||
assertEquals(fooJob, fooInstance.getJob());
|
||||
assertEquals(fooParams, fooInstance.getJobParameters());
|
||||
|
||||
JobInstance retrievedInstance = dao.getJobInstance(fooJob, fooParams);
|
||||
assertEquals(fooInstance, retrievedInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trying to create instance twice for the same job+parameters causes error
|
||||
*/
|
||||
public void testCreateDuplicateInstance() {
|
||||
|
||||
dao.createJobInstance(fooJob, fooParams);
|
||||
|
||||
try {
|
||||
dao.createJobInstance(fooJob, fooParams);
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* 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 org.springframework.batch.execution.repository.dao.NoSuchObjectException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class NoSuchBatchDomainObjectExceptionTests extends TestCase {
|
||||
|
||||
public void testCreateException() throws Exception {
|
||||
NoSuchObjectException e = new NoSuchObjectException("Foo");
|
||||
assertEquals("Foo", e.getMessage());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 org.springframework.batch.execution.repository.dao.NoSuchObjectException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class NoSuchBatchDomainObjectExceptionTests extends TestCase {
|
||||
|
||||
public void testCreateException() throws Exception {
|
||||
NoSuchObjectException e = new NoSuchObjectException("Foo");
|
||||
assertEquals("Foo", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,117 +1,117 @@
|
||||
/*
|
||||
* 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 org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
|
||||
/**
|
||||
* Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that
|
||||
* if no name is provided explicitly it will be inferred from the bean definition in Spring configuration.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StepSupport implements Step, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
private int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
private boolean allowStartIfComplete;
|
||||
|
||||
/**
|
||||
* Default constructor for {@link StepSupport}.
|
||||
*/
|
||||
public StepSupport() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
public StepSupport(String string) {
|
||||
super();
|
||||
this.name = string;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the
|
||||
* name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent
|
||||
* bean has a name, then its children need an explicit name as well, otherwise they will not be unique.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
if (this.name == null) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property. Always overrides the default value if this object is a Spring bean.
|
||||
*
|
||||
* @see #setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getStartLimit() {
|
||||
return this.startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
public boolean isAllowStartIfComplete() {
|
||||
return this.allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported but provided so that tests can easily create a step.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*
|
||||
* @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot process a StepExecution. Use a smarter subclass of StepSupport.");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.io.exception.InfrastructureException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
|
||||
/**
|
||||
* Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that
|
||||
* if no name is provided explicitly it will be inferred from the bean definition in Spring configuration.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class StepSupport implements Step, BeanNameAware {
|
||||
|
||||
private String name;
|
||||
|
||||
private int startLimit = Integer.MAX_VALUE;
|
||||
|
||||
private boolean allowStartIfComplete;
|
||||
|
||||
/**
|
||||
* Default constructor for {@link StepSupport}.
|
||||
*/
|
||||
public StepSupport() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
public StepSupport(String string) {
|
||||
super();
|
||||
this.name = string;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the
|
||||
* name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent
|
||||
* bean has a name, then its children need an explicit name as well, otherwise they will not be unique.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setBeanName(String name) {
|
||||
if (this.name == null) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name property. Always overrides the default value if this object is a Spring bean.
|
||||
*
|
||||
* @see #setBeanName(java.lang.String)
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getStartLimit() {
|
||||
return this.startLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the startLimit.
|
||||
*
|
||||
* @param startLimit the startLimit to set
|
||||
*/
|
||||
public void setStartLimit(int startLimit) {
|
||||
this.startLimit = startLimit;
|
||||
}
|
||||
|
||||
public boolean isAllowStartIfComplete() {
|
||||
return this.allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the shouldAllowStartIfComplete.
|
||||
*
|
||||
* @param allowStartIfComplete the shouldAllowStartIfComplete to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported but provided so that tests can easily create a step.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*
|
||||
* @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot process a StepExecution. Use a smarter subclass of StepSupport.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,189 +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.step.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.BatchListener;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.listener.ItemListenerSupport;
|
||||
import org.springframework.batch.execution.job.SimpleJob;
|
||||
import org.springframework.batch.execution.repository.SimpleJobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.execution.step.AbstractStep;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.reader.ListItemReader;
|
||||
import org.springframework.batch.item.writer.AbstractItemWriter;
|
||||
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;
|
||||
|
||||
public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
|
||||
private List recovered = new ArrayList();
|
||||
|
||||
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(),
|
||||
new MapStepExecutionDao());
|
||||
|
||||
private List processed = new ArrayList();
|
||||
|
||||
private ItemWriter processor = new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
processed.add((String) data);
|
||||
}
|
||||
};
|
||||
|
||||
private ItemReader provider;
|
||||
|
||||
private SimpleJob job = new SimpleJob();;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
job.setJobRepository(repository);
|
||||
MapJobInstanceDao.clear();
|
||||
MapJobExecutionDao.clear();
|
||||
MapStepExecutionDao.clear();
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String arg) throws Exception {
|
||||
return getStep(new String[] { arg });
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String arg0, String arg1) throws Exception {
|
||||
return getStep(new String[] { arg0, arg1 });
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String[] args) throws Exception {
|
||||
DefaultStepFactoryBean factory = new DefaultStepFactoryBean();
|
||||
|
||||
List items = TransactionAwareProxyFactory.createTransactionalList();
|
||||
items.addAll(Arrays.asList(args));
|
||||
provider = new ListItemReader(items);
|
||||
|
||||
factory.setItemReader(provider);
|
||||
factory.setItemWriter(processor);
|
||||
factory.setJobRepository(repository);
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
factory.setBeanName("stepName");
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void testSimpleJob() throws Exception {
|
||||
|
||||
job.setSteps(new ArrayList());
|
||||
AbstractStep step = (AbstractStep) getStep("foo", "bar").getObject();
|
||||
step.setName("step1");
|
||||
job.addStep(step);
|
||||
step = (AbstractStep) getStep("spam").getObject();
|
||||
step.setName("step2");
|
||||
job.addStep(step);
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
|
||||
job.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(3, processed.size());
|
||||
assertTrue(processed.contains("foo"));
|
||||
}
|
||||
|
||||
public void testSimpleJobWithItemListeners() throws Exception {
|
||||
|
||||
final List throwables = new ArrayList();
|
||||
|
||||
RepeatTemplate chunkOperations = new RepeatTemplate();
|
||||
// Always handle the exception a check it is the right one...
|
||||
chunkOperations.setExceptionHandler(new ExceptionHandler() {
|
||||
public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException {
|
||||
throwables.add(throwable);
|
||||
assertEquals("Error!", throwable.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 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)...
|
||||
*/
|
||||
DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" });
|
||||
|
||||
factory.setItemWriter(new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
throw new RuntimeException("Error!");
|
||||
}
|
||||
});
|
||||
factory.setListeners(new BatchListener[] { new ItemListenerSupport() {
|
||||
public void onReadError(Exception ex) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
|
||||
public void onWriteError(Exception ex, Object item) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
} });
|
||||
|
||||
ItemOrientedStep step = (ItemOrientedStep) factory.getObject();
|
||||
step.setChunkOperations(chunkOperations);
|
||||
|
||||
job.setSteps(Collections.singletonList(step));
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
job.execute(jobExecution);
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(0, processed.size());
|
||||
// provider should be exhausted
|
||||
assertEquals(null, provider.read());
|
||||
assertEquals(3, recovered.size());
|
||||
}
|
||||
|
||||
public void testExceptionTerminates() throws Exception {
|
||||
DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" });
|
||||
factory.setBeanName("exceptionStep");
|
||||
factory.setItemWriter(new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
throw new RuntimeException("Foo");
|
||||
}
|
||||
});
|
||||
ItemOrientedStep step = (ItemOrientedStep) factory.getObject();
|
||||
job.setSteps(Collections.singletonList(step));
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
try {
|
||||
job.execute(jobExecution);
|
||||
fail("Expected RuntimeException");
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
assertEquals("Foo", e.getMessage());
|
||||
// expected
|
||||
}
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.BatchListener;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.listener.ItemListenerSupport;
|
||||
import org.springframework.batch.execution.job.SimpleJob;
|
||||
import org.springframework.batch.execution.repository.SimpleJobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.execution.step.AbstractStep;
|
||||
import org.springframework.batch.execution.step.ItemOrientedStep;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.reader.ListItemReader;
|
||||
import org.springframework.batch.item.writer.AbstractItemWriter;
|
||||
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;
|
||||
|
||||
public class DefaultStepFactoryBeanTests extends TestCase {
|
||||
|
||||
private List recovered = new ArrayList();
|
||||
|
||||
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(),
|
||||
new MapStepExecutionDao());
|
||||
|
||||
private List processed = new ArrayList();
|
||||
|
||||
private ItemWriter processor = new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
processed.add((String) data);
|
||||
}
|
||||
};
|
||||
|
||||
private ItemReader provider;
|
||||
|
||||
private SimpleJob job = new SimpleJob();;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
job.setJobRepository(repository);
|
||||
MapJobInstanceDao.clear();
|
||||
MapJobExecutionDao.clear();
|
||||
MapStepExecutionDao.clear();
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String arg) throws Exception {
|
||||
return getStep(new String[] { arg });
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String arg0, String arg1) throws Exception {
|
||||
return getStep(new String[] { arg0, arg1 });
|
||||
}
|
||||
|
||||
private DefaultStepFactoryBean getStep(String[] args) throws Exception {
|
||||
DefaultStepFactoryBean factory = new DefaultStepFactoryBean();
|
||||
|
||||
List items = TransactionAwareProxyFactory.createTransactionalList();
|
||||
items.addAll(Arrays.asList(args));
|
||||
provider = new ListItemReader(items);
|
||||
|
||||
factory.setItemReader(provider);
|
||||
factory.setItemWriter(processor);
|
||||
factory.setJobRepository(repository);
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
factory.setBeanName("stepName");
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void testSimpleJob() throws Exception {
|
||||
|
||||
job.setSteps(new ArrayList());
|
||||
AbstractStep step = (AbstractStep) getStep("foo", "bar").getObject();
|
||||
step.setName("step1");
|
||||
job.addStep(step);
|
||||
step = (AbstractStep) getStep("spam").getObject();
|
||||
step.setName("step2");
|
||||
job.addStep(step);
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
|
||||
job.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(3, processed.size());
|
||||
assertTrue(processed.contains("foo"));
|
||||
}
|
||||
|
||||
public void testSimpleJobWithItemListeners() throws Exception {
|
||||
|
||||
final List throwables = new ArrayList();
|
||||
|
||||
RepeatTemplate chunkOperations = new RepeatTemplate();
|
||||
// Always handle the exception a check it is the right one...
|
||||
chunkOperations.setExceptionHandler(new ExceptionHandler() {
|
||||
public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException {
|
||||
throwables.add(throwable);
|
||||
assertEquals("Error!", throwable.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 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)...
|
||||
*/
|
||||
DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" });
|
||||
|
||||
factory.setItemWriter(new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
throw new RuntimeException("Error!");
|
||||
}
|
||||
});
|
||||
factory.setListeners(new BatchListener[] { new ItemListenerSupport() {
|
||||
public void onReadError(Exception ex) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
|
||||
public void onWriteError(Exception ex, Object item) {
|
||||
recovered.add(ex);
|
||||
}
|
||||
} });
|
||||
|
||||
ItemOrientedStep step = (ItemOrientedStep) factory.getObject();
|
||||
step.setChunkOperations(chunkOperations);
|
||||
|
||||
job.setSteps(Collections.singletonList(step));
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
job.execute(jobExecution);
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(0, processed.size());
|
||||
// provider should be exhausted
|
||||
assertEquals(null, provider.read());
|
||||
assertEquals(3, recovered.size());
|
||||
}
|
||||
|
||||
public void testExceptionTerminates() throws Exception {
|
||||
DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" });
|
||||
factory.setBeanName("exceptionStep");
|
||||
factory.setItemWriter(new AbstractItemWriter() {
|
||||
public void write(Object data) throws Exception {
|
||||
throw new RuntimeException("Foo");
|
||||
}
|
||||
});
|
||||
ItemOrientedStep step = (ItemOrientedStep) factory.getObject();
|
||||
job.setSteps(Collections.singletonList(step));
|
||||
|
||||
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
|
||||
try {
|
||||
job.execute(jobExecution);
|
||||
fail("Expected RuntimeException");
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
assertEquals("Foo", e.getMessage());
|
||||
// expected
|
||||
}
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
|
||||
/**
|
||||
* @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 JobExecution createJobExecution(Job jobConfiguration, JobParameters jobParameters) {
|
||||
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.core.repository.JobRepository#saveOrUpdateExecutionContext(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void saveOrUpdateExecutionContext(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) {
|
||||
}
|
||||
|
||||
public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getStepExecutionCount(JobInstance jobInstance, Step step) {
|
||||
// TODO Auto-generated method stub
|
||||
return 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.execution.step.support;
|
||||
|
||||
import org.springframework.batch.core.domain.Job;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.Step;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
|
||||
/**
|
||||
* @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 JobExecution createJobExecution(Job jobConfiguration, JobParameters jobParameters) {
|
||||
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.core.repository.JobRepository#saveOrUpdateExecutionContext(org.springframework.batch.core.domain.StepExecution)
|
||||
*/
|
||||
public void saveOrUpdateExecutionContext(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) {
|
||||
}
|
||||
|
||||
public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getStepExecutionCount(JobInstance jobInstance, Step step) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class SimpleExitStatusExceptionClassifierTests extends TestCase {
|
||||
|
||||
NullPointerException exception;
|
||||
|
||||
SimpleExitStatusExceptionClassifier classifier = new SimpleExitStatusExceptionClassifier();
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
exception = new NullPointerException();
|
||||
}
|
||||
|
||||
public void testClassifyForExitCode() {
|
||||
ExitStatus exitStatus = classifier.classifyForExitCode(exception);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
String description = exitStatus.getExitDescription();
|
||||
assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0);
|
||||
}
|
||||
|
||||
public void testClassify() {
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classify(exception);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
String description = exitStatus.getExitDescription();
|
||||
assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0);
|
||||
}
|
||||
|
||||
public void testGetDefault() {
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.getDefault();
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
assertEquals(exitStatus.getExitDescription(), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempting to classify a null throwable should lead to a blank description, not a
|
||||
* null pointer exception.
|
||||
*/
|
||||
public void testClassifyNullThrowable(){
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classify(null);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
assertEquals(exitStatus.getExitDescription(), "");
|
||||
}
|
||||
|
||||
public void testClassifyInterruptedException(){
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classifyForExitCode(new JobInterruptedException(""));
|
||||
assertEquals(exitStatus.getExitCode(), ExitStatusExceptionClassifier.JOB_INTERRUPTED);
|
||||
assertEquals(exitStatus.getExitDescription(),
|
||||
JobInterruptedException.class.getName());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class SimpleExitStatusExceptionClassifierTests extends TestCase {
|
||||
|
||||
NullPointerException exception;
|
||||
|
||||
SimpleExitStatusExceptionClassifier classifier = new SimpleExitStatusExceptionClassifier();
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
exception = new NullPointerException();
|
||||
}
|
||||
|
||||
public void testClassifyForExitCode() {
|
||||
ExitStatus exitStatus = classifier.classifyForExitCode(exception);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
String description = exitStatus.getExitDescription();
|
||||
assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0);
|
||||
}
|
||||
|
||||
public void testClassify() {
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classify(exception);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
String description = exitStatus.getExitDescription();
|
||||
assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0);
|
||||
}
|
||||
|
||||
public void testGetDefault() {
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.getDefault();
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
assertEquals(exitStatus.getExitDescription(), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempting to classify a null throwable should lead to a blank description, not a
|
||||
* null pointer exception.
|
||||
*/
|
||||
public void testClassifyNullThrowable(){
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classify(null);
|
||||
assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION");
|
||||
assertEquals(exitStatus.getExitDescription(), "");
|
||||
}
|
||||
|
||||
public void testClassifyInterruptedException(){
|
||||
ExitStatus exitStatus = (ExitStatus)classifier.classifyForExitCode(new JobInterruptedException(""));
|
||||
assertEquals(exitStatus.getExitCode(), ExitStatusExceptionClassifier.JOB_INTERRUPTED);
|
||||
assertEquals(exitStatus.getExitDescription(),
|
||||
JobInterruptedException.class.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy;
|
||||
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 (JobInterruptedException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("interrupt")>=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.execution.step.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInterruptedException;
|
||||
import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy;
|
||||
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 (JobInterruptedException e) {
|
||||
// expected
|
||||
assertTrue(e.getMessage().indexOf("interrupt")>=0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user