Claude Media
Claude CodeでStruts 1.xのAction・JSP対応表を作り修正範囲を絞る

Claude CodeでStruts 1.xのAction・JSP対応表を作り修正範囲を絞る

struts-config.xmlからURL・Action・ActionForm・forward先JSPの対応表を作り、JSPを直したときに影響する画面を逆引きする手順です。

Struts 1.xの保守で最初に詰まるのは、「このJSPを直すと、どの画面が変わるのか」が分からないことです。答えは struts-config.xml とJavaソースに散らばっています。URLのpathからActionクラス、ActionForm、forward先のJSPまでを1枚の表にしておけば、JSPのファイル名から逆引きして影響範囲を出せます。Claude Codeには、この表をXMLから起こし、ソースと突き合わせて検証する作業を任せられます。

Struts 1は、Apache Strutsプロジェクトが寿命の終了(EOL)を告知したフレームワークです。最後のリリースは2008年12月の1.3.10で、重大なバグやセキュリティ問題が見つかっても新しいリリースは期待できないと告知に書かれています。それでも現場に残っている以上、直す範囲を正確に絞る技術のほうが、全面移行の議論より先に必要になります。

逆引きに必要な4つの列

対応表の列は、struts-config.xml の要素から決まります。DTD(struts-config_1_3.dtd)で各属性の意味を確かめたうえで、次の4列にそろえます。

列

表にする4つの情報

  • URLのpath

    <action> の path 属性です。先頭は / で、拡張子マッピングを使う場合は拡張子を含めません。

  • Actionクラス

    <action> の type 属性です。type の代わりに forward か include を指定した定義もあり、その場合はActionクラスが存在しません。

  • ActionForm

    <action> の name 属性が、<form-bean> の name を指します。type 側のクラスが実体です。

  • forward先のJSP

    <forward> の path 属性です。<action> の中に書かれたものと、<global-forwards> に書かれたものの2系統があります。

DTDには、画面の分岐に効く属性がほかにもあります。validate はActionを呼ぶ前にActionFormの validate メソッドを呼ぶかを決め、input は検証エラーのときに制御を戻す先のpathです。input は name を指定したときだけ有効です。入力エラー時に戻る画面は、正常系のforwardとは別の画面なので、表には「入力エラー時の戻り先」の列を足しておくと取りこぼしません。

例外のときの遷移先も、別の画面です。<exception> 要素の path は、その例外が起きたときにリクエストを引き取るリソース(module-relative)で、多くはエラー画面のJSPを指します。<action> の中に書けば個別のActionだけ、<global-exceptions> に書けば全体が対象で、同じ例外型ならAction側の定義が上書きします。エラー画面のJSPを直すときは、この path を引かないと影響する画面が出てきません。

forward要素には redirect 属性があり、true なら新しいリクエストを発行させ、false なら RequestDispatcher.forward が呼ばれます。リダイレクトを挟むとリクエスト属性が引き継がれないため、JSPが読む値の出どころが変わります。表のforwardの欄にredirectの有無を添えておく価値は、この違いにあります。

もう1つ、parameter 属性にも注意が要ります。DTDは、Actionクラスに追加情報を渡す汎用の設定値としか説明していません。値の意味はActionクラスの実装で決まります。呼び出すメソッド名を入れている現場もあるため、列に parameter を足し、その値をActionがどう使うかはソースで確かめます。1つのpathに複数の処理がぶら下がっている場合、そのpathは影響範囲の逆引きで重く扱う必要があります。

設定の読み方をCLAUDE.mdに固定する

毎回同じ読み方をさせるために、読み方の規則を CLAUDE.md に書きます。ベストプラクティスのページは、CLAUDE.md には「コードから読み取れないこと」だけを置くよう勧めています。具体的には、コードの見た目が紛らわしい箇所や、同じ訂正を2回したことの記録です。Strutsの設定の読み方は、まさに後者に当たります。

# Struts 1 の読み方(このリポジトリ)
 
- 設定ファイルは WEB-INF/struts-config*.xml。モジュールごとに分かれている
- 画面の対応表は docs/struts-map.md に置く。列は
  path / Action(type) / ActionForm(name→form-bean の type) /
  forward名→JSP(redirect の有無つき) / input・exception の遷移先
- <action> に type が無く forward 属性だけの定義は「Actionなし」と明記する
- <global-forwards> の forward は全 Action から使える。<action> 内に同名の
  forward があればそちらが上書きする。表では別枠にして、JSP からの逆引きに含める
- <exception> と <global-exceptions> の path(エラー画面)も表に入れる
- 読んだ根拠は XML の行番号で示す。推測で埋めない

全体のデータや用語を最初に把握させる使い方は、ドメイン用語集を CLAUDE.md に置く手順と同じ形です。CLAUDE.md は1ファイル200行以内が目安とされています。表そのものはここに貼らず、docs/struts-map.md のように別ファイルへ出して、必要なときに読ませます。

表を作る手順

最初に、リポジトリの全体像を聞きます。公式ドキュメントには「プロジェクトのコードベースの概要を聞く」「ドメイン用語を含めた用語集を頼む」といったプロンプトの型があります。Struts 1では、次のように設定ファイルを名指しすると話が早くなります。

WEB-INF/struts-config*.xml をすべて読んで、action 定義ごとに
path / type / name(form-bean の type まで解決)/ forward の name と path
(redirect の有無つき)/ input / exception の path を表にして docs/struts-map.md に書いて。
type が無い action は「Actionなし」と明記して。

出てくる表は、たとえば次のような形になります(これは書式の例示で、実際の内容はリポジトリ次第です)。

pathActionActionFormforward(name→JSP)input・exception先
/orderEntryActionOrderEntryActionActionFormOrderFormforward(name→JSP)success→/order/confirm.jspinput・exception先input=/order/entry.jsp
/orderConfirmActionOrderConfirmActionActionFormOrderFormforward(name→JSP)done→/order/complete.jsp(redirect)input・exception先input=/order/confirm.jsp、exception=/error/stock.jsp
/loginActionLoginActionActionFormLoginFormforward(name→JSP)success→/menu.jspinput・exception先input=/login.jsp

この例では、OrderForm が2つのactionで共有されています。ActionFormを共有する画面は、フォームのプロパティを変えたときに両方が影響を受けるので、後の逆引きで必ず効いてきます。

設定とソースを突き合わせる

XMLだけで表を閉じず、ソースとも突き合わせます。ActionのJavaソースは、mapping.findForward("success") のように論理名で遷移先を呼びます。設定にforward名が書かれていても、ソースが呼ばない名前なら死んだ定義です。逆に、ソースが呼ぶ名前が設定のどこにも無いなら、<global-forwards> に頼っているか、実行時に例外になる状態です。

docs/struts-map.md の各行について、Action の execute メソッドが
呼ぶ findForward の引数をすべて列挙して。表の forward 名と比べて、
(1)表にあってソースが呼ばない名前 (2)ソースが呼ぶのに表にも
global-forwards にも無い名前 を、ファイルと行番号つきで出して。

数十のActionを一度に読むと、会話のコンテキストがファイルの中身で埋まります。探索をサブエージェントに任せると、読んだファイルが自分の会話に積まれずに要約だけが返ります。組み込みの探索用サブエージェントは読み取り専用で、WriteとEditが禁止されています。突き合わせの前半は、次のように頼めます。

サブエージェントで、com.example.web.action 配下の全 Action について
findForward の引数を調べて、Action名 → 論理名の一覧だけ返して。

JSPから影響範囲を逆引きする

表ができたら、本題の逆引きです。JSPのファイル名を入力にして、そのJSPを表示する画面を探します。

手順

JSPを直す前の確認の順番

  1. 1

    forward先の列を引く

    表のforward先の列に、そのJSPのpathがあるかを見ます。あれば、その行のpathが「そのJSPを出すURL」です。1行ごとにURLを控えます。

  2. 2

    global-forwardsを引く

    <global-forwards> のpathにそのJSPがあれば、同名のforwardを <action> 内に持たないactionすべてが対象です。ソースが呼ぶ論理名で絞り込みます。

  3. 3

    exceptionのpathを引く

    そのJSPがエラー画面なら、<exception> と <global-exceptions> のpathを引きます。該当する例外型を受けるactionが、影響を受ける画面です。

  4. 4

    includeしている側を引く

    jsp:include や <%@ include %> の取り込み先を検索します。部品JSPは、取り込んでいるすべての画面に効きます。

  5. 5

    対象リストを確定する

    ここまでに出たURLの一覧が、動作確認の対象です。ActionFormを共有するactionは、プロパティを変えるときだけ対象に加えます。

4つ目の確認(includeしている側を引く手順)は、struts-config.xml を読むだけでは出てきません。JSPの中のインクルードは設定ファイルの外にあるため、grepで確かめます。Tilesのようなレイアウト機構を使っている場合は、tiles-defs.xml のような別の定義ファイルに、画面を構成するJSPが書かれていることがあります。表の「forward先」がJSPではなくTilesの定義名になっているときは、その先の定義ファイルまで追って、実際のJSPに解決した列を足します。

次のように頼めば、確認を1回のプロンプトにまとめられます。

WEB-INF/jsp/order/confirm.jsp を修正する予定。docs/struts-map.md と
ソースから、(1)このJSPを forward 先に持つ path (2)global-forwards
経由で到達する path (3)このJSPを include している別JSP とその先の
path (4)exception / global-exceptions の path にこのJSPを持つ action
を洗い出して、画面確認の対象リストにして。根拠の行番号も付けて。

表の誤りを人が確かめる箇所

表が正しいかどうかは、自動では保証されません。次の点を、サンプルの数行について人が見ておくと、誤読が早く見つかります。

  • <form-bean> の type が、実在するクラスにたどり着いているか。name が同じ別定義を取り違えていないか
  • <action> 内のforwardと <global-forwards> で同名のものがあるとき、action側が優先されているか。DTDは、actionが同名のローカルなforwardを定義するとglobal forwardを上書きできると説明しています。exceptionも同様です
  • モジュール分割をしている場合、pathが「モジュール相対」である点。DTDはforwardやactionのpathを「module-relative」と説明しています。複数の設定ファイルがあるなら、表にモジュール名の列を足します

表の全行を読むのではなく、サンプルの行を検算する。この確認ひとつで、読み方の規則の漏れが分かります。見つかった誤りは、同じ訂正を繰り返さないよう CLAUDE.md の規則に書き足します。

表を最新に保つ

対応表は、設定を直すたびに古くなります。再生成を一行で呼べるように、非対話モードで回す形にしておきます。公式は claude -p "prompt" を、1回実行して終了する形としてCIやgit hookに載せる使い方で紹介しています。

claude -p "WEB-INF/struts-config*.xml から docs/struts-map.md を
  CLAUDE.md の規則どおりに再生成して" \
  --allowedTools "Read,Glob,Grep,Write,Edit"

設定ファイルを変更するプルリクエストで再生成を走らせ、差分を表の更新としてレビューすれば、対応表が保守のたびに壊れることを避けられます。

注意: 表は調査の入口であって保証ではない

この表は、設定ファイルとソースに書かれたことだけを写しています。実行時に動く仕組みは写せません。たとえば、Actionが動的に決めた遷移先や、フィルタやインターセプタ的な処理が挟む分岐です。動作確認の対象リストが「必要十分」であるとは言えず、「最低限これは見る」の一覧です。

もうひとつ、画面の見た目の崩れは表から読めません。JSPやCSSを直した結果を目で確かめたい場合は、Playwrightのスクリーンショット比較で、対象リストの画面を直す前後で撮って比べる手があります。

まとめ

Struts 1の保守は、「何を直すか」より「どこまで波及するか」を先に決めると進めやすくなります。struts-config.xml の action・form-bean・forward を1枚の表にし、JSPの名前から逆引きできる状態を作る。読み方の規則を CLAUDE.md に書いておけば、Claude Codeは毎回同じ列で表を出します。ソースの findForward との突き合わせまで済ませた表が、JSP修正のたびに確認すべき画面の一覧になります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/common-workflows
  2. code.claude.com/docs/en/memory
  3. code.claude.com/docs/en/best-practices
  4. code.claude.com/docs/en/sub-agents
  5. struts.apache.org/struts1eol-announcement.html
  6. struts.apache.org/dtds/struts-config_1_3.dtd
この記事を共有:XはてブLinkedIn