Rationalise BatchResourceFactoryBean and allow %{key}% values in replacement patterns for JobParameters
This commit is contained in:
@@ -17,8 +17,14 @@
|
||||
package org.springframework.batch.execution.resource;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.runtime.JobParametersFactory;
|
||||
import org.springframework.batch.execution.bootstrap.support.DefaultJobParametersFactory;
|
||||
import org.springframework.batch.execution.scope.StepContext;
|
||||
import org.springframework.batch.execution.scope.StepContextAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
@@ -40,14 +46,20 @@ import org.springframework.util.StringUtils;
|
||||
* If no pattern is passed in, then following default is used:
|
||||
*
|
||||
* <pre>
|
||||
* /%BATCH_ROOT%/job_data/%JOB_NAME%/%JOB_IDENTIFIER%-%STEP_NAME%.txt
|
||||
* data/%JOB_NAME%/%STEP_NAME%.txt
|
||||
* </pre>
|
||||
*
|
||||
* The %% variables are replaced with the corresponding bean property at run
|
||||
* time, when the factory method is executed. Note that the default pattern
|
||||
* starts with a forward slash "/", which means the root directory will be
|
||||
* interpreted as an absolute path if it too starts with "/" (because of the
|
||||
* implementation of the Spring Core Resource abstractions).<br/>
|
||||
* time, when the factory method is executed. To insert {@link JobParameters}
|
||||
* use a pattern with the parameter key surrounded by %%, e.g.
|
||||
*
|
||||
* <pre>
|
||||
* //home/jobs/data/%JOB_NAME%/%STEP_NAME%-%schedule.date%.txt
|
||||
* </pre>
|
||||
*
|
||||
* Note that the default pattern does not start with a separator. Because of the
|
||||
* implementation of the Spring Core Resource abstractions, it would need to
|
||||
* start with a double forward slash "//" to resolve to an absolute directory.<br/>
|
||||
*
|
||||
* It doesn't make much sense to use this factory unless it is step scoped, but
|
||||
* note that it is thread safe only if it is step scoped and its mutators are
|
||||
@@ -59,28 +71,36 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @see FactoryBean
|
||||
*/
|
||||
public class BatchResourceFactoryBean extends AbstractFactoryBean implements
|
||||
ResourceLoaderAware, StepContextAware {
|
||||
|
||||
private static final String BATCH_ROOT_PATTERN = "%BATCH_ROOT%";
|
||||
public class BatchResourceFactoryBean extends AbstractFactoryBean implements ResourceLoaderAware, StepContextAware {
|
||||
|
||||
private static final String JOB_NAME_PATTERN = "%JOB_NAME%";
|
||||
|
||||
private static final String STEP_NAME_PATTERN = "%STEP_NAME%";
|
||||
|
||||
private static final String DEFAULT_PATTERN = "/%BATCH_ROOT%/data/%JOB_NAME%/"
|
||||
+ "%STEP_NAME%.txt";
|
||||
private static final String DEFAULT_PATTERN = "data/%JOB_NAME%/" + "%STEP_NAME%.txt";
|
||||
|
||||
private String filePattern = DEFAULT_PATTERN;
|
||||
|
||||
private String jobName = null;
|
||||
|
||||
private String rootDirectory = "";
|
||||
|
||||
private String stepName = "";
|
||||
|
||||
private JobParametersFactory jobParametersFactory = new DefaultJobParametersFactory();
|
||||
|
||||
private ResourceLoader resourceLoader = new FileSystemResourceLoader();
|
||||
|
||||
private Properties properties;
|
||||
|
||||
/**
|
||||
* Public setter for the {@link JobParametersFactory} used to translate
|
||||
* {@link JobParameters} into {@link Properties}. Defaults to a
|
||||
* {@link DefaultJobParametersFactory}.
|
||||
* @param jobParametersFactory the {@link JobParametersFactory} to set
|
||||
*/
|
||||
public void setJobParametersFactory(JobParametersFactory jobParametersFactory) {
|
||||
this.jobParametersFactory = jobParametersFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always false because we are expecting to be step scoped.
|
||||
*
|
||||
@@ -106,11 +126,11 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
|
||||
* @see org.springframework.batch.execution.scope.StepContextAware#setStepScopeContext(org.springframework.core.AttributeAccessor)
|
||||
*/
|
||||
public void setStepContext(StepContext context) {
|
||||
Assert.state(context.getStepExecution() != null,
|
||||
"The StepContext does not have an execution.");
|
||||
Assert.state(context.getStepExecution() != null, "The StepContext does not have an execution.");
|
||||
StepExecution execution = context.getStepExecution();
|
||||
stepName = execution.getStep().getName();
|
||||
jobName = execution.getStep().getJobInstance().getJobName();
|
||||
properties = jobParametersFactory.getProperties(execution.getStep().getJobInstance().getJobParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,8 +150,7 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
|
||||
/**
|
||||
* helper method for <code>createFileName()</code>
|
||||
*/
|
||||
private String replacePattern(String string, String pattern,
|
||||
String replacement) {
|
||||
private String replacePattern(String string, String pattern, String replacement) {
|
||||
|
||||
if (string == null)
|
||||
return null;
|
||||
@@ -155,11 +174,17 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
|
||||
|
||||
String fileName = filePattern;
|
||||
|
||||
fileName = replacePattern(fileName, BATCH_ROOT_PATTERN, rootDirectory);
|
||||
fileName = replacePattern(fileName, JOB_NAME_PATTERN,
|
||||
jobName == null ? "job" : jobName);
|
||||
fileName = replacePattern(fileName, JOB_NAME_PATTERN, jobName == null ? "job" : jobName);
|
||||
fileName = replacePattern(fileName, STEP_NAME_PATTERN, stepName);
|
||||
|
||||
if (properties != null) {
|
||||
for (Iterator iterator = properties.entrySet().iterator(); iterator.hasNext();) {
|
||||
Entry entry = (Entry) iterator.next();
|
||||
String key = (String) entry.getKey();
|
||||
fileName = replacePattern(fileName, "%" + key + "%", (String) entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@@ -167,12 +192,4 @@ public class BatchResourceFactoryBean extends AbstractFactoryBean implements
|
||||
this.filePattern = replacePattern(filePattern, "\\", File.separator);
|
||||
}
|
||||
|
||||
public void setRootDirectory(String rootDirectory) {
|
||||
this.rootDirectory = replacePattern(rootDirectory, "\\", File.separator);
|
||||
if (rootDirectory != null && rootDirectory.endsWith(File.separator)) {
|
||||
this.rootDirectory = rootDirectory.substring(0, rootDirectory
|
||||
.lastIndexOf(File.separator));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,17 +21,16 @@ import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.batch.core.domain.JobSupport;
|
||||
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.StepExecution;
|
||||
import org.springframework.batch.core.domain.JobParametersBuilder;
|
||||
import org.springframework.batch.core.domain.JobSupport;
|
||||
import org.springframework.batch.core.domain.StepInstance;
|
||||
import org.springframework.batch.execution.scope.SimpleStepContext;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BatchResourceFactoryBean}
|
||||
@@ -47,41 +46,28 @@ public class BatchResourceFactoryBeanTests extends TestCase {
|
||||
*/
|
||||
private BatchResourceFactoryBean resourceFactory = new BatchResourceFactoryBean();
|
||||
|
||||
private String rootDir = getRootDir();
|
||||
|
||||
private char pathsep = File.separatorChar;
|
||||
|
||||
private String path = "data" + pathsep;
|
||||
|
||||
private JobInstance jobInstance;
|
||||
|
||||
private StepInstance stepInstance;
|
||||
|
||||
/**
|
||||
* mock step context
|
||||
*/
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
resourceFactory.setRootDirectory(rootDir);
|
||||
|
||||
jobInstance = new JobInstance(new Long(0), new JobParameters());
|
||||
jobInstance.setJob(new JobSupport("testJob"));
|
||||
JobExecution jobExecution = new JobExecution(jobInstance);
|
||||
StepInstance step = new StepInstance(jobInstance, "bar");
|
||||
StepExecution stepExecution = new StepExecution(step, jobExecution, null);
|
||||
SimpleStepContext context = new SimpleStepContext(stepExecution);
|
||||
resourceFactory.setStepContext(context);
|
||||
JobExecution jobExecution = jobInstance.createJobExecution();
|
||||
stepInstance = new StepInstance(jobInstance, "bar");
|
||||
resourceFactory.setStepContext(new SimpleStepContext(jobExecution.createStepExecution(stepInstance)));
|
||||
|
||||
resourceFactory.afterPropertiesSet();
|
||||
|
||||
}
|
||||
|
||||
private String getRootDir() {
|
||||
String rootDir = System.getProperty("java.io.tmpdir");
|
||||
assertNotNull(rootDir);
|
||||
if (rootDir != null && rootDir.endsWith(File.separator)) {
|
||||
rootDir = rootDir.substring(0, rootDir.lastIndexOf(File.separator));
|
||||
}
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,15 +87,26 @@ public class BatchResourceFactoryBeanTests extends TestCase {
|
||||
try {
|
||||
resourceFactory.getObject();
|
||||
fail("Expected IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testNonStandardFilePattern() throws Exception {
|
||||
resourceFactory.setFilePattern("/%BATCH_ROOT%/data/%JOB_NAME%/"
|
||||
+ "%STEP_NAME%-job");
|
||||
doTestPathName("bar-job", path);
|
||||
resourceFactory.setFilePattern("foo/data/%JOB_NAME%/" + "%STEP_NAME%-job");
|
||||
doTestPathName("bar-job", "foo" + pathsep + "data" + pathsep);
|
||||
}
|
||||
|
||||
public void testNonStandardFilePatternWithJobParameters() throws Exception {
|
||||
jobInstance = new JobInstance(new Long(0), new JobParametersBuilder().addString("job.key", "spam")
|
||||
.toJobParameters());
|
||||
jobInstance.setJob(new JobSupport("testJob"));
|
||||
JobExecution jobExecution = jobInstance.createJobExecution();
|
||||
stepInstance = new StepInstance(jobInstance, "bar");
|
||||
resourceFactory.setStepContext(new SimpleStepContext(jobExecution.createStepExecution(stepInstance)));
|
||||
resourceFactory.setFilePattern("foo/data/%JOB_NAME%/%job.key%-foo");
|
||||
doTestPathName("spam-foo", "foo" + pathsep + "data" + pathsep);
|
||||
}
|
||||
|
||||
public void testResoureLoaderAware() throws Exception {
|
||||
@@ -125,30 +122,11 @@ public class BatchResourceFactoryBeanTests extends TestCase {
|
||||
assertTrue(resource.exists());
|
||||
}
|
||||
|
||||
public void testRootDirectoryEndsWithForwardSlash() throws Exception {
|
||||
String rootDir = getRootDir();
|
||||
rootDir = StringUtils.replace(rootDir, File.separator, "/") + "/";
|
||||
resourceFactory.setRootDirectory(rootDir);
|
||||
doTestPathName("bar.txt", path);
|
||||
}
|
||||
|
||||
public void testRootDirectoryEndsWithBackSlash() throws Exception {
|
||||
String rootDir = getRootDir();
|
||||
rootDir = "/"+StringUtils.replace(rootDir, File.separator, "\\") + "\\";
|
||||
resourceFactory.setRootDirectory(rootDir);
|
||||
doTestPathName("bar.txt", path);
|
||||
}
|
||||
|
||||
private void doTestPathName(String filename, String path) throws Exception, IOException {
|
||||
Resource resource = (Resource) resourceFactory.getObject();
|
||||
|
||||
String returnedPath = resource.getFile().getAbsolutePath();
|
||||
|
||||
String absolutePath = new File("/" + rootDir + pathsep + path + jobInstance.getJobName() + pathsep + filename).getAbsolutePath();
|
||||
|
||||
// System.err.println(absolutePath);
|
||||
// System.err.println(returnedPath);
|
||||
String absolutePath = new File(path + jobInstance.getJobName() + pathsep + filename).getAbsolutePath();
|
||||
assertEquals(absolutePath, returnedPath);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user