spring.datasource.hikari.jdbc-url인데 spring.datasource.hikari.url로 설정하게 되면 다음과 같은 오류가 발생하면서 실패한다.
Caused by: java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, jdbc:h2:mem:bc4ba7e6-c5cd-4c61-8406-7eb55dc03018;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
at com.zaxxer.hikari.util.DriverDataSource.<init>(DriverDataSource.java:110) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:331) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:114) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:108) ~[HikariCP-4.0.3.jar:na]
이때 수동 설정없이 jdbc-url로 설정하면, hirari.url로 설정하는 것과 동일한 오류 발생하므로 주의해야한다.
Caused by: java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, jdbc:h2:mem:5513bc19-062e-4178-89ff-164d5bde2112;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
at com.zaxxer.hikari.util.DriverDataSource.<init>(DriverDataSource.java:110) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:331) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:114) ~[HikariCP-4.0.3.jar:na]
spring.datasource.hikari : 상황에 따라 계속해서 application.yml을 수정할 수 없으므로, hikari 설정을 별도로 하면 된다.
즉, HikariCP를 사용할경우 spring.datasource로 값을 설정하기 보다는 spring.datasource.hikari로 하시면 수동/자동 구분없이, 오해없이 설정할 수 있다.
Transaction already active
java.lang.IllegalStateException: Transaction already active
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:74) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:193) ~[spring-batch-infrastructure-4.3.3.jar:4.3.3]
at org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:110) ~[spring-batch-infrastructure-4.3.3.jar:4.3.3]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:93) ~[spring-batch-infrastructure-4.3.3.jar:4.3.3]
at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:99) ~[spring-batch-core-4.3.3.jar:4.3.3]
at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:180) ~[spring-batch-core-4.3.3.jar:4.3.3]
위 오류와 같이 Transaction 오류가 발생하는 경우가 있었다. 오류의 시작 지점으로 가보니
021-12-10 01:19:49.430 ERROR 18132 --- [agingTaskPool-1] o.h.hql.internal.ast.ErrorTracker : line 1:87: unexpected token: limit
2021-12-10 01:19:49.431 ERROR 18132 --- [agingTaskPool-1] o.h.hql.internal.ast.ErrorTracker : line 1:87: unexpected token: limit
antlr.NoViableAltException: unexpected token: limit
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:1113) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3946) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
query에 오류가 있어 1번째 threadPool에서 실패를 하여 transaction rollback을 시작했는데 뒤이어서 thread 2~4가 transaction rollback을 하다 보니, 해당 오류가 발생하는 것이었다.
transaction-4
2021-12-10 01:27:51.558 DEBUG 18183 --- [agingTaskPool-4] o.s.t.support.TransactionTemplate : Initiating transaction rollback on application exception
java.lang.IllegalStateException: Transaction already active
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:74) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
transaction-3
2021-12-10 01:27:51.559 DEBUG 18183 --- [agingTaskPool-3] o.s.batch.core.step.tasklet.TaskletStep : Rollback for RuntimeException: java.lang.IllegalStateException: Transaction already active
2021-12-10 01:27:51.559 DEBUG 18183 --- [agingTaskPool-3] o.s.t.support.TransactionTemplate : Initiating transaction rollback on application exception
java.lang.IllegalStateException: Transaction already active
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:74) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
ItemWriter와 ItemReader의 Datasource설정을 따로 하여, 읽어올떄는 setReadOnly로 설정하여 해결해보고 추가로 내용 정리할 예정이다.
@SpringBootApplication(exclude =DataSourceAutoConfiguration.class)publicclassSpringBatchRealApplication {publicstaticvoidmain(String[] args) {// main thread가 종료되면 jvm 강제 종료// main thread가 종료됐다는 것은 자식 thread도 모두 종료됐다는 것을 보장System.exit(SpringApplication.exit(SpringApplication.run(SpringBatchRealApplication.class, args))); }}
main thread가 종료되면, jvm을 강제로 종료하게 되며, main thread가 종료됐다는 것은 자식 thread들이 모두 종료됐다는 것을 의미하므로 모든 task가 완료된것을 보장할 수 있다.
// 쓰레드 풀을 이용한 쓰레드 관리 방식ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();executor.setCorePoolSize(poolSize); // 풀의 기본 사이즈executor.setMaxPoolSize(poolSize); // 풀의 최대 사이즈executor.setThreadGroupName("multi-thread-"); executor.setWaitForTasksToCompleteOnShutdown(Boolean.TRUE);// allowCoreThreadTimeOut을 true로 설정해// core thread 가 일정시간 태스크를 받지 않을 경우 pool 에서 정리하고,// 모든 자식 스레드가 정리되면 jvm 도 종료 되게 설정한다.executor.setKeepAliveSeconds(30);executor.setAllowCoreThreadTimeOut(true);
allowCoreThreadTimeOut는 keppAliveSeconds로 설정한 시간이 지나면, core thread도 pool에서 정리되도록 설정하는 것이다. 특정시간이 지나 core pool에 남아있는 thread도 없게되면 종료된다.
위 설정대로 설정한 후 실행해보면 정확히 Job이 수행 완료된 후 30초 후에 종료되는 것을 볼 수 있다.
2021-12-12 22:26:19.651 DEBUG 30911 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
2021-12-12 22:26:49.649 DEBUG 30911 --- [ionShutdownHook] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@bcef303, started on Sun Dec 12 22:26:18 KST 2021
2021-12-12 22:26:49.649 DEBUG 30911 --- [ionShutdownHook] ySourcesPropertyResolver$DefaultResolver : Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
2021-12-12 22:26:49.652 DEBUG 30911 --- [ionShutdownHook] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
2021-12-12 22:26:49.653 DEBUG 30911 --- [ionShutdownHook] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans
2021-12-12 22:26:49.653 DEBUG 30911 --- [ionShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'multithreadPagingJobTaskPool'