首页 > 解决方案 > 在作业 XML 中使用 CommandLineJobRunner 参数

问题描述

我相信我在这里遗漏了一些非常基本的东西。我有一个 spring-batch 批处理作业,我正在修改以在作业运行时接受一个参数,以允许将临时文件存储在每个作业运行临时文件夹中的时间戳中。目前所有临时文件都位于同一个文件夹中,如果作业不按顺序运行,临时文件会相互碰撞。

我有一个作业运行器 bat 文件,用于实际启动作业,它正在创建一个时间戳并将其附加到传递给 CommandLineJobRunner 的参数中。因此它使用 3 个参数运行 CommandLineJobRunner.main(args):

String[] args = new String[]{[File.XML], [JobName], build.timestamp=[timestamp]}
CommandLineJobRunner.main(args)

在我的 XML 我有以下

<bean id="tempfiledir" class="org.springframework.core.io.FileSystemResource">
    <constructor-arg value="${batch.file.drive}:/${batch.file.writer.input.root.directory}/${batch.input_file}/${build.timestamp}" />
</bean> 

其他变量在我的 batch.properties 文件中设置。它们显然是静态的。

从那里,我将资源传递给 bean,如下所示:

<bean id="[beanTaskletID]" class="[taskletDir]">
    <property name="temporaryFilesDir" ref="tempfiledir"/>
</bean>

然后在实际步骤中我有:

<step id="[stepID]">
        <tasklet ref="[beanTaskletID]"/>
        <next on="FAILED" to="[failStepID]"/>
        <next on="COMPLETED" to="[completeStepID]"/>
    </step>

在我的 tasklet 中,我得到传递的参数,如下所示:

Resource tempDirectory;
public void setTemporaryFilesDir(Resource temporaryFilesDir) {
    this.tempDirectory = temporaryFilesDir;
}

当我尝试运行它时,我收到以下错误:

lassPathXmlApplicationContext [WARN] Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'tempfiledir' defined in class path resource [XML FILE]: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:211)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:180)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:155)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:162)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:290)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
    at com.batch.myJobRunner.main(myJobRunner.java:28)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveStringValue(BeanDefinitionVisitor.java:282)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitGenericArgumentValues(BeanDefinitionVisitor.java:159)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitBeanDefinition(BeanDefinitionVisitor.java:85)
    at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:208)
    ... 11 more
2020-02-14 15:49:36 CommandLineJobRunner [ERROR] Job Terminated in error: Invalid bean definition with name 'tempfiledir' defined in class path resource [XML FILE]: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.nput_file}/${build.timestamp}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'tempfiledir' defined in class path resource [XML FILE]: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"
    at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:211)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:180)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:155)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:162)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:290)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
    at com.batch.myJobRunner.main(myJobRunner.java:28)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'build.timestamp' in string value "${batch.file.drive}:/${batch.file.writer.input.root.directory}${batch.input_file}/${build.timestamp}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveStringValue(BeanDefinitionVisitor.java:282)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveValue(BeanDefinitionVisitor.java:204)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitGenericArgumentValues(BeanDefinitionVisitor.java:159)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitBeanDefinition(BeanDefinitionVisitor.java:85)
    at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:208)
    ... 11 more

我想也许我需要一个声明的占位符来设置参数,所以我在 batch.properties 中添加了以下内容:

build.timestamp=

我读过运行时传入的作业参数将覆盖同一参数的任何属性文件设置。但是当我像这样运行工作时, build.timestamp 总是只是一个空字符串。所以要么不是这种情况,要么在作业运行时传入的参数实际上并没有在任何地方设置。

要么,要么我只是很清楚地不知道如何从 XML 文件中运行的作业访问传入的参数。任何有关如何做到这一点的帮助将不胜感激。我花了几个小时研究 spring-batch 文档,并没有清楚地表明如何访问 XML 文件中的参数,所有它所做的只是说明你可以做到。我找到的所有用于访问此类参数的文档都是通过在 java 中创建作业而不是将其存放在 XML 中来成功工作的。很明显,这不是我处理这个批处理工作的方法。

标签: javaspring-batch

解决方案


您可以使用 Spring 表达式语言访问作业参数。

#{jobParameters['build.timestamp']}

所以bean定义将是这样的。由于您使用的是文件系统资源,您可以直接将文件注入到beanTaskletID. 所以不需要tempfiledir单独定义bean。不要忘记添加范围步骤。

 <bean id="[beanTaskletID]" class="[taskletDir]" scope="step">
        <property name="temporaryFilesDir" value="file:${batch.file.drive}:/${batch.file.writer.input.root.directory}/${batch.input_file}/#{jobParameters['build.timestamp']}"/>
    </bean>

推荐阅读