【问题标题】:Can Spring Retry be used with Spring Batch FlatFileItemReaderSpring Retry 可以与 Spring Batch FlatFileItemReader 一起使用吗
【发布时间】:2016-08-09 21:45:57
【问题描述】:

我有以下ItemReader

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
public class MyReader extends FlatFileItemReader<Holding> {

    @Autowired
    public MyReader(LineMapper<Holding> lineMapper, File loadFile) {
        setResource(new FileSystemResource(loadFile));
        final int NUMBER_OF_HEADER_LINES = 1;
        setLinesToSkip(NUMBER_OF_HEADER_LINES);
        setLineMapper(lineMapper);
    }

    @Override
    @Retryable(value=ItemStreamException.class, maxAttempts=5,  backoff=@Backoff(delay=1800000))
    public void open(ExecutionContext executionContext) throws ItemStreamException {
                super.open(executionContext);
    }
}

在运行作业时,要读取的文件(即loadFile)可能可用也可能不可用。如果文件不可用,我希望阅读器休眠约 30 分钟,然后重试打开文件。如果在五次尝试后找不到该文件,它可能会像通常那样通过抛出ItemStreamException 失败。

很遗憾,上述代码不会尝试重试打开文件。它在第一次调用 open 时抛出 ItemStreamException 并且不会重试打开。

有人可以解释一下如何做到这一点吗?注意:我在 SpringBootApplication 类中确实有 @EnableRetry

【问题讨论】:

    标签: java spring spring-batch spring-retry


    【解决方案1】:

    这个有效。我做了一些小的改动,因为我不知道你的课程。

    build.gradle

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath(
                    "org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE",
            )
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'spring-boot'
    
    tasks.withType(JavaCompile) {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    
    repositories {
        mavenCentral()
    }
    
    springBoot {
        mainClass = "test.MyReader"
    }
    
    dependencies {
        compile(
                'org.springframework.boot:spring-boot-starter',
                'org.springframework.boot:spring-boot-starter-aop',
                'org.springframework.retry:spring-retry',
        )
    }
    

    MyApplication.java

    @EnableRetry
    @SpringBootApplication
    public class MyApplication implements CommandLineRunner {
        private final MyReader myReader;
    
        @Autowired
        public MyApplication(MyReader myReader) {
            this.myReader = myReader;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            myReader.read();
        }
    }
    

    MyReader.java

    @Service
    public class MyReader {
        private static final String PATH = "a2";
        private final Logger logger = LoggerFactory.getLogger(MyReader.class);
    
        public MyReader() {
    
        }
    
        @Retryable(value = IOException.class, maxAttempts = 5, backoff = @Backoff(delay = 5000))
        public void read() throws IOException {
            final Resource resource = new FileSystemResource(PATH);
            logger.info("\n\nRead attempt: {}\n", resource);
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {
                final String content = reader.lines().collect(Collectors.joining(" "));
                logger.info("\n\nFile content: {}\n", content);
            }
        }
    }
    

    当您执行并且文件存在时,您会在日志中看到一条“读取尝试”消息和一条“文件内容”消息。我什至在其中添加了空行,所以现在很难忽视。

    当文件不存在时,您将看到五条“读取尝试”消息,然后抛出异常。

    我将重试时间更改为 5 秒。如果你足够快,你可以在没有文件的情况下开始,然后在那里制作一些文件,你会看到它有效。您应该会看到几次读取尝试,最后是文件内容。

    我可以看到您已经在这个问题上苦苦挣扎了几天。请不要产生不必要的问题,因为它们对社区没有帮助。为了将来的参考,试着坚持你的一个问题,如果需要的话可以修改它。

    【讨论】:

    • 我还可以让 Spring Retry 在 Spring Batch 的 FlatFileItemReader 之外工作。在 OP 中,我问如何让它在 Spring Batch 的 FlatFileItemReader 中工作。
    【解决方案2】:

    从 Spring Boot 版本 1.3.1.RELEASE 移动到 1.4.0.RELEASE(及其相应的自动版本化依赖项,例如 spring-boot-starter-batch)解决了这个问题。重试在 OP 中实现的 1.4.0.RELEASE 中工作。不适用于 1.3.1.RELEASE。这是现在正在使用的 gradle 文件:

    buildscript {
        ext {
            // Previously using 1.3.1.RELEASE where retry functionality does not work
            springBootVersion = '1.4.0.RELEASE' 
        }
        repositories {
            mavenCentral()
            mavenLocal()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'spring-boot'
    
    configurations {
       provided
    }
    
    sourceSets {
        main {
            compileClasspath += configurations.provided
        }
    }
    
    jar {
        baseName = 'load'
        version = '1.0'
    }
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    repositories {
        mavenCentral()
        mavenLocal()
    }
    
    dependencies {
        compile('org.springframework.boot:spring-boot-starter-batch')
        compile('org.springframework.boot:spring-boot-configuration-processor')
        compile('org.springframework.boot:spring-boot-starter-data-jpa')
        compile('org.springframework.boot:spring-boot-starter-mail')
        compile('org.springframework.boot:spring-boot-starter-aop')
        compile('org.projectlombok:lombok:1.16.6')
        compile('org.hibernate:hibernate-validator:5.2.4.Final')
        compile('org.quartz-scheduler:quartz:2.2.3')
        runtime('javax.el:javax.el-api:2.2.4')
        runtime('org.glassfish.web:javax.el:2.2.4')
        runtime('net.sourceforge.jtds:jtds:1.3.1')
        testCompile('org.springframework.boot:spring-boot-starter-test')
        testCompile('org.springframework.batch:spring-batch-test')
    }
    
    
    
    eclipse {
        classpath {
             containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
             containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
        }
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = '2.11'
    } 
    

    注意:考虑使用JobExecutionDecider 重试使用FlatFileItemReader 的步骤。但是,ItemStreamException 会导致整个作业和应用程序终止,而决策者没有机会执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      相关资源
      最近更新 更多