I am integrating a spring boot project with a spring batch and data jpa project . All stuff related to job and data configuration is right except , persisting my job writer result in database . after I read a file and process it , i can't write it to mysql database . There is no error but no inserting too . interesting thing is my datasource is configured . because before inserting , I can fetch a sample record from database .please assist me to solve this problem.
my application.properties :
spring.datasource.url = jdbc:mysql://localhost:3306/batchtest? characterEncoding=UTF-8&autoReconnect=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
batch configuration:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager);
mapJobRepositoryFactoryBean.setTransactionManager(transactionManager);
return mapJobRepositoryFactoryBean.getObject();
}
@Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(jobRepository);
return simpleJobLauncher;
}
@Bean
public FlatFileItemReader<Person> reader() {
FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
reader.setResource(new ClassPathResource("sample-data.csv"));
reader.setLineMapper(new DefaultLineMapper<Person>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames(new String[] { "firstName", "lastName" });
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}});
}});
return reader;
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public ItemWriter<Person> writer() throws Exception {
return new PersonWriter();
}
@Bean
public Job importUserJob() throws Exception{
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
@Bean
public Step step1() throws Exception{
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(1)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
Dao class :
public interface PersonDao extends CrudRepository<Person,Integer> {
}
writer class :
public class PersonWriter implements ItemWriter<Person> {
@Autowired
PersonDao personDao;
@Override
public void write(List<? extends Person> items) throws Exception {
LOGGER.info("Received the information of {} students", items.size());
for(Person person:items)
{
LOGGER.info(String.format("inserting for customre %s %s", person.getFirstName(), person.getLastName()));
Person tempPerson = personDao.findOne(1);
personDao.save(person) ;
LOGGER.info(String.format("person id : %d",person.getId()));
}
}
tempPerson is an object for testing the jpa data . it fetches a person object with id 1 from database but next line there is no inserting to database with no error. just executing of the line and continue the loop.
Spring Batch is a powerful framework for developing robust batch applications. In our previous tutorial, we introduced Spring Batch. In this tutorial, we'll build on the previous one and learn how to set up and create a basic batch-driven application using Spring Boot.
The basic difference in bootstrapping an application in Spring and Spring Boot lies with the servlet. Spring uses either the web. xml or SpringServletContainerInitializer as its bootstrap entry point. On the other hand, Spring Boot uses only Servlet 3 features to bootstrap an application.
Spring Batch is a lightweight, open-source framework created to develop scalable batch processing applications. Batch processing is mostly used by applications that process a large quantity of data at a given time.
Spring Batch Integration provides the JobLaunchingMessageHandler class that you can use to launch batch jobs. The input for the JobLaunchingMessageHandler is provided by a Spring Integration message, which has a payload of type JobLaunchRequest .
A solution to this problem may be closer than expected. Did you simply try to change the name of the transactionManager bean? With a different name it won't be used by default by Spring Data JPA.
I reproduced your problem and then I simply switched from this:
@Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
to this:
@Bean
public ResourcelessTransactionManager resourcelessTransactionManager() {
return new ResourcelessTransactionManager();
}
And in my opinion that solved the problem. Remember that 'transactionManager' is the default bean name for transactionManager in Spring Data JPA (at least as far as I understand, Spring Boot auto-configures it unless it finds a Bean with that name, and if it does, it uses the one found--and your database transactions are going through a Resourceless one).
You can also skip this:
@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
return new MapJobRepositoryFactoryBean(transactionManager).getObject();
}
and call the bean directly (just to be 'more sure' that proper Transaction Manager is used with Batch):
@Bean
public JobRepository jobRepository() throws Exception {
return new MapJobRepositoryFactoryBean(resourcelessTransactionManager()).getObject();
}
Let me know when you test it, and I hope that it was the main problem :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With