问题
I have three different .properties files in a Spring Batch project, and I'm trying to set which .properties file should be used as a JobParameter. I'd like to be able to run the job like so:
java CommandLineJobRunner context.xml jobName region=us
The region should specify which .properties file should be used. The problem is getting the context to recognize the JobParameter. I've tried the following to no avail:
<context:property-placeholder location="classpath:batch.#{jobParameters['region']}.properties"/>
And also:
<util:properties id="batchProperties" location="classpath:batch.#{jobParameters['region']}.properties"></util:properties>
I had heard that adding scope="step" could fix similar issues, but I tried adding that to both of the above solutions and still had exceptions.
I think I'm missing a fundamental idea of why I can't get this working, but I'm unable to figure out what that idea is.
If anyone has any suggestions on getting this working and/or explaining why my previous approaches failed, I'd appreciate it.
回答1:
This is not the right way to proceed (it is impossible do what you are trying to do).
You have to think that jobParameters is available only when a job is running and only for its composing steps marked with scope="step" (and not <context:property-placeholder> nor <util:properties> has a step attribute).
A way for solving the problem is to load properties file in job's execution context before first step is running with a listener:
public class PropertyLoaderJobExecutionListener extends StepExecutionListenerSupport {
Properties countryProperties;
public void setCountryProperties(Properties pfb) {
this.countryProperties = pfb;
}
@Override
public void beforeStep(StepExecution stepExecution) {
super.beforeStep(stepExecution);
// Store property file content in jobExecutionContext with name "batchProperties"
stepExecution.getJobExecution().getExecutionContext().put("batchProperties", countryProperties);
}
}
in your job.xml
<bean id="loadPropertiesListener" class="PropertyLoaderJobExecutionListener" scope="step">
<property name="pfb">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:batch.#{jobParameters['region']}.properties" />
</bean>
</property>
</bean>
and register this listener in your first step (you can't do that in your JobExectionListsner.beforeJob() because there isn't a scope="job" for now and late-binding of #{jobParameters['region']} value is not available).
To access your data with spEL use this syntax:
#{jobExecutionContext.get('batchProperties').getProperty('language')}
or a better syntax to access properties (IDK spEL so good, sorry).
Hope to be clear and can help to solve your problem.
EDIT (full code of my working job.xml):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-util-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<job id="sourceJob" xmlns="http://www.springframework.org/schema/batch">
<step id="step1">
<tasklet ref="getRemoteFileTasklet" />
<listeners>
<listener ref="loadPropertiesListener" />
</listeners>
</step>
</job>
<bean id="loadPropertiesListener" class="PropertyLoaderJobExecutionListener" scope="step">
<property name="pfb">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:batch.#{jobParameters['region']}.properties" />
</bean>
</property>
</bean>
<bean id="getRemoteFileTasklet" class="GetRemoteFileTasklet" />
来源:https://stackoverflow.com/questions/18516012/setting-a-properties-file-in-spring-batch-via-a-jobparameter