1
votes

I'm basically new to spring batch. For my first step I am getting a file from an SFTP server and transferring it to a local directory using JSch. For the second step, I read the file in my local directory and write the contents in my DB. The problem is that there are instances wherein only saveWithdrawalTransaction (step2) executes and not getRemoteFile (step1)

execution from db

Configuration Class:

@Qualifier("writer")
@Autowired
JdbcBatchItemWriter<TopUpTransaction> writer;

@Qualifier("reader")
@Autowired
FlatFileItemReader<TopUpTransaction> reader;

@Bean(name="importWithdrawalTransactionJob")
public Job importWithdrawalTransactionJob() throws Exception {
    return jobBuilderFactory.get("importWithdrawalTransactionJob")
            .incrementer(new RunIdIncrementer())
            .start(getRemoteFile()).on(ExitStatus.FAILED.getExitCode()).end()
            .next(saveWithdrawalTransaction()).end()
            .build();
}

@Bean
public GetRemoteFileTasklet sFtpGetRemoteFilesTasklet() {
    return new GetRemoteFileTasklet();
}

@Bean
public Step getRemoteFile() throws Exception {
    return stepBuilderFactory.get("getRemoteFile")
            .tasklet(sFtpGetRemoteFilesTasklet())
            .build();
}

@Bean
public Step saveWithdrawalTransaction() throws Exception {
    return stepBuilderFactory.get("saveWithdrawalTransaction")
            .<TopUpTransaction, TopUpTransaction> chunk(1)
            .reader(reader)
            .processor(processor())
            .writer(writer)
            .build();
}

Reader:

@Bean
public FlatFileItemReader<TopUpTransaction> reader() throws Exception {

File folder = new File(csvFilePath);
File filesToProcess[] = folder.listFiles();
FlatFileItemReader<TopUpTransaction> reader = new FlatFileItemReader<TopUpTransaction>();

if (filesToProcess.length > 0) {
for (File file : filesToProcess) {
    if (file.isFile()) {
        System.out.println(file.getName());
        reader.setResource( new FileSystemResource(file.getAbsolutePath()));
        reader.setLineMapper(new DefaultLineMapper<TopUpTransaction>() {{
            setLineTokenizer(new DelimitedLineTokenizer() {{
                setNames(new String[] { "lineIdentifier","transactionDate", "beneAccNum", "beneAccName", "senderName", "senderInfo",
                        "creditedAmountWithCurrency", "originalAmountWithCurrency", "netAmountWithCurrency", 
                        "charges", "otherInfo1", "otherInfo2",
                        "ubTransactionId"});
                setDelimiter("|");
            }});
            setFieldSetMapper(new CustomTopUpMapper());          
        }});
        reader.setRecordSeparatorPolicy(new CustomReaderPolicy());
        System.out.println("end read");
        file.renameTo(new File(file.getName() + "-processed"));
    }
}

Writer:

@Bean(name="writer")
public JdbcBatchItemWriter<TopUpTransaction> writer() {

    StringBuffer insertWithdrawalTransaction = new StringBuffer();
    insertWithdrawalTransaction.append("INSERT INTO top_up_transactions (customer_id,txn_date, bene_acc_num, bene_acc_name,");
    insertWithdrawalTransaction.append("sender_name, sender_info, credited_amount, credited_currency,");
    insertWithdrawalTransaction.append("original_amount, original_currency,");
    insertWithdrawalTransaction.append("net_amount, net_currency, charges, other_info_1, other_info_2,");
    insertWithdrawalTransaction.append("ubp_txn_id,status) ");
    insertWithdrawalTransaction.append("VALUES (:customerId, :transactionDate,:beneAccNum,");
    insertWithdrawalTransaction.append(":beneAccName,:senderName,:senderInfo,:creditedAmount,:creditedAmountCurrency,");
    insertWithdrawalTransaction.append(":originalAmount,:originalAmountCurrency,");
    insertWithdrawalTransaction.append(":netAmount,:netAmountCurrency,:charges,:otherInfo1,:otherInfo2,");
    insertWithdrawalTransaction.append(":ubTransactionId,:status)");
    System.out.println("start write");
    JdbcBatchItemWriter<TopUpTransaction> writer = new JdbcBatchItemWriter<TopUpTransaction>();
    writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<TopUpTransaction>());
    writer.setSql(insertWithdrawalTransaction.toString());
    writer.setDataSource(dataSource);
    System.out.println("end write");

    return writer;
}

Tasklet:

public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception
{
    Session session = null;
    Channel channel = null;
    //deleteLocalFiles();
    System.out.println("=====start tasklet=====");
    try {
        JSch ssh = new JSch();
        session = ssh.getSession("username", "host", 22);
        session.setPassword("password");
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp sftp = (ChannelSftp) channel;
        sftp.get("*.rpt", "src/main/resources/files/");
    } catch (JSchException e) {
        e.printStackTrace();
    } catch (SftpException e) {
        e.printStackTrace();
    } finally {
        if (channel != null) {
            channel.disconnect();
        }
        if (session != null) {
            session.disconnect();
        }
    }

I don't have an idea how to go about this... I have been trying out stuff I found from everywhere. Please help thank you!

1
I'm not confident with JavaConfig but are calls to .end() after every placed correctly?Luca Basso Ricci
Is in your spring batch configure that if step1 fail it will not get to step 2.if First step failed then file is not available so what step 2 and step3 are doing,gati sahu
My goal is that if step1 fails batch ends. If step1 completed batch continues. I also tried this .start(getRemoteFile()).on("COMPLETED").to(saveWithdrawalTransaction()).end still having the same problem @LucaBassoRicciDands Manuel
My goal is that if step1 fails batch ends. If step1 completed batch continues. I also tried this .start(getRemoteFile()).on("COMPLETED").to(saveWithdrawalTra‌​nsaction()).end still having the same problem @gatisahuDands Manuel

1 Answers

0
votes

You can use JobExecutionDeciderdecision to control flow during failure.

for Xml something this you can mentioned

<decision id="decision" decider="decider">
            <next on="FAILED" to="step2" />
            <next on="COMPLETED" to="step3" />
        </decision>

or

jobs.get("job")
           .preventRestart()
           .listener(failedCleanupListener)
           .flow(step1)
           .next(step2)
           .next(step3)
           .end()
           .build();