3

I am currently developing a Spring Batch which converts an Excel (.xsls) file to CSV in first step and then reads the CSV, processes it and stores its data in database. The first step works well. The batch stops at the second step throwing this warning: Input resource does not exist class path resource [C:/work/referentielAgenceCE.csv]. Here after my code:

spring-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:batch="http://www.springframework.org/schema/batch"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/batch
    http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">

    <!-- import config Spring générale -->
    <import resource="classpath*:spring/***-batch-spring.xml" />

    <bean id="pathFichier" class="java.lang.String">
        <constructor-arg value="${batch.referentielAgenceCE.inputFilePathCSV}" />
    </bean>

    <batch:job id="simpleFileImportJob" xmlns="http://www.springframework.org/schema/batch">
        <batch:step id="convertStep" next="processingStep">
            <batch:tasklet ref="convert"/>
        </batch:step>
        <batch:step id="processingStep">
            <batch:tasklet>
                <batch:chunk reader="agenceCEReader" processor="agenceCEProcessor" writer="agenceCEWriter" 
                    commit-interval="5" />              
            </batch:tasklet>
        </batch:step>
    </batch:job>

    <bean id="convert"
        class="com.***.referentielAgenceCE.convertTasklet.convertXLSXtoCVS" />

    <!-- Reader -->
    <bean id="agenceCEReader" scope="step"
        class="org.springframework.batch.item.file.FlatFileItemReader">     
        <property name="strict" value="false" />
        <property name="resource" ref="pathFichier" />
        <property name="linesToSkip" value="1" />
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer">
                    <bean
                        class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                        <property name="delimiter" value=";" />
                        <property name="names"
                            value="Date Création,Date Dernière modif.,Date Début Validité,Date Fin Validité,Caisse,Identifiant Agence,Libellé Agence,Type Agence,Libellé Type Agence,Téléphone,Fax,2EME Ligne Adresse,3EME Ligne Adresse,4EME Ligne Adresse,5EME Ligne Adresse,6EME Ligne Adresse,Pays,Ville,Identifiant Niv. 1,Type Niv. 1,Libellé Niv. 1,Identifiant Niv. 2,Type Niv. 2,Libellé Niv. 2,Identifiant Niv. 3,Type Niv. 3,Libellé Niv. 3,Identifiant Niv. 4,Type Niv. 4,Libellé Niv. 4,Identifiant Niv. 5,Type Niv. 5,Libellé Niv. 5,Identifiant Niv. 6,Type Niv. 6,Libellé Niv. 6,Identifiant Niv. 7,Type Niv. 7,Libellé Niv. 7,Identifiant Niv. 8,Type Niv. 8,Libellé Niv. 8,Identifiant Niv. 9,Type Niv. 9,Libellé Niv. 9,Identifiant Niv. 10,Type Niv. 10,Libellé Niv. 10,Identifiant Niv. 11,Type Niv. 11,Libellé Niv. 11,Identifiant Niv. 12,Type Niv. 12,Libellé Niv. 12,Identifiant Niv. 13,Type Niv. 13,Libellé Niv. 13,Identifiant Niv. 14,Type Niv. 14,Libellé Niv. 14,Jours/Heures Ouverture,Code Etat" />
                    </bean>
                </property>
                <property name="fieldSetMapper">
                    <bean
                        class="com.***.referentielAgenceCE.mapping.AgenceCEFieldSetMapper" />
                </property>
            </bean>
        </property>
    </bean>

    <!-- Processor -->
    <bean id="agenceCEProcessor" 
        class="com.***.referentielAgenceCE.processor.AgenceCEItemProcessor"/>

    <!-- Writer -->
    <bean id="agenceCEWriter"
        class="com.***.referentielAgenceCE.writer.AgenceCEItemWriter" />
</beans>

Step 1 - convertXLSXtoCVS.java:

public class convertXLSXtoCVS implements Tasklet, InitializingBean{


    @Value("${batch.referentielAgenceCE.inputFilePathXLSX}")
    private String inputFile;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
            throws Exception {
        System.out.println("convertXLSXtoCVS.execute1");
        // For storing data into CSV files                
        StringBuffer data = new StringBuffer();                
        try {
            File outputFile = new File(getOutputFile(inputFile));
            FileWriter fw = new FileWriter(outputFile.getPath());

            BufferedWriter  fos = new BufferedWriter(fw);

            // Get the workbook object for XLSX file
            XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile));

            // Get first sheet from the workbook
            XSSFSheet sheet = wBook.getSheetAt(0);
            Row row;
            Cell cell;

            // Iterate through each rows from first sheet
            Iterator<Row> rowIterator = sheet.iterator();
            while (rowIterator.hasNext()) {
                row = rowIterator.next();
                // For each row, iterate through each columns
                Iterator<Cell> cellIterator = row.cellIterator();
                while (cellIterator.hasNext()) {
                    cell = cellIterator.next();
                    switch (cell.getCellType()) {
                        case Cell.CELL_TYPE_BOOLEAN:                                                
                            data.append(cell.getBooleanCellValue() + ",");                                                
                            break;                                        
                        case Cell.CELL_TYPE_NUMERIC:                                                
                            data.append(cell.getNumericCellValue() + ",");                                                
                            break;                                        
                        case Cell.CELL_TYPE_STRING:                                                
                            data.append(cell.getStringCellValue() + ",");                                                
                            break;                                        
                        case Cell.CELL_TYPE_BLANK:                                                
                            data.append("" + ",");                                                
                            break;
                        default:                                                
                            data.append(cell + ",");
                    }
                }
            }
            fos.write(data.toString());
            fos.close();
        }catch (Exception ioe) {
            ioe.printStackTrace();
        }
        return RepeatStatus.FINISHED;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(inputFile, "inputFile must be set");

    }

    public String getOutputFile(String inputFile){
        String[] parts = inputFile.split("\\.");
        return parts[0]+"."+parts[1].replace("xlsx", "csv");
    }

}

I mention the file paths in a properties file as follow:

batch.referentielAgenceCE.inputFilePathXLSX=C\:\\work\\referentielAgenceCE.xlsx
batch.referentielAgenceCE.inputFilePathCSV=C\:\\work\\referentielAgenceCE.csv

When I delete from the spring-config.xml in the reader definintion, I get the following error :

org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:137)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy44.open(Unknown Source)
    at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:93)
    at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:301)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:192)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
    at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:349)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:574)
Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode): URL [file://work//referentielAgenceCE.csv]
    at org.springframework.batch.item.file.FlatFileItemReader.doOpen(FlatFileItemReader.java:250)
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:134)
    ... 27 more

3 Answers 3

5

I found the solution. I should just add 'file:' to the output cvs file path. so it should be like this :

batch.referentielAgenceCE.inputFilePathCSV=file\:C\:\\work\\referentielAgenceCE.csv instead of C\:\\work\\referentielAgenceCE.csv
Sign up to request clarification or add additional context in comments.

Comments

1

Seeing :

Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode): URL [file://work//referentielAgenceCE.csv]

And more precisely :

file://work//referentielAgenceCE.csv

I think you need to replace :

batch.referentielAgenceCE.inputFilePathXLSX=C\:\\work\\referentielAgenceCE.xlsx
batch.referentielAgenceCE.inputFilePathCSV=C\:\\work\\referentielAgenceCE.csv

by

batch.referentielAgenceCE.inputFilePathXLSX=C:\\work\\referentielAgenceCE.xlsx
batch.referentielAgenceCE.inputFilePathCSV=C:\\work\\referentielAgenceCE.csv

8 Comments

@NabilSalah Try with file: before the driver letter (file:C:\\work\\referentielAgenceCE.xlsx)
Worst this time it return the following error : file:C:\\work\\referentielAgenceCE.xlsx does not exist
@NabilSalah Can you try with slashes instead of backslashes? C:/work/referentielAgenceCE.xlsx
still the first warning : WARN | Input resource does not exist class path resource [C:/work/referentielAgenceCE.csv]. I think it is not due to the file path.
After debbuging I noticed that the file is created in the same time the second step starts (the step where we read the CSV). I do not know if there is a way to make a break between the two steps ?
|
0

You may not be a dealing with a Resource object. It may be a String object. Something like filename.

Refer the batch_job_execution_params table's parameter_type field.

Reference Code Snippets

    @Bean
@StepScope
FlatFileItemReader<String> sanityReader(@Value("#{jobParameters['fileName']}") String inputFile) {
    FlatFileItemReader<String> itemReader = new FlatFileItemReader<>();
    itemReader.setResource(new FileSystemResource(inputFile));
    itemReader.setName("sanityReader");
    itemReader.setLineMapper(new PassThroughLineMapper());
    itemReader.setStrict(false);
    return itemReader;
}

    @Bean
Step sanityCheckStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new StepBuilder("SanityCheckStep", jobRepository)
            .<String, String>chunk(0, transactionManager)
            .reader(sanityReader(null))
            .processor(sanityCheckProcessor())
            .writer(sanityCheckWriter())
            .allowStartIfComplete(true).build();
}

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.