2025年7月12日土曜日

Pull Request 作成ガイドのひな形を作った

毎プロジェクトで作っていて毎回面倒だと思っている気がするのでひな形を作った。

# 開発者向け Pull Request 作成ガイド

以下の手順で開発環境を整え、プルリクエストを送ってください。

## 1. リポジトリをクローンする

まずは GitHub 上のリポジトリをローカルにクローンします。

```sh
git clone https://github.com/YourOrganization/YourRepository.git
cd YourRepository
```

**既に clone 済みの場合**

すでにリポジトリを clone している場合は、main ブランチに移動し、最新のソースコードを取得します。

```sh
git switch main
git pull origin main
```

## 2. 新しいブランチを作成する

開発作業は必ず新しいブランチで行ってください。
ブランチ名は以下のように issue 番号を含め、分かりやすい名前をつけるようにしてください。


例:

```sh
git switch -c 123_add-test
```

## 3. コードを修正する

### 3-1. 修正後、変更内容を確認する

修正を行った後、以下のコマンドで修正ファイルの一覧を確認します。

```sh
git status
```

さらに、修正内容の差分を確認する場合は次のコマンドを使います。

```sh
git diff
```

### 3-2. 修正をステージングする

修正内容をステージング(インデックスに追加)します。

```sh
git add .
```

### 3-3. ステージング後の確認

再度、ステージング済みファイルを確認します。

```sh
git status
```

ステージング済みの差分を確認したい場合は以下を使います。

```sh
git diff --cached
```

### 3-4. コミットする

コミットメッセージは簡潔かつ内容が分かるように記載してください。

例:

```sh
git commit -m "テストを追加"
```


## 4. プルリクエスト作成前に main ブランチへ rebase する

プルリクエストを作成する前に、最新の main ブランチを取り込み、自分のブランチを rebase します。

### 4-1. main ブランチを最新にする

```sh
git switch main
git pull origin main
```

### 4-2 作業ブランチに戻る

```sh
git switch feature/add-login-page
```

### 4-3. main ブランチの最新履歴を取り込む

```sh
git rebase main
```

もしコンフリクトが発生した場合は、表示される指示に従って解決し、以下で rebase を続行します。

```sh
git add .
git rebase --continue
```

## 5. リモートリポジトリへプッシュする

```sh
git push -u origin 123_add-test
```

## 6. プルリクエストを作成する

GitHub 上で以下の手順でプルリクエスト(PR)を作成してください。

1. GitHub のリポジトリページを開く
2. 「Compare & pull request」ボタンをクリック
3. タイトルと説明を入力
    - どのような変更か
    - 関連する Issue があれば番号を記載(例: closes #123)
4. レビューアを指定(必要であれば)
5. 「Create Pull Request」をクリックして作成


## 7. プルリクエストマージ後、main ブランチへ戻る

プルリクエストのマージが完了したら、作業ブランチから main ブランチへ戻します。

```sh
git switch main
git pull origin main
```

## 注意事項

- main ブランチには直接 push しないでください
- 大きな変更の場合は事前に Issue を立てて相談してください
- レビューコメントが付いたら対応をお願いします

変更履歴

日付 内容
2025/7/12 01 新規作成
2025/7/12 02 pull 操作について追加
リベースの説明追加
マージ後 main に戻る手順を追加

2025年5月3日土曜日

Keycloak の Admin UI の開発環境を整える

やりたいこと

Keycloak の Admin Console に上手く動かない箇所があった ので、自分で直すために環境づくりをする。

前提

  • Docker インストール済み
  • docker exec コマンドが使えること

開発環境の起動

今回はすべての作業をコンテナ上で行う。

必要に応じてバインドマウントするなり、ベアメタルで環境構築するなりしてください。

docker run -it --rm -p "8080:8080" -p "5174:5174" ubuntu:24.04

必要なパッケージのインストール

Keycloak のビルド・実行には Node.js と Java が必要なのでインストール。

その他、開発に必要なものとして curl, git, vim をインストールする。

いろいろ

apt update
DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends curl git vim

OpenJDK

apt install -y openjdk-17-jdk-headless

NodeJS & pnpm

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
npm install -g pnpm

Keycloak のクローン

cd ~/
git clone --depth 1 https://github.com/keycloak/keycloak.git

開発用サーバーを起動

フロントエンドの開発用サーバーを起動

別ターミナルで開発用サーバーを実行。

docker exec -it 72cc1a87a306 bash
cd ~/keycloak/js/apps/admin-ui/
pnpm install
pnpm dev

これだけでは動作確認ができないので、後述の「バックエンドの開発用サーバー」と連携させる必要がある。

バックエンドの開発用サーバーを起動

別ターミナルで開発用サーバーを実行。

docker exec -it 72cc1a87a306 bash
cd ~/keycloak/js/apps/keycloak-server/
pnpm start --admin-dev

これで、先ほど起動した admin-ui の開発サーバーといい感じに連携して、 admin-ui のソース更新を反映してくれるようになる。

ここまでの動作確認

ブラウザで http://localhost:8080 にアクセスすると、 Keycloak のログイン画面になる admin/admin でログインできる。

フロントエンドの修正

試しに Welcome to keycloak の文字列を変更してみる。

vim ~/keycloak/js/apps/admin-ui/src/dashboard/Dashboard.tsx

ファイルを開いたら、 t("welcomeTo", { realmDisplayInfo }) となっている箇所を "Customized!!!!!" に変更する。

変更が反映され、 Welcome to Keycloak と書かれていた場所が Customized!!!!! になっているのがわかる。

以上。

参考資料

2025年4月29日火曜日

Keycloak で SAML のクライアント証明書を設定する

やりたいこと

こんなことをしたときに、

こんなことがありました。

Bug: SAML Client Signing Certificate Not Stored via Admin Console (26.1.3) · keycloak/keycloak · Discussion #39232 にワークアラウンドが記載されていたので試す。

前提

Spring Boot で SAML 認証をする(署名無しバージョン) - mikoto2000 の日記 を実施済み。

やったこと

  1. myrealm の適切なユーザーにロール admin を割り当てる(今回は mikoto ユーザーに admin ロールを割り当てた)

  2. keycloak が起動しているコンテナに接続

    docker exec -it f29b1a6f3f70 bash
  3. kcadm.sh にパスを通す

    export PATH=$PATH:/opt/keycloak/bin/
  4. mikotomyrealm にログイン

    kcadm.sh config credentials --server http://localhost:8080 --realm master --user mikoto --password <PASSWORD>
  5. クライアント saml-sp の id を確認

    • JSON から頑張って探す
    • 今回は dafe91db-651f-4728-90f0-0faf2228fa38 だった
    kcadm.sh get clients --server http://localhost:8080 --realm myrealm
  6. saml-sp にクライアント証明書を設定

    • MIID...(略) の部分をクライアント証明書の文字列に置き換える
    kcadm.sh update clients/dafe91db-651f-4728-90f0-0faf2228fa38 --server http://localhost:8080 --realm myrealm -s 'attributes={"saml.signing.certificate": "MIID...(略)"}'
  7. 適用されたかの確認

    • saml.signing.certificate が更新されていれば OK.
    kcadm.sh get clients/dafe91db-651f-4728-90f0-0faf2228fa38 --server http://localhost:8080 --realm myrealm

動作確認

Keycloak の myrealm -> Clients -> saml-sp -> Keys -> Signing keys config -> Client signeture requiredOn にしても、 Spring Boot の SAML 認証が通るようになった。 OK.

2025年4月7日月曜日

devcontainer.vim で Claude Code を使う

AI コーディングというやつをやってみたかったのです。

前提

  • OS: Windows 11 Pro 23H2 ビルド 22631.5039
  • Docker Desktop: Version 4.37.1 (178610)
  • WSL2 の Ubuntu 24.04 から WSL Integration で Docker Desktop を利用
  • Java プロジェクトを作って、 Hello,World! するのが目標
  • Claude Code のアカウントを作って $5 入金済み

devcontainer 用のファイル作成

.devcontainer/devcontainer.json

  • Maven の Java プロジェクトを作りたいので、 devcontainer の features を利用してインストール
  • Claude Code に Node が必要なので、 devcontainer の features を利用してインストール
{
  "name": "app",
  "image": "mcr.microsoft.com/devcontainers/base",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {},
    "ghcr.io/devcontainers/features/java:1": {
      "version": "21",
      "installGradle": "false",
      "installMaven": "true"
    }
  }
}

.devcontainer/devcontainer.vim.json

  • devcontainer.vim config -g > .devcontainer/devcontainer.vim.json で生成したものそのまま使う
{
  "remoteEnv": {
    "EDITOR": "~/squashfs-root/AppRun",
    "PAGER": "sed -r 's/\\x1B\\[[0-9;]*[mGKH]//g' | ~/squashfs-root/AppRun -R -",
    "LESSCHARSET": "utf-8",
    "SHELL": "bash",
    "TERM": "xterm-256color",
    "HISTCONTROL": "erasedups",
    // If use WSLG
    // "DISPLAY": "${localEnv:DISPLAY}",
    // "WAYLAND_DISPLAY": "${localEnv:WAYLAND_DISPLAY}",
    // "XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}",
    // "PULSE_SERVER": "${localEnv:PULSE_SERVER}",
  },
  // devcontainer/cli はまだ forwardPorts に対応していないため、
  // 必要に応じて forwardPorts の定義を appPort に転記する。
  // ※ コンテナ側で Listen する際は、 `127.0.0.1` **ではなく** `0.0.0.0` で Listen すること。
  // "appPort": [
  // ],
  // Linux で実行する場合には、 runArgs をコメントアウトし、コンテナからホストへの接続ができるようにしてください
  //"runArgs": [
  //  "--add-host=host.docker.internal:host-gateway"
  //],
  "mounts": [
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.vim",
      "target": "/home/vscode/.vim"
    },
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.gitconfig",
      "target": "/home/vscode/.gitconfig"
    },
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.ssh",
      "target": "/home/vscode/.ssh"
    },
    // If use host's bashrc
    //{
    //  "type": "bind",
    //  "source": "${localEnv:HOME}/.bashrc",
    //  "target": "/home/vscode/.bashrc"
    //},
    // If use WSLG
    //{
    //  "type": "bind",
    //  "source": "/tmp/.X11-unix",
    //  "target": "/tmp/.X11-unix"
    //},
    //{
    //  "type": "bind",
    //  "source": "/mnt/wslg",
    //  "target": "/mnt/wslg"
    //},
  ],
  // denops など、別の実行環境が必要な場合や、
  // 後乗せで追加したいツールがある場合には以下の対象行をコメントアウトするか
  // https://containers.dev/features から必要な feature を探して追加してください。
  //"features": {
  //  "ghcr.io/devcontainers-community/features/deno:1": {}
  //  "ghcr.io/devcontainers/features/node:1": {}
  //  "ghcr.io/devcontainers/features/python:1": {}
  //  "ghcr.io/devcontainers/features/ruby:1": {}
  //  "ghcr.io/devcontainers-extra/features/fzf:1": {}
  //  "ghcr.io/jungaretti/features/ripgrep:1": {}
  //  "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
  //  "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  //}
}

開発環境の起動

devcontainer.vim start .

Claude Code のインストール・初期設定

インストール

Vim でターミナルを開き、以下コマンドを実行。

npm install -g @anthropic-ai/claude-code

初期設定

Vim でターミナルを開き、以下コマンドを実行。

cloude
  1. 表示のカラースタイルを聞かれるので答える(僕は Light text にした)
  2. ログイン処理 2.1 Enter 押下で表示される URL にアクセスし、ログインを行う 2.2 ログイン完了後に表示されるコードをターミナルにペーストし、 Enter
  3. Yes, proceed まで Enter を押し続ける
  4. プロンプト入力画面が表示される

あとはここにやって欲しいことを入力していくだけ。

実装

プロジェクトの作成

claude へ次の命令を入力する。

Maven の Java プロジェクトを作り、 Hello, World! を表示したい。 Java のバージョンは 21 とすること。

今回は、以下のような処理を行ってくれた。

  1. mkdir -p src/main/java/com/example

  2. pom.xml の作成

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>hello-world</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>21</maven.compiler.source>
            <maven.compiler.target>21</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.3.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>com.example.App</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
  3. App.java の作成

    package com.example;
    
    public class App {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
  4. コンパイル(mvn compile)

  5. 実行(mvn exec:java -Dexec.mainClass="com.example.App")

  6. 完了報告(Maven プロジェクトが正常に作成され、「Hello, World!」が表示されました。Java 21 を使用する Maven プロジェクトの基本構造を作成しました。)

良い感じ。

devcontainer.vim 特有のことが無かった気がするけれど、 Claude Code が使えたのでヨシ!

以上。

参考資料

2025年4月6日日曜日

Go 言語で MCP サーバーを作り、 Claude Desktop で利用する

前提

  • OS: Windows 11 Pro 24H2
  • Claude Desktop インストール済み
  • Go 言語の開発環境構築済み

MCP サーバーの実装

mark3labs/mcp-go を使用して、 Hello, World! を返却するツールを実装した。

プロジェクト初期化とライブラリのインストール

以下コマンドで環境構築完了。

go mod init mikoto2000.dev/study/mcp
go get github.com/mark3labs/mcp-go
go get github.com/mark3labs/mcp-go/server
go get github.com/mark3labs/mcp-go/mcp

ソースコード

main.go:

package main

import (
    "context"
    "fmt"

    "github.com/mark3labs/mcp-go/mcp"
    "github.com/mark3labs/mcp-go/server"
)

func main() {
    // サーバーの生成
    s := server.NewMCPServer("hello-mcp", "1.0.0")

    // ツールの仕様生成
    tool := mcp.NewTool("hello_world",
        mcp.WithDescription("Say `Hello, World!`"),
    )

    // サーバーにツールを追加
    s.AddTool(tool, helloHandler)

    // サーバーの開始
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %v\n", err)
    }
}

// `Hello, World!` を返却するツールのリクエスト受信ハンドラ
func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    return mcp.NewToolResultText("Hello, World!"), nil
}

ビルド

go build

Claude Desktop の設定

サーバーの配置

先ほどビルドした mcp.exe を、任意の場所に配置する。

今回は C:\Users\mikoto\tmp\mcp.exe に配置した。

MCP サーバーの設定

  1. Claude Desktop を開く

  2. 左上のハンバーガーアイコンをクリック -> ファイル -> 設定 -> 開発者 -> 構成を編集

  3. エクスプローラーが開くので、その中にある claude_desktop_config.json を編集

    {
      "mcpServers": {
        "hello-mcp": {
          "command": "C:\\Users\\mikoto\\tmp\\mcp.exe",
          "args": []
        }
      }
    }
  4. Claude Desktop を再起動する

呼び出してみる

新しいチャットを開始し、

「hello-mcp を呼び出して結果を教えて」と入力する。

hello-world(ローカル)からのツールを許可しますか?と聞かれるので このチャットで許可する を選択。

そうすると、しばらくぐるぐるした後以下のような返答が返ってきた。 OK.

関数の実行結果は「Hello, World!」でした。ご要望通りに関数を実行し、その結果をお知らせしました。何か他にお手伝いできることがありましたら、お気軽にお尋ねください。

参考資料

2025年3月26日水曜日

Windows で Gitea を試す

オンプレに Git サーバーを立てる機運だったので、 なるだけ簡単、かつ、Windows サーバーで動くやつとして Gitea を試す。

前提

  • OS: Windows 11 Pro 23H2 ビルド 22631.5039
  • Gitea: 1.23.5

ダウンロード

Gitea Official Website から Windows 版のバイナリをダウンロード。

名前を gitea.exe に変更し、 C:\gitea\gitea.exe に配置する。

初期設定

サーバーを起動し、アクセスする

以下コマンドで gitea サーバーを立ち上げ http://localhost:3000 へアクセスする。 初回アクセス時に初期設定を行うための画面が表示される。

.\gitea.exe web

初期設定入力

今回は以下の通り入力した。下記項目以外はデフォルト。

入力したら Giteaをインストール ボタンを押下。

必須設定

項目
データベースのタイプ SQLite3
パス C:\gitea\data\gitea.db
サイトタイトル Mikoto’s Gitea
リポジトリのルートパス C:\gitea\data\gitea-repositories
Git LFS ルートパス C:\g itea\data\lfs
実行ユーザー名 mikoto
サーバードメイン mnmain
SSHサーバーのポート 8022
Gitea HTTPポート 3000
GiteaのベースURL http://mnmain:3000/
ログの保存先パス C:\gitea\log

オプション設定 - サーバーと外部サービスの設定

項目
OpenIDを使ったサインインを有効にする チェックを外す
ページ閲覧にサインインが必要 チェックを入れる

オプション設定 - 管理者アカウントの設定

項目
管理者ユーザー名 mikoto
メールアドレス mikoto2000@gmail.com
パスワード ひみつ
パスワード確認 ひみつ

しばらくすると、管理者でログインした画面が表示されるが、ベース URL が違うため、改めて http://mnmain:3000 にアクセスしなおす。

HTTPS 設定

証明書の生成

なんと、自己証明書も作れちゃうらしい。

cd c:\gitea
.\gitea.exe cert --host mnmain --ca

設定ファイルの編集

C:\gitea\custom\conf\app.ini に設定ファイルがあるので、これを編集する。

今回編集するのは server セクション。

  • ROOT_URLhttphttps に変更
  • 以下 3 行を追加
    • PROTOCOL = https
    • CERT_FILE = C:\gitea\cert.pem
    • KEY_FILE = C:\gitea\key.pem

設定が完了したらもう一度 .\gitea.exe web を起動して https://mnmain:3000 にアクセス。

警告が出るが無視して進むと https で接続できる。

SSH サーバーの設定

Windows で実行する場合は、 Gitea 組み込みの SSH サーバーを使用するのが無難そうなので、その設定を行う。

組み込み SSH サーバーの有効化

C:\gitea\custom\conf\app.ini を編集する。

編集するのは SERVER セクション。 以下項目を追加する。

  • START_SSH_SERVER = true
    • 組み込み SSH サーバーを起動する

新規登録の禁止化

C:\gitea\custom\conf\app.ini を編集する。

DISABLE_REGISTRATIONtrue にする。

Windows サービス化

サービス化用に設定変更

C:\gitea\custom\conf\app.ini を編集する。

今回は RUN_USERmnmain$ (<コンピューター名>$) に修正。

サービスへの登録

コマンドプロンプト を管理者で開き、以下コマンドを実行。

sc.exe create gitea start= auto binPath= "\"c:\gitea\gitea.exe\" web --config \"c:\gitea\custom\conf\app.ini\""

後は Windows のサービスから 開始 を選択すれば OK.

公開鍵の登録

GitHub と同じで、 SSH 経由の操作は、公開鍵を用いて行われる。

公開鍵の登録方法は以下の通り。

  1. 右上の自分のアイコンをクリック -> 設定 -> SSH / GPG キー を選択
  2. SSHキーの管理キーを追加 ボタンを押下
  3. SSH の公開鍵を入力する

以上。

参考資料

変更履歴

日付 内容
2025/3/26 新規作成
2025/4/20 管理者ユーザーを明示的に追加する手順を追加
組み込み SSH サーバーによる接続について追加

Vim のマクロを使って気持ち良くなった話 - 表のデータを TS の enum にする

こんなデータから、こんなデータを作りたい

PDF に以下のような表がありました。

項目1 項目2
1
2
× 3

実際は行が 200 行くらいあります。

これを、以下のような TypeScript の enum にしたいのです。

enum Type {
= 1;
= 2;
= 3;
}

どうやったか?

まず、 PDF の表から文字列をコピペすると、以下のようなテキストデータになりました。



1


2

×
3

これを、前述の enum の形式にして、 200@q で気持ちよくなりたいわけです。

処理する順番としては以下のようにしました。

  1. 「項目2」 を消す
  2. 「項目1」の行末尾に = を追加
  3. 「項目1」と「値」 の行を結合
  4. 「3.」で結合した末尾に ; を追加
  5. 次の行の先頭にカーソルを配置

こうしてできた文字列を enum 内にコピペしてフォーマッタをかければ enum 定義の完成です。

ではやってみましょう。

<ここにカーソルがある>松

1


2

×
3

という状態から始め、 jddk で「項目2」の行を削除します。(1.)

<ここにカーソルがある>松
1


2

×
3

つづいて A = <Esc> で「項目1」の末尾に = を追加します。(2.)

すると以下の状態になりますになります。

松 = <ここにカーソルがある>
1


2

×
3

J で行を結合します。(3.)

松 = <ここにカーソルがある>1


2

×
3

A;<Esc> で末尾に ; を追加します。(4.)

松 = 1;<ここにカーソルがある>


2

×
3

マクロの連続実行ができるように、j^ で次の行の先頭にカーソルを持っていきます。(5.)

松 = 1;
<ここにカーソルがある>竹

2

×
3

この操作を記録して、 200@q とかすれば、他の項目も全て enum の形式になります。やったね。

2025年3月19日水曜日

Vim のマクロを使って気持ち良くなった話 - モックの JSON データ作成・編集編

モックデータの新規作成

こんなデータを作りたい

ホストにぶら下がっているエッジが大量にあり、そのエッジのステータスを取得する API がある。 その API のモックデータを作りたい。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 120 個くらい続く

どうしたか?

何個かデータを追加していくと、キー操作のパターンが見えてきました。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
<ここにカーソルがある>{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},

上記状態で、qqVjjjjyjjjjpjj<C-a>j<C-a>kkkq としたあと、 117@q と打って気持ちよくなりました。 (実際は何個かやって感覚をつかんでからなので、 114@q くらいだった気がする…)

モックデータの修正

こんなデータを作りたい、既にデータはある

先ほど作ったデータが、実は間違いでした…。 本当は「電球60個に人感センサ60個」なのでした。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
    "name", "人感センサ1",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ2",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ3",
},
... これが 60 個続く

どうしたか?

このデータだけ見ると、「人感センサについてさっきと同じことすればいいじゃん」と思うでしょう。その通りです。

ただ、考えるのが面倒でこのデータには入れていませんが、既に使われているモックデータのため、「type, name 以外のパラメーターを変更したくない」という制約があったのです。

なんでそんな状況になったか覚えていませんが、そんな状況だったのです。

という事で、制約を守った編集ができるような手順を、マクロ含みで考えました。

まずは、61 個目以降のtype, name の数値部分以外を人感センサに一括置換します。

そうすると、以下のようなデータになります。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",

},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
    "name", "人感センサ61",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ62",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ63",
},
... これが 60 個続く

後は簡単ですね。

以下の位置にカーソルを移動し、 qq60<C-x>jjjjj^q59@q で完了です。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
<ここにカーソルがある>    "name", "人感センサ61",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ62",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ63",
},
... これが 60 個続く

これで気持ちよくなれました。

以上です。

2025年3月15日土曜日

Maven で Servlet 開発する

新人研修で JSP&Servlet をやるっぽいので素振りをした。

前提

  • Docker: Docker version 27.4.0, build bde2b89
  • 使用コンテナ: maven:3, tomcat:11

compose.yaml の作成

services:
  app:
    image: maven:3
    volumes:
      - .:/workspaces
      # tomcat11 との共有ディレクトリ
      # ビルドした war ファイルをここに格納する
      - firststep-webapps:/tomcat-webapps
    command: "sleep infinity"
  tomcat:
    image: tomcat:11
    volumes:
      - firststep-webapps:/usr/local/tomcat/webapps
    ports:
      - 8080:8080
volumes:
  firststep-webapps:
    driver: local

開発環境の起動

docker compose up -d

開発環境へ接続

docker compose exec app bash

Maven プロジェクトの作成

ひな形の作成

mvn archetype:generate -DgroupId=dev.mikoto2000.study.servlet -DartifactId=firststep -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

ただし、このプロジェクトは依存が足りなかったり Servlet が jakarta になる前のものだったりするので、 pom.xmlweb.xml を修正する。

pom.xml の修正

${PROJECT_ROOT}/pom.xml に以下依存を追加する。

    <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>6.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
    <dependency>
      <groupId>jakarta.servlet.jsp.jstl</groupId>
      <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
      <version>3.0.2</version>
    </dependency>

web.xml の修正

${PROJECT_ROOT}/src/main/webapp/WEB-INF/web.xml を修正。

before:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

after:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <display-name>MyApp</display-name>
</web-app>

開発

実装

${PROJECT_ROOT}/src/main/java/dev/mikoto2000/study/servlet/firststep/HelloServlet.java に Servlet を実装する。

package dev.mikoto2000.study.servlet.firststep;

import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      response.getWriter().println("<h1>Hello, Servlet!</h1>");
  }
}

ビルド

mvn package

${PROJECT_ROOT}/target/firststep.war が作成される。

デプロイ

/tomcat-webapps が tomcat のアプリデプロイディレクトリと共有されているので、 war ファイルをそこにコピーする。

cp target/firststep.war /tomcat-webapps/

動作確認

http://localhost:8080/firststep/hello へアクセスすると、 Hello, Servlet! が表示される。

以上。