【问题标题】:How to use Spring Profiles in configuring a Spring Job如何使用 Spring Profiles 配置 Spring Job
【发布时间】:2017-12-22 01:29:45
【问题描述】:

我需要运行 Spring 批处理作业。我的要求是根据弹簧轮廓按顺序/并行运行几个步骤

我将 Job 配置放置在 spring 配置文件中以并行运行步骤 parallel.xml

<job id="job" xmlns="http://www.springframework.org/schema/batch"
incrementer="incrementer">

<step id="step1" next="step2">
    <tasklet ref="tasklet" />
</step>

<split id="step2" task-executor="assetStepAsyncTaskExecutor">
    <flow>
        <step id="split1">
            <tasklet ref="tasklet" />
        </step>
    </flow>
    <flow>
        <step id="split2">
            <tasklet ref="tasklet" />
        </step>
    </flow>
</split>
<listeners>
    <listener ref="listener" />
</listeners>
</job>

以及在 spring 配置文件 default.xml 中按顺序运行步骤的 Job 配置

<job id="job" xmlns="http://www.springframework.org/schema/batch"
incrementer="incrementer">

<step id="step1" next="step2">
    <tasklet ref="tasklet" />
</step>
<step id="step2" next="step3">
            <tasklet ref="tasklet" />
</step>
<step id="step3">
    <tasklet ref="tasklet" />
</step>
<listeners>
    <listener ref="listener" />
</listeners>
</job>

我正在使用 Spring 配置文件在作业配置之间切换。

<beans profile="parallel">
<import resource="classpath:/spring/parallel.xml" />
</beans>

<beans profile="default">
<import resource="classpath:/spring/default.xml" />
</beans>

我正在通过 web.xml 中的 contextConfigLocation 上下文参数加载配置文件。

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
// other config files
classpath*:/spring/default.xml
classpath*:/spring/parallel.xml
</param-value>
</context-param>

我将配置文件详细信息作为上下文参数传递

<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>default</param-value>
</context-param>

<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>parallel</param-value>
</context-param>

如果我不包含 contextConfigLocation 中的文件,它不会在 default.xml 和 parallel.xml 中加载 spring bean,因此我得到 NoBeanFoundException

Error creating bean with name 'controller' defined in class path resource [config.xml]: Cannot resolve reference to bean 'batchJob' while setting bean property 'job'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'batchJob' is defined
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3339) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:3780) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
    at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:163) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:61) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:96) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_121]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_121]
    at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'batchJob' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1083) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    ... 26 more

如果我包含两个配置文件。我得到一个 DuplicateJobException。

12/21/2017 17:00:58,971 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (ServerService Thread Pool -- 85) JBWEB000287: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener: java.lang.IllegalStateException: org.springframework.batch.core.configuration.DuplicateJobException: A job configuration with this name [batchJob] was already registered
    at org.springframework.batch.core.configuration.support.AutomaticJobRegistrar.start(AutomaticJobRegistrar.java:164) [spring-batch-core-2.1.8.RELEASE.jar:]
    at org.springframework.batch.core.configuration.support.AutomaticJobRegistrar.onApplicationEvent(AutomaticJobRegistrar.java:128) [spring-batch-core-2.1.8.RELEASE.jar:]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:97) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:303) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:911) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:428) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3339) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:3780) [jbossweb-7.5.7.Final-redhat-1.jar:7.5.7.Final-redhat-1]
    at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:163) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:61) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:96) [jboss-as-web-7.5.0.Final-redhat-21.jar:7.5.0.Final-redhat-21]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_121]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_121]
    at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: org.springframework.batch.core.configuration.DuplicateJobException: A job configuration with this name [batchJob] was already registered
    at org.springframework.batch.core.configuration.support.MapJobRegistry.register(MapJobRegistry.java:52) [spring-batch-core-2.1.8.RELEASE.jar:]
    at org.springframework.batch.core.configuration.support.DefaultJobLoader.doLoad(DefaultJobLoader.java:152) [spring-batch-core-2.1.8.RELEASE.jar:]
    at org.springframework.batch.core.configuration.support.DefaultJobLoader.load(DefaultJobLoader.java:114) [spring-batch-core-2.1.8.RELEASE.jar:]
    at org.springframework.batch.core.configuration.support.AutomaticJobRegistrar.start(AutomaticJobRegistrar.java:161) [spring-batch-core-2.1.8.RELEASE.jar:]
    ... 19 more

我错过了什么?

【问题讨论】:

  • 为了清楚起见,您希望根据弹簧活动配置文件定义一项作业,并行或顺序?
  • 是的。作业中的几个步骤将并行或按顺序运行,具体取决于活动配置文件。
  • 请问你用的是哪个版本的Spring,能不能创建一个github repo来演示一下情况?
  • Spring 批处理核心 - 2.1.8 Spring 核心 3.0.5 Spring 批处理集成 - 1.2.1 我将尝试使用此设置创建一个项目。 - 谢谢!
  • 请看here。似乎 default 配置文件是在 Spring 3.1 中添加的。也许这是你坚持的问题?如果是这样,请尝试升级 Spring 版本(一点点)或尝试为 default 作业配置定义不同的配置文件(我已删除的答案)。

标签: spring spring-batch spring-profiles


【解决方案1】:

Spring Batch 每个作业名称必须是唯一的,在配置作业时定义为 id="job"。以上配置尝试设置两个作业名称与“batchJob”相同的作业,这就是您看到异常的原因。

要实现您的需要,您需要这样做。

 <job id="jobA" xmlns="http://www.springframework.org/schema/batch"
incrementer="incrementer">

<step id="step1" next="step2">
    <tasklet ref="tasklet" />
</step>

<split id="step2" task-executor="assetStepAsyncTaskExecutor">
    <flow>
        <step id="split1">
            <tasklet ref="tasklet" />
        </step>
    </flow>
    <flow>
        <step id="split2">
            <tasklet ref="tasklet" />
        </step>
    </flow>
</split>
<listeners>
    <listener ref="listener" />
</listeners>
</job>


<job id="jobB" xmlns="http://www.springframework.org/schema/batch"
incrementer="incrementer">

<step id="step1" next="step2">
    <tasklet ref="tasklet" />
</step>
<step id="step2" next="step3">
            <tasklet ref="tasklet" />
</step>
<step id="step3">
    <tasklet ref="tasklet" />
</step>
<listeners>
    <listener ref="listener" />
</listeners>
</job>

从您的控制器中,您可以根据上下文参数调用 jobA 或 jobB。

【讨论】:

【解决方案2】:

正如@lzagkaretos 在 cmets 中所建议的那样,问题出在 Spring 版本上。将版本更新到 3.2.2.RELEASE 为我解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    相关资源
    最近更新 更多