简体   繁体   中英

Can I use placeholders in an @Value annotated Resource?

I am trying to build a Spring Batch job, where the user gives the path to a directory as the input. In this directory is a csv-file and the name of this file is always different. I am defining my ItemReader with this Java Config:

@Bean
@StepScope
public FlatFileItemReader<MyObject> itemReader(
        @Value("file:#{jobParameters['directory']}/*.csv") final Resource resource,
        final DefaultLineMapper<MyObject> lineMapper) {
    final FlatFileItemReader<MyObject> reader = new FlatFileItemReader<>();

    reader.setResource(resource);
    reader.setLinesToSkip(1);
    reader.setLineMapper(lineMapper);

    return reader;
}

When I run the job I get the following error:

Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode): URL [file:C:/path/to/directory/*.csv]
    at org.springframework.batch.item.file.FlatFileItemReader.doOpen(FlatFileItemReader.java:251)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144)
    ... 26 more

Obviously it is not possible to use an asterisk as a placeholder at this place. Is there any other way to get the path of the csv file dynamically?

If you are sure about the directory and there is only one CSV file always, then you can go for create File object for the directory and get the first item from listFiles() , then create the Resource object, as shown below:

public FlatFileItemReader<MyObject> itemReader(
        @Value("file:#{jobParameters['directory']}") final String resourceDir,
        final DefaultLineMapper<MyObject> lineMapper) {

        File[] files=new File(resourceDir).listFiles(); // you can try giving FileNameFilter for .csv
        File csvFile=files[0]; // do null check and isempty
        // create Resource
        Resource resource = new FileSystemResource(csvFile);
    final FlatFileItemReader<MyObject> reader = new FlatFileItemReader<>();

    reader.setResource(resource);
    reader.setLinesToSkip(1);
    reader.setLineMapper(lineMapper);

    return reader;
}

Or, if the .csv file name has any static prefix or suffix you can try with the existing code itself. Please check section 6.7.2 Wildcards in application context constructor resource paths here . For example, suppose in your case the .csv file has a pattern abc*.csv :

 @Value("file:#{jobParameters['directory']}/abc*.csv")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM