将参数从 tasklet 步骤添加到作业上下文,并在 Spring Batch 的后续步骤中使用

2024-04-19

目前,我使用 jobParameters 来获取 FlatFileItemReader 和 FlatFileItemWriter 的文件名。测试我的批次是可以的,但我的目标是读取某个目录中的文件(该目录中只有这个文件)并且文件名可能会改变。输出文件名应取决于输入文件名。

因此,我考虑在我的工作中添加一个新步骤,该步骤将通过搜索好目录并在其中查找文件来设置输出和输入文件名。我读将数据传递给未来的步骤 http://docs.spring.io/spring-batch/trunk/reference/html/patterns.html来自 Spring 文档,以及这个线程 https://stackoverflow.com/questions/21549951/spring-batch-flatfileitemwriter-how-to-use-stepexecution-jobid-to-generate-fil来自SO,但我无法使其工作,文件始终为“空”。

首先,我定义了以下 Tasklet

public class SettingFilenamesTasklet implements Tasklet {

    private StepExecution stepExecution;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        // TODO Search folder and set real filenames
        String inputFilename = "D:/TestInputFolder/dataFile.csv";
        String outputFilename = "D:/TestOutputFolder/dataFile-processed.csv";
        ExecutionContext stepContext = stepExecution.getExecutionContext();
        stepContext.put("inputFile", inputFilename);
        stepContext.put("outputFile", outputFilename);
        return RepeatStatus.FINISHED;
    }

    @BeforeStep
    public void saveStepExecution(StepExecution stepExec) {
        stepExecution = stepExec;
    }
}

然后,我添加了 PromotionListener bean

@Bean
public ExecutionContextPromotionListener promotionListener() {
    ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
    listener.setKeys(new String[]{
            "inputFile", "outputFile"
    });
    return listener;
}

我通过 FlatFileItemWriter 定义中的 jobExecutionContext 更改了 jobParameters (我没有更改代码本身的一行)

@Bean
@StepScope
public FlatFileItemWriter<RedevableCRE> flatFileWriter(@Value("#{jobExecutionContext[outputFile]}") String outputFile) {
    FlatFileItemWriter<Employee> flatWriter = new FlatFileItemWriter<Employee>();
    FileSystemResource isr;
    isr = new FileSystemResource(new File(outputFile));
    flatWriter.setResource(isr);
    DelimitedLineAggregator<RedevableCRE> aggregator = new DelimitedLineAggregator<RedevableCRE>();
    aggregator.setDelimiter(";");
    BeanWrapperFieldExtractor<RedevableCRE> beanWrapper = new BeanWrapperFieldExtractor<RedevableCRE>();
    beanWrapper.setNames(new String[]{
        "id", "firstName", "lastName", "phone", "address"
    });
    aggregator.setFieldExtractor(beanWrapper);
    flatWriter.setLineAggregator(aggregator);
    flatWriter.setEncoding("ISO-8859-1");
    return flatWriter;
}

我添加了我的 Tasklet bean

@Bean
public SettingFilenamesTasklet settingFilenames() {
    return new SettingFilenamesTasklet();
}

我创建了一个新步骤来添加到我的工作声明中

@Bean
public Step stepSettings(StepBuilderFactory stepBuilderFactory, SettingFilenamesTasklet tasklet, ExecutionContextPromotionListener listener) {
    return stepBuilderFactory.get("stepSettings").tasklet(tasklet).listener(listener).build();
}

目前,FlatFileItemReader 仍然使用 jobParameters 值,我想让我的 FlatFileItemWriter 首先工作。我收到以下错误:

[...]    
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.file.FlatFileItemWriter]: Factory method 'flatFileWriter' threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:591)
    ... 87 common frames omitted
Caused by: java.lang.NullPointerException: null
    at java.io.File.<init>(Unknown Source)
    at batchTest.BatchConfiguration.flatFileWriter(BatchConfiguration.java:165)
    at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889.CGLIB$flatFileWriter$1(<generated>)
    at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889$$FastClassBySpringCGLIB$$969a8527.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889.flatFileWriter(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    ... 88 common frames omitted

我尝试用 @JobScope 替换 @StepScope 注释;将我的参数直接放入 jobExecutionContext (+ JobExecutionListener) 而不是使用 StepContext + PromotionListener...没有任何作用。当我尝试创建 FlatFileItemWriter 时,资源文件始终为空。

我缺少什么?

感谢您的帮助。


在任务中你有ChunkContext供您使用,因此您不需要@BeforeStep,您可以将其删除(在我的配置中,它根本不会被调用,当您将其视为一个操作步骤时,没有多大意义,但我没有看到 NPE,所以猜测该部分有效)。我们通过以下两种方法之一解决了这个问题:

  1. 您可以将任何参数从tasklet传递到作业ExecutionContext直接使用chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put("inputFile", inputFilename);

  2. 你可以加ExecutionContextPromotionListener到你的tasklet步骤然后做chunkContext.getStepContext().getStepExecution().getExecutionContext().put("inputFile", inputFilename);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将参数从 tasklet 步骤添加到作业上下文,并在 Spring Batch 的后续步骤中使用 的相关文章

随机推荐

  • 如何监控 Tomcat 服务器上的多个 Web 应用程序(使用 JMX)?

    有没有办法监控单个 Web 应用程序的 CPU 和内存消耗Tomcat server I have Tomcat打开其 JVM 下的所有 Web 应用程序 因此我只能看到一个 JVM 无法单独监控每个 Web 应用程序 Web 应用程序是密
  • jquery中删除多个元素

    在我当前的代码中我有这样的 foo remove bar remove 有没有办法通过使用删除多个元素remove once 它不限于 remove 但只需用逗号分隔选择器 foo bar remove 多重选择器 选择器1 选择器2 选择
  • 如何调整 UIImageView 的大小以适应底层图像而不移动它?

    我有一个 UIImageView 其框架在加载图像之前设置 对于图像来说总是太大 因此 例如 当我尝试圆角时 什么也没有发生 如何调整框架大小 使其与底层图像的大小相同 同时确保 UIImageView 的中心点不会改变 如果更改 UIVi
  • CPython的静态对象地址和碎片

    I read 对于Python来说 if x 是存储x的内存地址 这是给定的id对象的属性永远不会改变 这意味着对象在其生命周期中始终存储在给定的内存地址中 这就引出了一个问题 虚拟 内存碎片怎么样 说一个物体A位于地址 1 有id1 占用
  • IIS7的工作进程是什么?

    我正在尝试在 Visual Studio 2008 中执行 附加到进程 进行调试 但我无法弄清楚要附加到哪个进程 帮助 事实上它仍然是 w3wp exe 您需要检查 显示所有会话中的进程 让它显示的选项 这也让我困惑了一段时间
  • 如果不调用notify(),等待线程会发生什么?

    如果不调用notify 等待线程会发生什么 这是虚假唤醒吗 If a waiting Thread is not notified通过致电notify or notifyAll 在所述线程正在等待的对象上 则可能会发生以下任一情况 the
  • Chrome 调试协议:HeapProfiler.getHeapSnapshot 忽略回调

    我正在开发一个测试套件 作为 Chrome 扩展实现 该套件使用 Chrome Chromium 的远程调试协议以编程方式获取和分析堆快照 因为Profiler 似乎不是公共协议的一部分 我正在使用这一页 http trac webkit
  • HTML 多选框

    我只是想知道下面的表格的名称是什么 我从早上就在谷歌上搜索 HTML 表单列表 但我在任何地方都找不到这种表单 谁能告诉我这个表单的确切名称以及它是否可以在 HTML 表单中使用 我只想在我的网站中添加这种形式 它适用于 HTML 还是我应
  • 将变量传递给 Google Cloud Functions

    我刚刚在 Beta Python 3 7 运行时中使用 HTTP 触发器编写了 Google Cloud Function 现在我试图弄清楚如何在调用函数时将字符串变量传递给函数 我已阅读文档 但没有找到任何相关内容 我的触发器类似于 ht
  • 如何在光线平行且不使用光线模式的情况下运行函数?

    After sudo pip3 install ray 我创建了一个函数foo 在射线装饰器中定义 import ray ray init ray remote def foo x print x 我希望能够使用foo并行和常规模式 忽略装
  • ViewModel 和 Service 类的实例化

    我试图理解 ViewModel 和 Service 类的实例化 并将其写下来供其他人使用 请在需要的地方更正 添加 ViewModel 和服务的实例化并不是以最常见的方式完成的 这是使用反射完成的 在 TipCalc 中 您有 public
  • 在特定日期触发 UILocalNotification

    我想开火UILocalNotification在特定日期 如果我使用这段代码 NSCalendar gregorian NSCalendar alloc initWithCalendarIdentifier NSGregorianCalen
  • 尝试理解 Pytorch 的 LSTM 实现

    我有一个包含 1000 个示例的数据集 其中每个示例都有5特征 a b c d e 我想喂7LSTM 的示例 以便它预测第 8 天的特征 a 阅读 nn LSTM 的 Pytorchs 文档 我得出以下结论 input size 5 hid
  • Akka 通过可堆叠行为拦截接收

    Akka 和 Scala 新手 请根据需要随意编辑问题 以便清楚地表达我在 Scala 和 Akka 领域的意图 在展示代码片段之前 这是我想要解决的问题 我本质上想开发一个通用模块 供我的团队在使用 Akka Actor 开发应用程序时使
  • Tcl正则表达式

    set d aa1 1 set d aa2 1 set d aa3 1 set d aa4 1 set d aa5 1 set d aa6 1 set d aa7 1 set d aa8 1 set d aa9 1 set d aa10 1
  • Fortran 读取混合文本和数字

    我正在使用 Fortran 90 读取包含以下格式数据的文件 number 125 var1 2 var2 1 var3 4 number 234 var1 3 var2 5 var3 1 我尝试了以下命令并且工作正常 read 2 tem
  • Ionic Jasmine:env.stopOnSpecFailure 编译成功后不是函数

    将 Ionic 与 jasmine karma 一起使用 在运行测试时 编译成功 但在 jasmine 仪表板中出现空屏幕 控制台中出现错误 以下教程 https leifwells github io 2017 08 27 testing
  • 受范数不等式约束的二次函数最小化

    我正在尝试解决以下不等式约束 给定 N 只股票的时间序列数据 我试图构建一个投资组合权重向量以最小化回报的方差 目标函数 min w T sum w s t e n T w 1 left w right leq C where w是权重向量
  • 从外部访问 Google 地图

    我有一些 javascript 代码 可以绘制 v3 GoogleMap 我想从外部访问地图对象 另一个js文件 是否有可能不创建额外的全局变量来引用地图 单独的 JS 文件在同一范围内加载和执行 因此无论您使用一个还是多个 JS 文件 都
  • 将参数从 tasklet 步骤添加到作业上下文,并在 Spring Batch 的后续步骤中使用

    目前 我使用 jobParameters 来获取 FlatFileItemReader 和 FlatFileItemWriter 的文件名 测试我的批次是可以的 但我的目标是读取某个目录中的文件 该目录中只有这个文件 并且文件名可能会改变