Spring Batch/Spring Boot 总是自动启动我的工作

Posted

技术标签:

【中文标题】Spring Batch/Spring Boot 总是自动启动我的工作【英文标题】:Spring Batch/Spring Boot always auto-start my jobs 【发布时间】:2016-11-04 08:00:11 【问题描述】:

我正在使用 Spring Boot 1.3.3.RELEASESpring Batch 3.0.6.RELEASE,并且无法让 Spring Batch/Spring Boot 自动启动我的工作。

这个问题类似于how to stop spring batch scheduled jobs from running at first time when executing the code?

我有以下测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@Configuration
@ComponentScan(useDefaultFilters = false,
    includeFilters = @ComponentScan.Filter(value = GetMarkerViaSpringBatchApplicationTest.class,
        type = FilterType.ASSIGNABLE_TYPE) )
@EnableBatchProcessing
//@IntegrationTest("spring.batch.job.enabled=false")
@EnableAutoConfiguration
@TestPropertySource(
    locations = "classpath:env.properties", "classpath:application.properties", "classpath:database.properties",
    properties = "spring.batch.job.enabled=false")
@SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class,
    locations = "classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml")
public class GetMarkerViaSpringBatchApplicationTest 
  @Autowired
  private JobLauncherTestUtils jobLauncherTestUtils;

  @Test
  public void testLaunchJob() throws Exception 
    JobExecution jobExecution = jobLauncherTestUtils.launchJob();
     assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED);
  

在与测试类相同的目录(包)中,我有配置文件GetMarkerViaSpringBatchApplicationTest-context.xml

GetMarkerViaSpringBatchApplicationTest-context.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:batch="http://www.springframework.org/schema/batch"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="classpath:/META-INF/spring/get-marker-job-new.xml" />

    <bean id="jobLauncherTestUtils" class="org.springframework.batch.test.JobLauncherTestUtils" />

    <bean id="batchConfigurer" class="org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer">
        <constructor-arg name="dataSource" ref="hsqlDataSource" />
    </bean>
</beans>

get-marker-job-new.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:task="http://www.springframework.org/schema/task"
    xmlns:file="http://www.springframework.org/schema/integration/file" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd    
    http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <import resource="classpath:META-INF/spring/application-context.xml" />
    <import resource="classpath:META-INF/spring/database.xml" />

    <!-- The @EnableBatchProcessing on the main class sets up: job-repository, jobLauncher, and jobRepository -->
    <!-- Spring Boot with Spring Batch doesn't like multiple DataSources since it doesn't know which one -->
    <!-- to pick for Spring Batch. This class will therefore coerce to pick the proper HSQL dataSource. -->
    <!-- See https://***.com/questions/25540502/use-of-multiple-datasources-in-spring-batch -->
    <bean id="batchConfigurer" class="org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer">
        <constructor-arg name="dataSource" ref="hsqlDataSource" />
    </bean>

    <bean id="foo" class="myClass" />

    <bean id="myTasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
        <property name="targetObject" ref="myClass" />
        <property name="targetMethod" value="deliver" />
    </bean>

    <batch:job id="batchJob" restartable="false">
        <batch:step id="step1">
            <batch:tasklet ref="myTasklet"/>
        </batch:step>
    </batch:job>
</beans>    

application-context.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <import resource="classpath:META-INF/spring/database.xml" />

    <!-- load properties from config files -->
    <context:property-placeholder location="classpath:env.properties,classpath:application.properties,classpath:database.properties" />

    <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
</beans>

database.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

    <bean id="myDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <property name="driverClassName" value="$jdbc.myco.driverClassName" />
        <property name="username" value="$jdbc.myco.username" />
        <property name="password" value="$jdbc.myco.encpassword" />
        <property name="jdbcUrl" value="$jdbc.myco.url" />
        <property name="maximumPoolSize" value="$jdbc.myco.pool.maxactive" />
    </bean>
    <alias alias="dataSource" name="myDataSource" />

    <bean id="hsqlDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" primary="true">
        <property name="driverClassName" value="$jdbc.hsqldb.driverClassName" />
        <property name="username" value="$jdbc.hsqldb.username" />
        <property name="password" value="$jdbc.hsqldb.password" />
        <property name="jdbcUrl" value="$jdbc.hsqldb.url" />
        <property name="maximumPoolSize" value="$jdbc.hsqldb.pool.maxactive" />
    </bean>

</beans>

application.properties(在根目录中,也在类路径中):

spring.datasource.platform=sqlserver
spring.profiles.active=local
spring.batch.job.enabled=true
spring.batch.initializer.enabled=true
spring.batch.schema=classpath:org/springframework/batch/core/schema-hsqldb.sql

注意spring.batch.job.enabled=trueapplication.properties 中,但在@IntegrationTest@TestPropertySource 中为假。 每当我在application.properties 中设置spring.batch.job.enabled=true 时,无论在@IntegrationTest@TestPropertySource 中尝试各种spring.batch.job.enabled=false 组合,每当我运行此测试时,工作就会在jobLauncherTestUtils.launchJob() 被调用之前开始。 运行日志:

15:52:49,083 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - Before test class: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].

15:52:49,099 (o.s.test.context.support.DependencyInjectionTestExecutionListener) - Performing dependency injection for test context [[DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]]].

15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'

15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
...
   BatchAutoConfiguration#jobExplorer did not match
      - @ConditionalOnMissingBean (types: o.s.batch.core.explore.JobExplorer; SearchStrategy: all) found the following [jobExplorer] (OnBeanCondition)

   BatchAutoConfiguration#jobLauncherCommandLineRunner did not match
      - @ConditionalOnMissingBean (types: o.s.boot.autoconfigure.batch.JobLauncherCommandLineRunner; SearchStrategy: all) found no beans (OnBeanCondition)
      - @ConditionalOnProperty expected 'true' for properties spring.batch.job.enabled (OnPropertyCondition)

   BatchAutoConfiguration.JpaBatchConfiguration did not match
      - required @ConditionalOnClass classes not found: javax.persistence.EntityManagerFactory (OnClassCondition)
...
15:53:02,225 (o.s.test.context.cache.DefaultCacheAwareContextLoaderDelegate) - Storing ApplicationContext in cache under key [[MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]]

15:53:02,256 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - Before test method: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = testLaunchJob@GetMarkerViaSpringBatchApplicationTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].

15:53:04,669 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - After test method: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = testLaunchJob@GetMarkerViaSpringBatchApplicationTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].

15:53:04,685 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - After test class: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].

我已阅读 http://forum.spring.io/forum/spring-projects/batch/748038-i-do-not-want-enablebatchprocessing-to-launch-a-job 和 how to stop spring batch scheduled jobs from running at first time when executing the code?,但似乎无法让 jobLauncher自动启动。 我的理解是application.properties 属性应该被我试图在测试中直接设置的两个地方覆盖,但BatchAutoConfiguration 似乎不尊重该覆盖。 如果我在application.properties 中设置spring.batch.job.enabled=false(或注释掉该属性)并尝试从@IntegrationTest@TestPropertySource 驱动它,它的行为与预期相同。 我对值覆盖的理解不正确吗?

任何帮助将不胜感激。

【问题讨论】:

@ComponentScan@EnableAutoConfiguration 不属于测试类。这只是噪音,因为他们什么都不做。 @DaveSyer 这有效(通知@EnableAutoConfiguration):@RunWith(SpringJUnit4ClassRunner.class) @EnableBatchProcessing @IntegrationTest("spring.batch.job.enabled=false") @EnableAutoConfiguration @TestPropertySource( location = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class, locations = "classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml") 公共类GetMarkerViaSpringBatchApplicationTest @DaveSyer 这不起作用(注意没有@EnableAutoConfiguration)得到“没有定义名为'jobRepository'的bean”错误:@RunWith(SpringJUnit4ClassRunner.class)@EnableBatchProcessing @IntegrationTest(“spring .batch.job.enabled=false") @TestPropertySource(locations = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class,locations = "classpath :**/GetMarkerViaSpringBatchApplicationTest-context.xml") 公共类 GetMarkerViaSpringBatchApplicationTest @DaveSyer 这也不起作用(通知已删除@EnableAutoConfiguration)得到“没有定义名为'jobRepository'的bean”错误:@RunWith(SpringJUnit4ClassRunner.class)@EnableBatchProcessing @IntegrationTest(“ spring.batch.job.enabled=false") @TestPropertySource(locations = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration public class GetMarkerViaSpringBatchApplicationTest 是的,您正在使用测试类作为配置。我明白了。这不是很常见,我预计它可能会导致其他问题,所以我在评论中指出了这一点。 【参考方案1】:

如果您将application.properties 添加到@TestPropertySource,那么它最终会覆盖其他内容。如果您使用的是 spring boot,则不需要它。

【讨论】:

是的,这确实是个问题。如果您可以查看对您的@EnableAutoConfiguration 建议的回复 cmets,那将会很有帮助。我怀疑我的问题与将 XML 文件与配置文件的 Java 类混合有关。

以上是关于Spring Batch/Spring Boot 总是自动启动我的工作的主要内容,如果未能解决你的问题,请参考以下文章

“BasicBatchConfigurer”已保护访问 - Spring Batch/Spring Boot 未将数据持久化到数据库

Spring Boot 批处理应用程序 - Maven 错误

Spring Batch - Spring 集成

如何使用单个实体或单个存储库设计两个不同的项目?

Spring Boot 学习例子

Spring Boot 2Spring Boot CLI