From a40a362d9ac26a15c8dc5c8379caa37693f524ad Mon Sep 17 00:00:00 2001 From: dsyer Date: Mon, 4 Feb 2008 18:38:09 +0000 Subject: [PATCH] Rationalise BatchResourceFactoryBean and allow %{key}% values in replacement patterns for JobParameters --- .../resource/BatchResourceFactoryBean.java | 73 ++++++++++++------- .../BatchResourceFactoryBeanTests.java | 70 ++++++------------ 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java index f148b8b2c..1be4091d8 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/resource/BatchResourceFactoryBean.java @@ -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: * *
- * /%BATCH_ROOT%/job_data/%JOB_NAME%/%JOB_IDENTIFIER%-%STEP_NAME%.txt
+ * data/%JOB_NAME%/%STEP_NAME%.txt
  * 
* * 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).
+ * time, when the factory method is executed. To insert {@link JobParameters} + * use a pattern with the parameter key surrounded by %%, e.g. + * + *
+ * //home/jobs/data/%JOB_NAME%/%STEP_NAME%-%schedule.date%.txt
+ * 
+ * + * 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.
* * 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 createFileName() */ - 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)); - } - } - } diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java index 97af01eea..7e080dd2e 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/resource/BatchResourceFactoryBeanTests.java @@ -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); } - + }