springspring-bootspring-batchbatch-processingdata-migration

spring batch RepositoryItemWriter doesnt write data to database


@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource appDataSource() {
        DataSourceBuilder builder = DataSourceBuilder.create();
        builder.driverClassName("org.mariadb.jdbc.Driver");
        builder.url("jdbc:mariadb://localhost:3306/people");
        builder.username("user");
        builder.password("pwd");
        return builder.build();
    }
}

@Configuration
public class BatchConfiguration {

    // tag::readerwriterprocessor[]
    @Autowired
    private DataSource dataSource;

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }

    @Bean
    public FlatFileItemReader<Person> reader() {
        return new FlatFileItemReaderBuilder<Person>()
            .name("personItemReader")
            .resource(new ClassPathResource("sample-data.csv"))
            .delimited()
            .names(new String[]{"firstName", "lastName"})
            .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                setTargetType(Person.class);
            }})
            .build();
    }

    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public JdbcBatchItemWriter<People> writer() {
        JdbcBatchItemWriter<People> writer = new JdbcBatchItemWriter<>();
        writer.setDataSource(dataSource);
        writer.setSql("INSERT INTO people (first_name, last_name) VALUES (?, ?)");
        writer.setItemPreparedStatementSetter((item, ps) -> {
            ps.setString(1, item.getFirstName());
            ps.setString(2, item.getLastName());

            // Log the item being processed
            System.out.println("Processing item: " + item);
        });
        return writer;
    }


    // end::readerwriterprocessor[]

    // tag::jobstep[]
    @Bean
    public Job importUserJob(JobRepository jobRepository,
            JobCompletionNotificationListener listener, Step step1) {
        return new JobBuilder("importUserJob", jobRepository)
            .incrementer(new RunIdIncrementer())
            .listener(listener)
            .flow(step1)
            .end()
            .build();
    }

    @Bean
    public Step step1(JobRepository jobRepository,
                      JpaTransactionManager transactionManager, JdbcBatchItemWriter<People> writer) {
        return new StepBuilder("step1", jobRepository)
            .<Person, People> chunk(10, transactionManager)
            .reader(reader())
            .processor(processor())
            .writer(writer)
            .build();
    }
    // end::jobstep[]
}

@SpringBootApplication
@EnableBatchProcessing(dataSourceRef ="appDataSource")
public class BatchProcessingApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(BatchProcessingApplication.class, args);
    }
}

The problem I'm facing is that it doesn't write any data to the mariadb database. It automatically creates database tables, so the connection doesn't seem to be the issue. However, when I use an in-memory database, it successfully writes data. There are no errors in the logs, but the Spring Batch jobs don't seem to start, Pom file is also given below

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>batch-processing-complete</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>batch-processing-complete</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>3.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

If someone could assist me with this issue, I would greatly appreciate it


Solution

  • the Spring Batch jobs don't seem to start

    With Spring Boot 3, there is no need for @EnableBatchProcessing. If you add it, the auto-configuration of Spring Batch (including the automatic launching of jobs at startup) will back off.

    This is mentioned in the migration guide of Spring Boot 3.

    The problem I'm facing is that it doesn't write any data to the mariadb database.

    This is because you are using a JpaTransactionManager but your step does not use any JPA reader or writer (you have a FlatFileItemReader and JdbcBatchItemWriter). Changing the transaction manager to a JdbcTransactionManager should solve your issue.