無料のSSL証明書をインストールする

※2022/04/25追記 無料のSSL証明書をインストールする(Ubuntu 22.04版)を公開。

No-IPドメインでLet’s Encryptの証明書を使うことが出来る。

1.事前確認
・ドメイン名を取得していること(今回はNo-IPを使用する)
・80、443ポートが外部に開放されていること

2.Certbotをインストールする

yum install epel-release
yum install certbot python-certbot-apache

3.証明書取得する

certbot certonly --agree-tos --webroot -w /var/www/html/ -d hoge.no-ip.org

取得に成功した場合、証明書は以下に保存される。

ll /etc/letsencrypt/live/hoge.no-ip.org/

4.Apacheに証明書を設定し再起動する

バージョン2.4.7以前の場合

SSLCertificateFile /etc/letsencrypt/live/hoge.no-ip.org/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/hoge.no-ip.org/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/hoge.no-ip.org/chain.pem

バージョン2.4.8以降の場合

SSLCertificateFile /etc/letsencrypt/live/hoge.no-ip.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/hoge.no-ip.org/privkey.pem
systemctl restart httpd

5.証明書を自動的に更新する

証明書は90日で失効してしまうため、cron.dに以下のスクリプトを置いておく。
有効期限の30日前になると自動的に更新されるので、とりあえず毎日か、毎週実行する様にしておけば良い。

#!/bin/sh

/bin/certbot renew --webroot-path /var/www/html/ --post-hook "systemctl reload httpd"

Apache Tomcat 9.0.31にアップデートしたらエラー発生

Apache Tomcat 9.0.31にアップデートしたらAJP経由でアクセス出来なくなった。
server.xmlを見てみるとAJPの設定がコメントアウトされていたので、下記を追記した。

    <Connector protocol="AJP/1.3"
               port="8009"
               redirectPort="8443"/>

しかし、今度は下記のようなエラーが出るようになった。

Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
    at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:264)
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1035)

secretRequiredがデフォルトで”true”になっているため、secretを設定しろということらしい。
面倒なのでアドレスでアクセス制限をかけて、secretRequiredは”false”にした。

<Connector protocol="AJP/1.3"
           address="localhost"
           port="8009"
           redirectPort="8443"
           secretRequired="false"/>

Spring BootでLazyInitializationExceptionが発生する場合

fetch = FetchType.LAZYとしている場合、データベースを参照するときにSessionが切れていてLazyInitializationExceptionが発生することがある。

Caused by:
 org.hibernate.LazyInitializationException:
  failed to lazily initialize a collection of role:
   crawlerapi.entity.Novel.novelChapters, could not initialize proxy - no Session

そのような場合は、application.ymlに以下を追加する。

jpa:
  properties:
    hibernate:
      enable_lazy_load_no_trans: true

vue/cliを3.xから4.xにアップグレードする

最新バージョンを確認する。

D:\>npm outdated
Package                 Current  Wanted  Latest  Location
@vue/cli-plugin-babel    3.12.1  3.12.1   4.1.1  crawler-client
@vue/cli-plugin-eslint   3.12.1  3.12.1   4.1.1  crawler-client
@vue/cli-service         3.12.1  3.12.1   4.1.1  crawler-client

メジャーバージョンは、npm updateでは更新されないので、以下のコマンドを実行する。

D:\>vue upgrade
  Gathering package information...
  Name                    Installed       Wanted          Latest          Command to upgrade
  @vue/cli-service        3.12.1          3.12.1          4.1.1           vue upgrade @vue/cli-service
  @vue/cli-plugin-babel   3.12.1          3.12.1          4.1.1           vue upgrade @vue/cli-plugin-babel
  @vue/cli-plugin-eslint  3.12.1          3.12.1          4.1.1           vue upgrade @vue/cli-plugin-eslint
? Continue to upgrade these plugins? (Y/n) Y

他にも、

Package            Current  Wanted  Latest  Location
eslint              5.16.0  5.16.0   6.7.2  crawler-client
eslint-plugin-vue    5.2.3   5.2.3   6.0.1  crawler-client
sass-loader          7.3.1   7.3.1   8.0.0  crawler-client

などを個別にアップグレードする場合は、以下のコマンドを実行する。

D:\>npm install --save-dev sass-loader@8

以下のようにワーニングが出た場合は指示に従ってインストールする。

npm WARN sass-loader@8.0.0 requires a peer of node-sass@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN sass-loader@8.0.0 requires a peer of fibers@>= 3.1.0 but none is installed. You must install peer dependencies yourself.

D:\>npm install --save-dev sass fibers

OpencsvでJava BeansとMappingする

Opencsvについては、リンク先を参照。
ここではアノテーションを使わずに、各列を各変数にマッピングする方法を紹介する。

・CSVを読み込む

try (InputStreamReader is = new InputStreamReader(multipartFile.getInputStream(), Constants.ENCODING);
        CSVReader reader = new CSVReaderBuilder(is).withSkipLines(1).build()) {
    ColumnPositionMappingStrategy strat = new ColumnPositionMappingStrategy<>();
    strat.setType(User.class);
    strat.setColumnMapping("username", "password", "firstName", "lastName", "email");

    CsvToBean<User> csv = new CsvToBean<>();
    csv.setCsvReader(reader);
    csv.setMappingStrategy(strat);
    return csv.parse();
} catch (IOException e) {
    // 適宜例外処理
} catch (IllegalStateException e) {
    // 適宜例外処理
}

InputStreamReaderについては、どこからファイルを取得するかによって変更する。

CSVReader reader = new CSVReaderBuilder(is).withSkipLines(1).build();

で、CSVReaderを作成する。1行目はヘッダー行のため、withSkipLines(1)で2行目から読み込むようにしている。

ColumnPositionMappingStrategyで、CSVファイルの各列をどのクラスのどの変数にマッピングするか指定出来る。
strat.setType(User.class)で、Userクラスにマッピングすることを指定している。
strat.setColumnMapping(“username”, “password”, “firstName”, “lastName”, “email”)で、1列目をUserクラスのusername変数へ、2列目をpasswordへのように指定していることになる。

CsvToBeanで、List<String[]>をList<User>に変換する。

・CSVに書き出す

try (OutputStreamWriter os = new OutputStreamWriter(response.getOutputStream(), Constants.ENCODING);
        CSVWriter writer = new CSVWriter(os)) {
    // ヘッダー行を追加
    writer.writeNext(new String[] {"ユーザ名","パスワード","名字","名前","eメール"});

    ColumnPositionMappingStrategy<User> strat = new ColumnPositionMappingStrategy<>();
    strat.setType(User.class);
    strat.setColumnMapping("username", "password", "firstName", "lastName", "email");

    StatefulBeanToCsv<User> beanToCsv = new StatefulBeanToCsvBuilder<User>(writer)
        .withMappingStrategy(strat)
        .build();
    beanToCsv.write(userList);
} catch (IOException e) {
    // 適宜例外処理
} catch (CsvException e) {
    // 適宜例外処理
}

CSVファイルへの書き出しは上記の通り。

Spring Tool Suite(Eclipse)のデフォルトのworkspaceを変更出来ない時の対処法

Spring Tool Suiteの設定を変更してもworkspaceが、 「~/Documents/workspace-spring-tool-suite-4-4.4.0.RELEASE」から変更できない場合は、 インストールフォルダ下のconfiguration\config.iniファイルを開き下記1行を削除すれば良い。

osgi.instance.area.default=@user.home/Documents/workspace-spring-tool-suite-4-4.4.0.RELEASE

Spring Boot 2.1でJUnit 5.5を使用する

testCompile 'org.springframework.boot:spring-boot-starter-test'

を以下の通り変更する。

testCompile('org.springframework.boot:spring-boot-starter-test') {
   exclude module: 'junit'
}

さらに、以下の行を追加する。

testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'

なお、Spring Boot 2.2からはJUnit 5.5が標準になったので、上記の対応は不要となる。

Coverallsをopenjdk11環境で使用する

ビルド環境をopenjdk11に変更したら、coveralls-maven-pluginが落ちてしまって、Coverallsのカバレッジが更新されなくなっていた。

coveralls-maven-pluginに以下の依存関係を追加することで回避することが出来る。

<dependencies>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
</dependencies>

本家がJava11に対応してくれるのが一番良いのだが、忙しいみたいでいつ対応されるかわからない。

Travis CIでMySQL 5.7

Travis CIのMySQLが5.7になって、Timestamp型の0は許容しなくなった。
そこで、.travis.ymlファイルのbefore_scriptの1行目に「set global sql_mode = ”」を追記した。

before_script:
 - mysql -e "set global sql_mode = ''"
 - mysql -uroot -e "create database crawler"
 - mysql -uroot crawler < src/config/schema.sql