文件可用后立即运行Spring Batch Job

时间:2018-07-24 04:56:24

标签: java spring spring-boot spring-batch

我想在共享文件夹中的文件可用后立即运行Spring Batch作业。我已经提供了一个观察程序服务来检查目录中的新条目,但是我将如何触发我的批处理作业?

我做了以下更改-

  @Component
public class ScheduleJob {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private UtilizationBatchConfiguration utilizationBatchConfiguration;

    @Value("${excel.to.database.job.source.file.source.path}")
    private String PROPERTY_EXCEL_SOURCE_FILE_PATH;


    //@Scheduled(cron = "${excel.to.database.job.cron}")
    public void runJob() {
        //String fileSource = PROPERTY_EXCEL_SOURCE_FILE_PATH.concat(PROPERTY_EXCEL_SOURCE_FILE_NAME)+".xlsx";
        Path path = Paths.get(PROPERTY_EXCEL_SOURCE_FILE_PATH);
        WatchKey key;
        WatchService watchService = null;
        try {
            watchService = FileSystems.getDefault().newWatchService();
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

            while ((key = watchService.take()) != null) {
                for (WatchEvent<?> event : key.pollEvents()) {

                    System.out.println(
                            "Event kind:" + event.kind()
                                    + ". File affected: " + event.context() + ".");
                    if(event.kind().equals("ENTRY_CREATE")) {
                        impoerJob();
                    }
                }
                key.reset();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void impoerJob() {

        // make unique JobParameters so now instance of job can be started
        Map<String, JobParameter> confMap = new HashMap<String, JobParameter>();
        confMap.put("time", new JobParameter(System.currentTimeMillis()));
        JobParameters jobParameters = new JobParameters(confMap);
        try {
            JobExecution ex = jobLauncher.run(utilizationBatchConfiguration.importExcelJob(), jobParameters);
            log.info(String.format("Execution status-----> %s, Execution Start Time ------> %s, Execution End Time %s", ex.getStatus(), ex.getStartTime(), ex.getEndTime()));
        } catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
                | JobParametersInvalidException e) {
            //
            e.printStackTrace();
        }
    }
}

如果我使用调度程序代替WatchService,则批处理作业将成功运行。 这里的问题是,我不知道文件何时将复制到共享位置。因此必须使用WatchService而不是Scheduler。 我的导入工作是-

@Component
public class UtilizationBatchConfiguration {
---- removed for brevity

@Bean
    public Job importExcelJob() {
        return jobBuilderFactory.get("importExcelJob")
            .incrementer(new RunIdIncrementer())
            .preventRestart()
            .listener(listener)
            .flow(step1())
            .end()
            .build();
    }
}

这几乎类似于Spring.io中的Spring Batch服务指南

现在,如果我尝试运行代码,则会得到以下响应-

  

在10.506秒内启动应用程序(JVM运行11.676)   2018-07-23 16:55:53.646信息18200-[线程2]   s.c.a.AnnotationConfigApplicationContext:关闭   org.springframework.context.annotation.AnnotationConfigApplicationContext@7b9a4292:   启动日期[IST 2018年7月23日星期一16:55:44];上下文层次结构的根   2018-07-23 16:55:53.649信息18200 --- [线程2]   o.s.j.e.a.AnnotationMBeanExporter:取消注册暴露于JMX的对象   关机时关闭bean 2018-07-23 16:55:53.650 INFO 18200 --- [
  线程2] o.s.j.e.a.AnnotationMBeanExporter:正在取消注册   JMX暴露的豆类2018-07-23 16:55:53.654信息18200 --- [
  线程2] j.LocalContainerEntityManagerFactoryBean:关闭JPA   EntityManagerFactory用于持久性单元``默认''2018-07-23   16:55:53.655 INFO 18200-[线程2]   com.zaxxer.hikari.HikariDataSource:HikariPool-1-关闭   启动... 2018-07-23 16:55:53.683信息18200 --- [线程2]   com.zaxxer.hikari.HikariDataSource:HikariPool-1-关闭   完成。

我又如何确保每次都读取一个新文件,而不是再次读取旧文件?

3 个答案:

答案 0 :(得分:1)

我不能代表type T = typeof a & typeof b & typeof c ,但通常JVM需要至少运行一个非守护进程线程以防止其关闭。看来您的应用程序没有该功能(因此已关闭)。在这种用例中,通常使用Spring Integration,我们在这里的文档中有此内容:https://docs.spring.io/spring-batch/trunk/reference/html/springBatchIntegration.html#launching-batch-jobs-through-messages

答案 1 :(得分:0)

您可以通过这种方式使用它,唯一的问题是Spring-Context在启动后立即关闭,因为“无事可做”。只需看看https://github.com/barryvdh/laravel-debugbar解决方案如何防止您的Spring-Context关闭即可。

答案 2 :(得分:0)

我不确定您为什么需要这里的批处理作业功能,因为看守服务似乎就足够了。

如果您对该位置具有写权限,则可以标记已处理的文件(可能添加前缀)并更改程序以忽略带有该前缀的文件名,也可以创建已处理的目录并将已处理的文件移动到该位置。处理后的目录,或者可以通过跟踪上一次成功运行的文件进程并查找比该时间戳新的文件来使用使用时间戳。