Java Spring 批处理 - 资源文件未注入到 tasklet 中
Java Spring Batch - Resource file is not injected into the tasklet
我正在做 java 一书中的示例 Spring Batch In Action 第 1 章。
在此示例中,tasket 解压一个 zip 文件。 tasklet 接收 zip 文件路径作为作业参数。
我实现了一个运行作业并传递参数的测试方法。
@StepScope
@Component
public class DecompressTasklet implements Tasklet {
private static final Logger LOGGER = LogManager.getLogger(DecompressTasklet.class);
@Value("#{jobParameters['inputResource']}")
private Resource inputResource;
@Value("#{jobParameters['targetDirectory']}")
private String targetDirectory;
@Value("#{jobParameters['targetFile']}")
private String targetFile;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//code here
}
}
@Configuration
public class DescompressStep {
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private DecompressTasklet decompressTasklet;
@Bean
public Step stepDescompress() {
return stepBuilderFactory
.get(DescompressStep.class.getSimpleName())
.tasklet(decompressTasklet)
.build();
}
}
@EnableBatchProcessing
@Configuration
public class ImportProductsJob {
@Autowired
private DescompressStep descompressStep;
@Autowired
private ReadWriteProductStep readWriteProductStep;
@Bean
public Job job(JobBuilderFactory jobBuilderFactory) {
return jobBuilderFactory
.get("importProductsJob")
.start(descompressStep.stepDescompress())
.next(readWriteProductStep.stepReaderWriter())
.incrementer(new RunIdIncrementer())
.build();
}
}
下面是运行作业的测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBatchTest
@AutoConfigureTestDatabase
public class ImportProductsIntegrationTest {
@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@After
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
@Test
public void importProducts() throws Exception {
jobLauncherTestUtils.launchJob(defaultJobParameters());
}
private JobParameters defaultJobParameters() {
JobParametersBuilder paramsBuilder = new JobParametersBuilder();
paramsBuilder.addString("inputResource", "classpath:input/products.zip");
paramsBuilder.addString("targetDirectory", "./target/importproductsbatch/");
paramsBuilder.addString("targetFile", "products.txt");
paramsBuilder.addLong("timestamp", System.currentTimeMillis());
return paramsBuilder.toJobParameters();
}
}
products.zip 文件在 src/main/resources/input
问题是运行测试时出现错误
java.lang.NullPointerException: null
at com.springbatch.inaction.ch01.DecompressTasklet.execute(DecompressTasklet.java:62) ~[classes/:na]
我验证了 inputResource 属性 为空。为什么会出现这个错误?
在您的职位定义中,您有:
@Bean
public Job job(JobBuilderFactory jobBuilderFactory) {
return jobBuilderFactory
.get("importProductsJob")
.start(descompressStep.stepDescompress())
.next(readWriteProductStep.stepReaderWriter())
.incrementer(new RunIdIncrementer())
.build();
}
您将步骤传递给 start
和 next
方法的方式不正确(我什至不知道这将如何编译)。您可以做的是导入步骤配置 类 并在作业定义中注入这两个步骤。类似于:
@EnableBatchProcessing
@Configuration
@Import({DescompressStep.class, ReadWriteProductStep.class})
public class ImportProductsJob {
@Bean
public Job job(JobBuilderFactory jobBuilderFactory,
Step stepDescompress, Step stepReaderWriter) {
return jobBuilderFactory
.get("importProductsJob")
.start(stepDescompress)
.next(stepReaderWriter)
.incrementer(new RunIdIncrementer())
.build();
}
}
我正在做 java 一书中的示例 Spring Batch In Action 第 1 章。 在此示例中,tasket 解压一个 zip 文件。 tasklet 接收 zip 文件路径作为作业参数。 我实现了一个运行作业并传递参数的测试方法。
@StepScope
@Component
public class DecompressTasklet implements Tasklet {
private static final Logger LOGGER = LogManager.getLogger(DecompressTasklet.class);
@Value("#{jobParameters['inputResource']}")
private Resource inputResource;
@Value("#{jobParameters['targetDirectory']}")
private String targetDirectory;
@Value("#{jobParameters['targetFile']}")
private String targetFile;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//code here
}
}
@Configuration
public class DescompressStep {
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private DecompressTasklet decompressTasklet;
@Bean
public Step stepDescompress() {
return stepBuilderFactory
.get(DescompressStep.class.getSimpleName())
.tasklet(decompressTasklet)
.build();
}
}
@EnableBatchProcessing
@Configuration
public class ImportProductsJob {
@Autowired
private DescompressStep descompressStep;
@Autowired
private ReadWriteProductStep readWriteProductStep;
@Bean
public Job job(JobBuilderFactory jobBuilderFactory) {
return jobBuilderFactory
.get("importProductsJob")
.start(descompressStep.stepDescompress())
.next(readWriteProductStep.stepReaderWriter())
.incrementer(new RunIdIncrementer())
.build();
}
}
下面是运行作业的测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBatchTest
@AutoConfigureTestDatabase
public class ImportProductsIntegrationTest {
@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@After
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
@Test
public void importProducts() throws Exception {
jobLauncherTestUtils.launchJob(defaultJobParameters());
}
private JobParameters defaultJobParameters() {
JobParametersBuilder paramsBuilder = new JobParametersBuilder();
paramsBuilder.addString("inputResource", "classpath:input/products.zip");
paramsBuilder.addString("targetDirectory", "./target/importproductsbatch/");
paramsBuilder.addString("targetFile", "products.txt");
paramsBuilder.addLong("timestamp", System.currentTimeMillis());
return paramsBuilder.toJobParameters();
}
}
products.zip 文件在 src/main/resources/input 问题是运行测试时出现错误
java.lang.NullPointerException: null
at com.springbatch.inaction.ch01.DecompressTasklet.execute(DecompressTasklet.java:62) ~[classes/:na]
我验证了 inputResource 属性 为空。为什么会出现这个错误?
在您的职位定义中,您有:
@Bean
public Job job(JobBuilderFactory jobBuilderFactory) {
return jobBuilderFactory
.get("importProductsJob")
.start(descompressStep.stepDescompress())
.next(readWriteProductStep.stepReaderWriter())
.incrementer(new RunIdIncrementer())
.build();
}
您将步骤传递给 start
和 next
方法的方式不正确(我什至不知道这将如何编译)。您可以做的是导入步骤配置 类 并在作业定义中注入这两个步骤。类似于:
@EnableBatchProcessing
@Configuration
@Import({DescompressStep.class, ReadWriteProductStep.class})
public class ImportProductsJob {
@Bean
public Job job(JobBuilderFactory jobBuilderFactory,
Step stepDescompress, Step stepReaderWriter) {
return jobBuilderFactory
.get("importProductsJob")
.start(stepDescompress)
.next(stepReaderWriter)
.incrementer(new RunIdIncrementer())
.build();
}
}