I really discover Spring, and I can set up some jobs. Now I would like to save the imported data in the database using Hibernate / JPA, and I keep getting this error:
14:46:43.500 [main] ERROR osbcore.step.AbstractStep - Encountered an error executing the step javax.persistence.TransactionRequiredException: no transaction is in progress
I see that the problem is related to the transaction. Here is my Spring java config for entityManager and transactionManager :
@Configuration public class PersistenceSpringConfig implements EnvironmentAware { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception { // Initializes the entity manager LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setPersistenceUnitName(PERSISTENCE_UNIT_NAME); factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); factoryBean.setDataSource(dataSource()); // Scans the database model factoryBean.setPackagesToScan(EntiteJuridiqueJPA.class.getPackage().getName()); // Defines the Hibernate properties Properties jpaProperties = new Properties(); jpaProperties.setProperty("hibernate.show_sql", "false"); jpaProperties.setProperty("hibernate.format_sql", "false"); String connectionURL = "jdbc:h2:file:" + getDatabaseLocation(); jpaProperties.setProperty("hibernate.connection.url", connectionURL); jpaProperties.setProperty("hibernate.connection.username", "sa"); jpaProperties.setProperty("hibernate.connection.driver_class", "org.h2.Driver"); jpaProperties.setProperty("hibernate.dialect", H2Dialect.class.getName()); jpaProperties.setProperty("hibernate.hbm2ddl.auto", "create"); jpaProperties.setProperty("hibernate.hbm2ddl.import_files_sql_extractor", "org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor"); jpaProperties.setProperty("hibernate.hbm2ddl.import_files", "org/springframework/batch/core/schema-drop-h2.sql,org/springframework/batch/core/schema-h2.sql"); factoryBean.setJpaProperties(jpaProperties); return factoryBean; } @Bean public PlatformTransactionManager transactionManager2() throws Exception { EntityManagerFactory object = entityManagerFactory().getObject(); JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(object); return jpaTransactionManager; }
I use JpaItemWriter to store data in a database:
@Bean public ItemWriter<EntiteJuridiqueJPA> writer() { JpaItemWriter<EntiteJuridiqueJPA> writer = new JpaItemWriter<EntiteJuridiqueJPA>(); writer.setEntityManagerFactory(entityManagerFactory.getObject()); return writer; }
This is the code that throws the exception: javax.persistence.TransactionRequiredException: no transaction is in progress
Any idea how to solve this problem?
[Edit] I also put the definition of the job and the definition of the step. All my Spring configuration is written in Java.
@Configuration @EnableBatchProcessing @Import(PersistenceSpringConfig.class) public class BatchSpringConfig { @Autowired private JobBuilderFactory jobBuilders; @Autowired private StepBuilderFactory stepBuilders; @Autowired private DataSource dataSource; @Autowired private LocalContainerEntityManagerFactoryBean entityManagerFactory; @Bean public Step step() { return stepBuilders.get("step").<EntiteJuridique, EntiteJuridiqueJPA> chunk(5).reader(cvsReader(null)) .processor(processor()).writer(writer()).listener(processListener()).build(); } @Bean @StepScope public FlatFileItemReader<EntiteJuridique> cvsReader(@Value("#{jobParameters[input]}") String input) { FlatFileItemReader<EntiteJuridique> flatFileReader = new FlatFileItemReader<EntiteJuridique>(); flatFileReader.setLineMapper(lineMapper()); flatFileReader.setResource(new ClassPathResource(input)); return flatFileReader; } @Bean public LineMapper<EntiteJuridique> lineMapper() { DefaultLineMapper<EntiteJuridique> lineMapper = new DefaultLineMapper<EntiteJuridique>(); DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(";"); lineTokenizer.setNames(new String[] { "MEGA_ENTITE", "PORTEFEUILLE", "MEGA_ENTITE", "LibellΓ©" }); BeanWrapperFieldSetMapper<EntiteJuridique> fieldSetMapper = new BeanWrapperFieldSetMapper<EntiteJuridique>(); fieldSetMapper.setTargetType(EntiteJuridique.class); lineMapper.setLineTokenizer(lineTokenizer); lineMapper.setFieldSetMapper(fieldSetMapper); return lineMapper; } @Bean public Job dataInitializer() { return jobBuilders.get("dataInitializer").listener(protocolListener()).start(step()).build(); } @Bean public ItemProcessor<EntiteJuridique, EntiteJuridiqueJPA> processor() { return new EntiteJuridiqueProcessor(); } @Bean public ItemWriter<EntiteJuridiqueJPA> writer() { JpaItemWriter<EntiteJuridiqueJPA> writer = new JpaItemWriter<EntiteJuridiqueJPA>(); writer.setEntityManagerFactory(entityManagerFactory.getObject()); return writer;
[EDIT] I am still sticking to this issue. I followed @Sean Patrick Floyd and @bellabax's suggestions by installing a transaction manager for stepBuilders, but I still get the same exception. I tested my entityManager independently of spring-batch, and I can store any data in the database.
But when using the same entity manager with Spring package, I have this exception.
Can anyone give more information on how to manage transactions in a Spring package? thanks for your help?