Search code examples
spring-data-jpaspring-batchspring-repositoriesjava-17

Spring batch RepositoryItemWriter not working


I have a scenario where a given json file Employee.json needs to be read to Employee object and then written to employee table in mysql database in a batch process.

Employee.json:

    [
      {
        "firstName": "John",
        "lastName":"Snow",
        "age":30
      },
      {
        "firstName": "Tony",
        "lastName": "Stark",
        "age": 40
      },
      {
        "firstName": "Peter",
        "lastName":"Parker",
        "age":35
      }
    ]

Employee.java :

import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Data
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private int age;
}

I used the JsonItemReader for reading the file from my resource location and RepositoryItemWriter for persisting the employee object.

This is how my batch config looks:

@Configuration
@ComponentScan(basePackages = "za.co.sanlam.employee")
@EnableBatchProcessing
@EnableTransactionManagement
public class DataInsertJsontoMysqlJob {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    PlatformTransactionManager platformTransactionManager;

    @Autowired
    LocalContainerEntityManagerFactoryBean entityManagerFactory;

    @Value("input/Employee.json")
    private Resource inputjson;

    @Bean(name = "insertDataJob")
    public Job job(@Qualifier("step1") Step step1) {
        return jobBuilderFactory.get("insertDataJob").incrementer(new RunIdIncrementer()).start(step1).build();
    }

    @Bean
    protected Step step1(ItemWriter writer) throws ParseException {

        return stepBuilderFactory
                .get("step1")
                .transactionManager(platformTransactionManager)
                .<Employee, Employee>chunk(2)
                .reader(jsonItemReader())
                .writer(writer)
                .build();
    }

    @Bean
    public JsonItemReader<Employee> jsonItemReader() {
        return new JsonItemReaderBuilder<Employee>()
                .jsonObjectReader(new JacksonJsonObjectReader<>(Employee.class))
                .resource(inputjson)
                .name("jsonItemReader")
                .build();
    }

    @Bean
    public RepositoryItemWriter<Employee> writer(EmployeeRepository repository) {
        final RepositoryItemWriter<Employee> repositoryItemWriter = new RepositoryItemWriter<>();
        repositoryItemWriter.setRepository(repository);
        repositoryItemWriter.setMethodName("save");
        return repositoryItemWriter;
    }
}

Even though the item writer code is executed no data is getting persisted to the Employee table on my local mysql database. The application is able to connect to the database successfully and all the spring batch related tables are getting populated.

I was able to write the data to the Employee table if i use JdbcBatchItemWriter instead of RepositoryItemWriter:

    @Bean //WORKING
    public JdbcBatchItemWriter<Employee> writer(DataSource dataSource) {
    JdbcBatchItemWriter<Employee> itemWriter = new JdbcBatchItemWriter<>();

    itemWriter.setDataSource(dataSource);
    itemWriter.setSql("insert into Employee (firstName,lastName,age) values (:firstName,:lastName,:age)");
    itemWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());
    itemWriter.afterPropertiesSet();

    return itemWriter;
}

I am not including my databaseconfiguration class here.

What am i missing while using RepositoryItemWriter ?


Solution

  • I guess EmployeeRepository uses a JPA-based implementation. If this is the case, the cause of the issue would be that the platformTransactionManager injected on your step is of type DataSourceTransactionManager while it should be JpaTransactionManager.

    Make sure you are using a JpaTransactionManager on your step and job repository when using RepositoryItemWriter.