Spring Boot + npm + Geb で入力フォームを作ってテストする ( その75 )( コネクションプーリング用ライブラリを Tomcat connection pool → HikariCP に切り替える )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その74 )( FindBugs 3.0.1 → SpotBugs 3.1.3 に切り替える ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot 2 からデフォルトのコネクションプーリング用ライブラリが Tomcat connection pool → HikariCP に変わりましたので、HikariCP に変更します。
参照したサイト・書籍
brettwooldridge/HikariCP
https://github.com/brettwooldridge/HikariCPSpring Boot + HikariCPでコネクションプールのMetricsを取得する
https://matsumana.info/blog/2016/02/06/spring-boot-hikaricp-metrics/Spring Boot 2.0でのHikariCPに関する変更
https://matsumana.info/blog/2017/07/04/spring-boot2-hikaricp/Unable to register MBean [HikariDataSource (HikariPool-0)] with key 'dataSource'
https://stackoverflow.com/questions/27440985/unable-to-register-mbean-hikaridatasource-hikaripool-0-with-key-datasourceSQL logging
https://github.com/brettwooldridge/HikariCP/issues/57
目次
- build.gradle を変更する
- application.properties を変更する
- logback-spring.xml を変更する
- dataSource Bean の実装を変更する
- clean タスク → Rebuild Project → build タスクを実行する
- JMX への登録状況を確認する
- Executable Jar ファイルから起動してみる
手順
build.gradle を変更する
build.gradle の dependencies block から implementation("org.apache.tomcat:tomcat-jdbc")
の行を削除します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
application.properties を変更する
Configuration を読んだのですが、おそらく HikariCP はデフォルトの設定で十分で個別に設定する必要がないと思います。よって jdbc-url, username, password, driver-class-name と気になった leak-detection-threshold だけ設定します(leak-detection-threshold もその心配がなければ削除して構わないと思います)。
また JMX への登録は Tomcat connection pool の時は spring.datasource.jmx-enabled=true
の設定で行いましたが、HikariCP では spring.datasource.hikari.register-mbeans=true
の設定で行います。
src/main/resources/application.properties を以下のように変更します。
doma.dialect=org.seasar.doma.jdbc.dialect.H2Dialect spring.datasource.hikari.jdbc-url=jdbc:h2:mem:bootnpmgebdb spring.datasource.hikari.username=sa spring.datasource.hikari.password= spring.datasource.hikari.driver-class-name=org.h2.Driver spring.datasource.hikari.leak-detection-threshold=5000 spring.datasource.hikari.register-mbeans=true spring.session.store-type=jdbc ..........
また src/main/resources/application-product.properties から以下の5行の設定を削除します。
slowquery.logging.file=${server.tomcat.basedir}/logs/slow-query.log
spring.datasource.tomcat.initialSize=2
spring.datasource.tomcat.maxActive=2
spring.datasource.tomcat.maxIdle=2
spring.datasource.tomcat.minIdle=2
logback-spring.xml を変更する
Tomcat connection pool の SlowQueryReport interceptor がなくなりましたので、<if condition='"${spring.profiles.active}" == "product" && "${slowquery.logging.file}" != ""'> ... </if>
の設定を削除します。
dataSource Bean の実装を変更する
src/main/java/ksbysample/webapp/bootnpmgeb/config/ApplicationConfig.java の以下の点を変更します。
@Configuration @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) public class ApplicationConfig { .......... /** * @return HikariCP の DataSource オブジェクト */ @Bean @ConfigurationProperties("spring.datasource.hikari") public DataSource dataSource() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } }
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
を追加します。@ConfigurationProperties("spring.datasource.tomcat")
→@ConfigurationProperties("spring.datasource.hikari")
に変更します。.type(org.apache.tomcat.jdbc.pool.DataSource.class)
→.type(HikariDataSource.class)
に変更します。
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
を付けていないと Executable Jar から起動しようとした時に以下の例外が発生して起動しません(IntelliJ IDEA の時は起動します)。
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [HikariDataSource (HikariPool-1)] with key 'dataSource'; nested exception is javax.management.InstanceAlreadyExistsException: MXBean already registered with name com.zaxxer.hikari:type=PoolConfig (HikariPool-1) at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:625) at org.springframework.jmx.export.MBeanExporter.lambda$registerBeans$2(MBeanExporter.java:551) at java.util.HashMap.forEach(HashMap.java:1289) at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:551) at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:434) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) at ksbysample.webapp.bootnpmgeb.Application.main(Application.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) Caused by: javax.management.InstanceAlreadyExistsException: MXBean already registered with name com.zaxxer.hikari:type=PoolConfig (HikariPool-1) at com.sun.jmx.mbeanserver.MXBeanLookup.addReference(MXBeanLookup.java:151) at com.sun.jmx.mbeanserver.MXBeanSupport.register(MXBeanSupport.java:160) at com.sun.jmx.mbeanserver.MBeanSupport.preRegister2(MBeanSupport.java:173) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:930) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324) at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:137) at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:671) at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:615) ... 22 common frames omitted
clean タスク → Rebuild Project → build タスクを実行する
clean タスク → Rebuild Project → build タスクを実行すると BUILD SUCCESSFUL が出力されました。問題ないようです。
JMX への登録状況を確認する
IntelliJ IDEA から Tomcat を起動した後、コマンドプロンプトから jconsole コマンドを実行します。
「JConsole: 新規接続」ダイアログが表示されますので、「ローカル・プロセス」の一覧から ksbysample.webapp.bootnpmgeb.Application を選択した後「接続」ボタンをクリックします。
JConsole の画面が表示されますので「MBeans」タグをクリックします。画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。
Executable Jar ファイルから起動してみる
生成された build/libs/boot-npm-geb-sample-1.0.2-RELEASE.jar を C:\webapps\boot-npm-geb-sample\lib の下にコピーした後、C:\webapps\boot-npm-geb-sample\bat\webapp_startup.bat をコマンドプロンプトから起動します。
入力画面1~3で入力して確認画面→送信画面まで進めても特にエラーは発生しませんでした。ただし、今回ログを見ていて気づきましたが、Spring Session が生成している SESSION Cookie の domain 属性が null? とか、httponly 属性が false?とかなんかいろいろ問題がありそうです。。。 次回以降で調査してみます。
[req][cookie] name = SESSION, value = MThlNDQ3NGUtNmQ0Mi00Y2Q2LTlmNTYtMDA4ZDZlYjg3NTQ3, domain = null, path = null, maxage = -1, secure = false, httponly = false
JMX の登録状況も確認します。コマンドプロンプトから jconsole コマンドを実行した後、「JConsole: 新規接続」ダイアログの「ローカル・プロセス」の一覧から boot-npm-geb-sample-1.0.2-RELEASE.jar を選択して「接続」ボタンをクリックします。
IntelliJ IDEA から起動した時と同様に「MBeans」タグの画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。
履歴
2018/08/05
初版発行。