【问题标题】:Failed to execute CommandLineRunner - Spring Batch无法执行 CommandLineRunner - Spring Batch
【发布时间】:2018-10-15 21:17:43
【问题描述】:

您好,我对 Spring 批处理非常陌生,遇到以下我无法解决的异常:

java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:781) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at com.demo.BatchDemo.main(KnpBatchApplication.java:16) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.0.1.RELEASE.jar:2.0.1.RELEASE]
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653) ~[na:1.8.0_72]
at java.util.ArrayList.get(ArrayList.java:429) ~[na:1.8.0_72]
at org.springframework.batch.core.JobParametersBuilder.getNextJobParameters(JobParametersBuilder.java:265) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:162) ~[spring-boot-autoconfigure-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:179) ~[spring-boot-autoconfigure-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:134) ~[spring-boot-autoconfigure-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:128) ~[spring-boot-autoconfigure-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
... 10 common frames omitted

我的代码在这里:

    @SpringBootApplication
    public class BatchDemo {
    public static void main(String args[])
    {
        SpringApplication.run(BatchDemo.class);
    }
}

我可以通过添加exclude = BatchAutoConfiguration.class 来解决它。但我想找到真正的原因并解决它。

我没有传递任何命令行参数,并且此异常并非一直发生。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>demo_batch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo_batch</name>
<url>http://maven.apache.org</url>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.batch</groupId>
        <artifactId>spring-batch-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.batch</groupId>
        <artifactId>spring-batch-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

【问题讨论】:

  • 请发布您的 pom.xml 或 build.gradle。
  • @Ozilophile 我添加了 pom.xml

标签: spring spring-boot spring-batch


【解决方案1】:

当你使用@SpringBootApplication 时,Spring 的 autoConfiguration 默认是开启的。由于您在类路径中加载了 Spring Batch 依赖项,因此也启用了 Spring Batch AutoConfiguration。

在应用程序启动期间,Spring Batch 的自动配置 (BatchAutoConfiguration) 会创建一个 Runner,它会运行 BatchConfig 中定义的所有作业。

您可以通过在应用程序属性中将 spring.batch.job.enabled 属性设置为 false 或像您一样简单地排除批处理的自动配置来禁用此行为。

请参阅herehere 了解更多信息。

【讨论】:

  • 属性中的 spring.batch.job.enabled: false 错误完全消失了。还修复了在启动时启动所有作业的奇怪行为。谢谢大佬。
【解决方案2】:

对于希望实际执行其批处理作业并遇到此错误的任何人,请尝试检查 Spring 批处理元数据表中的记录是否存在任何不一致。

为了获取下一个JobParameters,Spring Batch 搜索与您的工作相同的JOB_NAME 的最新BATCH_JOB_INSTANCE,然后在数据库中查找匹配的BATCH_JOB_EXECUTION 记录(由JOB_INSTANCE_ID 链接)。

我们有一个内部任务正在运行,它从 BATCH_JOB_EXECUTION 中删除了记录,但由于错误,没有从 BATCH_JOB_INSTANCE 中删除匹配的记录。

在一个环境中,我们已经超过 3 个月没有执行任何作业,因此我们不再有 BATCH_JOB_EXECUTION 记录,但有大量 BATCH_JOB_INSTANCE 记录。我们反复抛出这个问题中列出的堆栈跟踪,跨越多个不同的 Spring Batch 应用程序,并且在网上的任何地方都找不到解决方案。

我们解决了这个问题

  1. 运行 SQL 以从 BATCH_JOB_INSTANCE 中删除 BATCH_JOB_EXECUTION 中没有匹配记录 - 这在短期内解除了阻塞作业;并且,
  2. 使用spring-batch-toolkit 替换我们的清除任务;它提供了一个RemoveSpringBatchHistoryTasklet,可以正确删除记录。

【讨论】:

    【解决方案3】:

    我收到此错误,这是因为我从遵循一般命名约定和类型的文件夹中读取文件。我错误地将图像文件留在了同一目录中,我的代码无法处理它并引发了此错误。

    【讨论】: