かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

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 に変更します。

参照したサイト・書籍

目次

  1. build.gradle を変更する
  2. application.properties を変更する
  3. logback-spring.xml を変更する
  4. dataSource Bean の実装を変更する
  5. clean タスク → Rebuild Project → build タスクを実行する
  6. JMX への登録状況を確認する
  7. 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" &amp;&amp; "${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 が出力されました。問題ないようです。

f:id:ksby:20180805080215p:plain

JMX への登録状況を確認する

IntelliJ IDEA から Tomcat を起動した後、コマンドプロンプトから jconsole コマンドを実行します。

f:id:ksby:20180805080936p:plain

「JConsole: 新規接続」ダイアログが表示されますので、「ローカル・プロセス」の一覧から ksbysample.webapp.bootnpmgeb.Application を選択した後「接続」ボタンをクリックします。

f:id:ksby:20180805081108p:plain

JConsole の画面が表示されますので「MBeans」タグをクリックします。画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。

f:id:ksby:20180805081344p:plain

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 を選択して「接続」ボタンをクリックします。

f:id:ksby:20180805124621p:plain

IntelliJ IDEA から起動した時と同様に「MBeans」タグの画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。

f:id:ksby:20180805124813p:plain

履歴

2018/08/05
初版発行。