Transaction Management with Spring Package

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; // return new EntiteJuridiqueWriter(); } @Bean public ProtocolListener protocolListener() { return new ProtocolListener(); } @Bean public CSVProcessListener processListener() { return new CSVProcessListener(); } @Bean public PlatformTransactionManager transactionManager2() throws Exception { EntityManagerFactory object = entityManagerFactory.getObject(); JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(object); return jpaTransactionManager; } 

[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?

+4
source share
2 answers

The problem is that you are creating a second transaction manager (transactionManager2), but Spring Batch uses a different transaction manager to start the transactions. If you use @EnableBatchProcessing, Spring Batch automatically registers the transaction manager to use for its transactions, and your JpaTransactionManager will never be used. If you want to change the transaction manager that Spring Batch uses for transactions, you need to implement the BatchConfigurer interface. Take a look at this example: https://github.com/codecentric/spring-batch-javaconfig/blob/master/src/main/java/de/codecentric/batch/configuration/WebsphereInfrastructureConfiguration.java . Here I will switch the transaction manager to WebspherUowTransactionManager and in the same way you can switch the transaction manager to another transaction manager. Here's the link to the blog post that explains it: http://blog.codecentric.de/en/2013/06/spring-batch-2-2-javaconfig-part-3-profiles-and-environments/

+9
source

You need to explicitly specify your Transaction Manager in the step definition:

 <job id="sampleJob" job-repository="jobRepository"> <step id="step1"> <tasklet transaction-manager="transactionManager"> <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/> </tasklet> </step> </job> 

See: 5.1.1. Stage setup


Ah, if you use JavaConfig, you need to assign the TaskletStepBuilder transaction TaskletStepBuilder using builder.transactionManager(transactionManager) (inherited from StepBuilderHelper )

+3
source

Source: https://habr.com/ru/post/1494288/


All Articles