I am trying to use transaction in SpringBoot app , for some reason it just doesn’t work. Below is the code for the sample app. I have a rest api in MyRestController.java which invokes DBService.hello() method. In hello() method I insert a row into a table using JOOQ. I see transaction is NOT being created , after further debugging I see that DataSourceTransactionManager.doBegin() method is not being invoked, which explains why transaction is not created. Can any one point what is wrong with this simple code?
@SpringBootApplication @EnableTransactionManagement(proxyTargetClass = true) public class JooqtransactionApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(JooqtransactionApplication.class, args); } }
MyRestController.java
@RestController public class MyRestController { @Autowired DBService DBService; @GetMapping("/callHello") void invokeHello() { DBService.hello(); } }
DBService.java
@Service public class DBService { @Autowired DSLContext ctx; @Transactional() void hello() { ctx.insertInto(Prospectiveclient.PROSPECTIVECLIENT).values("val1", "val2", "val3", "", LocalDateTime.now()).execute(); } }
Creation of Beans
@Configuration public class GlobalConfiguration { @Autowired private Environment environment; @Bean DataSource dataSource() { HikariConfig config = new HikariConfig(); HikariDataSource ds; config.setDriverClassName("com.mysql.cj.jdbc.Driver"); config.setJdbcUrl("jdbc:mysql://localhost:3306/qadb"); config.setUsername("admin"); config.setPassword("pass"); return new HikariDataSource(config); } @Bean public TransactionAwareDataSourceProxy transactionAwareDataSource() { return new TransactionAwareDataSourceProxy(dataSource()); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public DataSourceConnectionProvider connectionProvider() { return new DataSourceConnectionProvider(transactionAwareDataSource()); } @Bean public ExceptionTranslator exceptionTransformer() { return new ExceptionTranslator(); } @Bean public DefaultDSLContext dsl() { return new DefaultDSLContext(configuration()); } @Bean public DefaultConfiguration configuration() { DefaultConfiguration jooqConfiguration = new DefaultConfiguration(); jooqConfiguration.set(connectionProvider()); jooqConfiguration.set(new DefaultExecuteListenerProvider(exceptionTransformer())); SQLDialect dialect = SQLDialect.valueOf("MYSQL"); jooqConfiguration.set(dialect); return jooqConfiguration; } }
Advertisement
Answer
Method visibility and @Transactional
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.