Tomcat 10からTomcat 11にアップグレードする

動作環境

動作環境はTomcat 10と変わらなかった。

Jakarta EE

Jakarta EEのサポートバージョンが変わっている。
一部抜粋:参考
Tomcat 11
 Servlet 6.1
 JSP 4.0
 EL 6.0
 Java 17 and later

Tomcat 10
 Servlet 6.0
 JSP 3.1
 EL 5.0
 Java 11 and later

javax.*からjakarta.*に移行が済んでいれば、基本的にはプログラム変更なしで動くはず。

変更する場合

Tomcat 11のサポートバージョンにプログラムを書き換えてみる。

Web.xml

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_1.xsd"
  version="6.1">

pom.xml

Servlet 、JSPのバージョンをpom.xmlで指定することはそう無いと思う。

ELについては、Hibernate Validator 8.0で、Eclipse Expressly 5.0を使用しているので、jakarta.el-api 5.0が必要(Expresslyの依存関係に含まれている)になる。

Hibernate Validator 9.0であれば、jakarta.el-apiは6.0となるが、まだベータ版の段階である。

原神のスクリーンショット保存先のフォルダを変更する(PC版)

動機

  • スクリーンショットのフォルダが原神のインストールフォルダ下にあるのは、何かと不便
  • OneDriveフォルダにスクリーンショットを保存して、自動的にバックアップが取れるようにしたい

結論

原神にはスクリーンショットの保存場所を変更する機能がないため、Windowsのシンボリックリンク機能を使用して、保存場所を移動する。

以下手順

  1. 原神のインストールフォルダにあるScreenShotフォルダをOneDrive管理下のフォルダに移動する。
  2. スタートボタンの検索に「cmd」と入力し、コマンド プロンプトが表示されたら、右クリックメニューを開き、「管理者として実行」をクリックする。

  3. コマンド プロンプトで下記コマンドを入力しシンボリックリンクを作成する。
1. 原神のインストールフォルダに移動する。
例)※インストール先の確認方法は後述
cd C:\Games\HoYoverse\Genshin Impact game

2. シンボリックリンクを作成する。
mklink /d ScreenShot 上記手順1でスクリーンショットを移動したフォルダ/ScreenShot

3. 下記の様に表示されたら作成成功。
ScreenShot <<===>> 上記手順1でスクリーンショットを移動したフォルダ/ScreenShot のシンボリック リンクが作成されました

※原神のインストール先の確認方法

HoYoPlayのゲーム設定をクリックする。

基本情報の下に表示されているフォルダがインストール先

Ubuntu Server 24.04 LTSをインストールする

インストール用ISOファイルをダウンロード

https://jp.ubuntu.com/download

インストール用ISOファイルをUSBメモリに展開

ダウンロードしたISOファイルを展開してUSBメモリに書き込む。

自分はUSBWriterを使用。

USBメモリから起動しインストール

基本はデフォルトで設定し、以下項目だけ変更した。

  • 静的IPの設定
  • Open SSHのインストール

SSHで繋いで環境構築

sudo apt update
sudo apt upgrade
sudo reboot

Webminのインストール

curl -o setup-repos.sh https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh
sudo sh setup-repos.sh
sudo apt install --install-recommends webmin

その他

 →Ubuntu Server 22.04 LTSをインストールする
 →Ubuntu Proを使ってみる

Windows 11で休止状態を無効にし、hiberfil.sys を削除する

デスクトップPCに休止状態の設定はいらないだろうということで、無効にする。管理者権限でコマンドプロンプトを開き下記のコマンドを実行する。

powercfg.exe -h off

無効にすると自動的にhiberfil.sysが削除される。自分の環境ではCドライブの空き容量が64GB増えた。

xsdのURLは正しいのにEclipseのエディタ上でエラーになる

xsdのURLは正しいのにDownloading external resources is disabled.と表示されてエラーになっている。

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"

下記の設定を変更することで解決した。

Mavenの設定の「Download Artifact Javadoc」にチェックを入れる。

XML (Wild Web Developer)の設定の「Download external resources like referenced DTD, XSD」にチェックを入れる。

Hibernate Searchを7.2にアップデートしたらNoSuchMethodErrorが発生した

Hibernate Searchを7.2.1にアップグレードして、テストを実施したら下記のエラーが発生した。

NoSuchMethodError: 'java.lang.Object org.jboss.logging.Logger.getMessageLogger

コンパイルエラーにはなっていないが、テスト時のログ出力でエラーとなった。

他のライブラリとの依存関係の影響で、jboss-logging 3.5系を使用するようになっていた。3.6.0.Finalを使用するようにpom.xmlに依存関係を追記したところ、エラーは解消した。

<dependency>
    <groupId>org.jboss.logging</groupId>
    <artifactId>jboss-logging</artifactId>
    <version>3.6.0.Final</version>
</dependency>

Gradleの場合も同様。

implementation 'org.jboss.logging:jboss-logging:3.6.0.Final'

Vueのアップグレードでエラー

どのバージョンで変わったか定かではないのだけど、アップグレード後エラーになって起動しなくなった。

変更点

vue.config.jsのエラーメッセージ

 ERROR  SyntaxError: Cannot use import statement outside a module
E:\Work\wtp\workspace\crawler-client\vue.config.js:1
import { defineConfig } from '@vue/cli-service'

import fromをrequireに変更した。

const { defineConfig } = require('@vue/cli-service')

babel.config.jsのエラーメッセージ

 ERROR  SyntaxError: Unexpected token 'export'
E:\Work\wtp\workspace\crawler-client\babel.config.js:1
export const plugins = {

export const pluginsをmodule.exportsに変更した。

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}

PostgreSQLをダウンロードして、データベースを作成する

テスト用のユーザーと、テスト用のデータベースを作成して、実行する。

PostgreSQLのダウンロード

Zipファイルをダウンロードし、解凍する。

https://www.enterprisedb.com/download-postgresql-binaries

データベースクラスタの作成

データベース等の保存先になるフォルダを指定する。

PostgreSQLインストールフォルダ\bin\initdb.exe -D "任意フォルダ"

起動

PostgreSQLを起動する。

PostgreSQLインストールフォルダ\bin\pg_ctl.exe start -D "データベースクラスタのフォルダ" -l "任意フォルダ\ログファイル名"

以降、起動状態で作業する。

ユーザー作成

パスワード有りで、ユーザーを作成する。

PostgreSQLインストールフォルダ\bin\createuser -P testuser

データベース作成

先ほど作成したユーザーをオーナーに指定しデータベースを作成する。

PostgreSQLインストールフォルダ\bin\createdb -O testuser testdb

終了

PostgreSQLを終了する。

PostgreSQLインストールフォルダ\bin\pg_ctl.exe stop -D "データベースクラスタのフォルダ" -l "任意フォルダ\ログファイル名"

Spring BootでSessionをRedisに保存する

前回、Raspberry piで遊んだ時にTomcatによるSession Replicationを実装した。

今回はSpring BootとRedisでSession管理を外部化してSession Replicationを実装してみる。

Redisのインストール

sudo apt install redis

Redisの設定

複数サーバーからアクセス出来るようにするため、アクセス制限を削除する。

sudo vi /etc/redis/redis.conf
下記の通り修正

bind 0.0.0.0 ::0 # 一時的に使用するだけなので全てのIPからアクセスOKにしている

Spring Bootでの実装例

build.gradleの依存関係部分
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	implementation 'org.springframework.session:spring-session-data-redis'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

Sessionオブジェクトの保存にRedisを使用するようにConfigを設定する。なお、外部にデータを保存することになるので、Sessionに入れるデータはSerializableである必要がある。

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;

@Configuration
@EnableRedisWebSession()
public class SessionConfig {
}
Controllerの実装例
@RestController
@AllArgsConstructor
public class SessionController {

    @GetMapping("/websession")
    public Mono<SessionForm> getSession(WebSession session) {
        session.getAttributes().putIfAbsent("key", 0);
        session.getAttributes().putIfAbsent("note", "Nothing!");

        var sessionForm = new SessionForm();
        sessionForm.setKey((Integer) session.getAttributes().get("key"));
        sessionForm.setNote((String) session.getAttributes().get("note"));

        return Mono.just(sessionForm);
    }

    @GetMapping("/websession/test")
    public Mono<SessionForm> testWebSessionByParam(@RequestParam(value = "key") Integer key,
            @RequestParam(value = "note") String note, WebSession session) {
        session.getAttributes().put("key", key);
        session.getAttributes().put("note", note);

        var sessionForm = new SessionForm();
        sessionForm.setKey((Integer) session.getAttributes().get("key"));
        sessionForm.setNote((String) session.getAttributes().get("note"));

        return Mono.just(sessionForm);
    }
}

完全なコードはこちら。
https://github.com/hide6644/spring-session

動作確認

下記URLにアクセスするとパラメーターがSessionに保存される。
localhost:8080/websession/test?key=222&note=helloworld

下記のURLにアクセスすると、先ほど保存した文字が表示される。
localhost:8080/websession

{“key”:222,”note”:”helloworld”}

SessionをRedisに保存しているので、Spring Bootアプリをスケールアウトしても、それぞれのアプリでSessionが共有されていることが確認できると思う。

$ redis-cli
127.0.0.1:6379> keys *
1) "spring:session:sessions:セッションID"
127.0.0.1:6379> exit

AWSサーバーにエンドポイントで接続してみる

前回、IPv6の対応したついでにEC2のパブリックIPv4アドレスを無効にしたため、EC2のサーバーにSSHでアクセス出来なくなっている。IPv6で許可すれば良いのだが、そんなに頻繁に使用するものでもないので、エンドポイントを作成してプライベートIPに直接アクセスするように変更する。

セキュリティグループ

エンドポイント用のセキュリティグループ、EC2サーバー用のセキュリティグループを作成する。

エンドポイント

自分のVPC、先ほど作成したセキュリティグループ、接続したいEC2サーバーのあるサブネットを選択してエンドポイントを作成する。

接続

接続したいEC2インスタンスを選択し、下記の通り接続タイプを選択する。