はじめに
「古くなったJSPの画面を、そろそろReactあたりで作り直したい」——StrutsやJSPで作られたJavaアプリを前に、そう考えたことはないでしょうか。
ところが、いざ手をつけると簡単ではありません。画面をReactに置き換えるだけでは済まず、JSP・Struts Action・Serviceがどう絡み合っているかを解きほぐし、UIとバックエンドを切り離しながら、既存の業務ロジックや入力チェックはそのまま活かす——といった作業が待っています。
今回は、IBM Bob の Add-on である Premium Package for Java Modernizationを使用して、UIモダナイゼーションのワークフローでこういった作業を効率的に実施していきたいと思います。
このワークフローでは、JSFやStrutsなどで構築されたJava UIを分析し、React、Angular、VueなどのフロントエンドとJavaバックエンドに分離するための計画作成やコード生成を支援します。
今回は、Struts+JSPで作成したタスク管理アプリケーションを使用し、次の点を確認しました。
- 既存アプリケーションをどのように分析するか
- JSPとStruts Actionの関係を把握できるか
- UIとJavaバックエンドをどのように分離するか
- 既存のServiceやRepositoryを再利用できるか
- 生成されたアプリケーションが実際に動作するか
IBM Bobとは?
IBM Bobは、コードベース上で開発者と協働し、ソフトウェア開発を支援するAIパートナーです。
コード補完だけでなく、アプリケーションの分析、設計、実装、レビュー、モダナイゼーションなど、開発ライフサイクル全体を支援します。
30日間の無料トライアルでは、IBM Bobの利用に必要な「Bobコイン」を40コイン利用できます。
- 無料トライアル:https://bob.ibm.com/trial
- Bobコインの追加購入:https://bob.ibm.com/pricing
UI Modernization Workflowとは
IBM BobのJavaモダナイゼーション機能では、次のようなワークフローが提供されています。
- Libertyリプラットフォーミング:従来型JavaランタイムからLibertyへの移行を支援
- Javaアップグレード:Javaバージョン間の非互換を検出・修正
- UIモダナイゼーション:レガシーUIをRESTベースのバックエンドとフロントエンドへ変換
- ユニットテスト生成:テスト戦略とJUnitテストを生成し、実行・修正・カバレッジ確認を支援
今回使用するのは、UI モダナイゼーション ワークフローです。
このワークフローを使用することで、レガシーUIフレームワークを最新の代替手段にモダナイズすることが可能です。
例えば、従来のStruts+JSPアプリケーションでは、一般的に次のような構成になっています。
ブラウザー
↓
Struts Action
↓
Service
↓
Repository
↓
Database
Struts Action
↓
JSPによるHTML生成
↓
ブラウザー
JSPがサーバー側でHTMLを生成するため、UIとJavaバックエンドが密接に結び付いています。
UIモダナイズ後は、例えば次のようにフロントエンドとバックエンドを分離します。
Reactなどのフロントエンド
↓ JSON / HTTP
Java REST API
↓
Service
↓
Repository
↓
Database
このとき必要になるのが、JSPの表示ロジックやStruts Actionの役割を整理し、適切な移行先を判断する作業です。
例えば、次のような変換が考えられます。
JSP → フロントエンドコンポーネント
Struts Action → REST API
画面遷移 → クライアントルーティング
リクエスト属性 → APIレスポンス
フォーム送信 → JSONによるAPI呼び出し
Service → 既存コードを再利用
Repository → 既存コードを再利用
UI Modernization Workflowでは、こうした既存アプリケーションの分析、移行計画の作成、コード生成を一連の流れで進められます。
検証用アプリケーション
今回は、Struts+JSPで作成したシンプルなタスク管理アプリケーションを使用しました。
主な機能は次のとおりです。
- タスクの一覧表示
- タスクの新規登録
- タスクの詳細表示
- タスクを完了状態に変更
- 入力値の検証
- エラー表示
検証環境は次のとおりです。
| 項目 | 内容 |
|---|---|
| Java | 8 |
| Web Framework | Apache Struts 2(2.5.33) |
| View | JSP / JSTL |
| Build Tool | Maven |
| Package | WAR |
| Database | H2 Database(1.4.200) |
| Database Access | JDBC |
| Test | JUnit 4 |
| Character Encoding | UTF-8 |
アプリケーションは、Action、Service、Repository、Validatorに責務を分離しています。
ServiceとRepositoryをUI層から分離しておくことで、モダナイズ後に既存の業務ロジックやデータアクセス処理を再利用できるか確認します。
モダナイズ前の画面
タスク一覧画面では、JSTLの繰り返し処理と条件分岐を使用して、タスクと操作ボタンを表示しています。
タスク登録画面では、タイトル、担当者、期限、優先度、説明を入力します。
入力内容に問題がある場合は、サーバー側のValidatorで検証し、エラーメッセージを表示します。
タスク詳細画面では、選択したタスクの情報を表示します。
今回の検証では、これらの繰り返し表示、条件付き表示、フォーム入力、入力チェック、ステータス更新がモダナイズ後も維持されるかを確認します。
UI Modernization Workflowを実行する
ワークフローを実行する前に、システム、環境、プロジェクトの要件を満たしているか確認しておきます。
https://bob.ibm.com/docs/ide/premium-packages/java-modernization/prerequisites
BobでJava Modernizationのワークフローを使用するには、Add-onのPremium Package for Java Modernizationが必要です。
1. Java Modernizationを選択する
IBM Bobのワークフロー一覧から、Java Modernizationを選択します。
プロジェクトの分析が完了すると、実行するモダナイゼーションの種類を選択できます。
今回は、UI Modernizationを選択しました。
2. 既存アプリケーションを分析する
UI Modernization Workflowを開始すると、最初に既存アプリケーションのアーキテクチャが分析されます。
今回の検証では、分析結果として次のようなファイルが出力されました。
- アーキテクチャをまとめたMarkdownファイル
- アプリケーション構造を示すMermaid図
- 移行先候補をまとめたJSONファイル
コードを書き換える前に、既存構造と移行方針を確認できる点は、UI Modernization Workflowの特徴の一つです。
実際のプロジェクトでは、この段階で次の点をレビューするとよさそうです。
- JSPとActionの対応が正しく認識されているか
- ServiceやRepositoryが再利用対象になっているか
- UIロジックと業務ロジックが適切に区別されているか
- 変更対象に漏れや誤認識がないか
3. 移行先を選択する
分析後、フロントエンドとバックエンドの移行先を選択します。
今回は、次の構成を選択しました。
- フロントエンド:React+Carbon Design System
- バックエンド:Quarkus
バックエンドの実装
最初に、Quarkusを使用したバックエンドが実装されました。
元のStrutsアプリケーションのレイヤー構造をおおむね維持しながら、Struts Actionの処理がJAX-RSベースのREST APIとして再実装されています。
なお、元のアプリケーションはJava 8で動作していましたが、生成されたバックエンドはQuarkus 3.xを前提とするため、実行ランタイムはJava 17へ引き上げられています。
主な対応関係は次のとおりです。
| 移行前 | 移行後 |
|---|---|
| Struts Action | JAX-RSのRESTリソース |
| Service | 既存ロジックを再利用 |
| Repository | 既存のJDBC処理を再利用 |
| Domain | 既存モデルを再利用 |
| Validator | 既存の入力チェックを再利用 |
| Listener | Quarkusの起動処理へ移行 |
複数のActionクラスは、TaskResourceにまとめられ、次のREST APIとして公開されました。
GET /api/tasks
GET /api/tasks/{id}
POST /api/tasks
POST /api/tasks/{id}/complete
また、フロントエンドからAPIを呼び出すためのCORS設定や、APIを確認するためのOpenAPI/Swagger UIも追加されていました。
生成後はビルドまで実行されます。
起動して確認したところ、Quarkusバックエンドは問題なく動作しました。
今回のポイントは、Service、Repository、Domain、Validatorなどを再利用しつつ、Struts ActionがREST APIへ置き換えられたことです。
フロントエンドの実装
続いて、分析結果をもとにフロントエンドが実装されました。
フロントエンドは、Vite+React+TypeScriptのプロジェクトとして作成されています。
主な構成は次のとおりです。
- React
- TypeScript
- React Router
- Carbon Design System
- axios
- Vite
StrutsのActionマッピングとJSPによる画面遷移は、React Routerのルーティングへ置き換えられました。
/ → ランディングページ
/tasks → タスク一覧
/tasks/new → タスク登録
/tasks/:id → タスク詳細
バックエンドとの通信処理はService層(taskServiceモジュール)に集約され、各画面からREST APIを呼び出す構成になっています。
初回生成時点では、Reactアプリケーションの起動は確認できましたが、タスク一覧などの各機能はまだ接続されていませんでした。
コンポーネントの実装とAPI接続
次のサブタスクで、各Reactコンポーネントの実装とバックエンドAPIへの接続が行われました。
タスク一覧には、Carbon Design SystemのDataTableが使用され、一覧表示や検索などが実装されました。
登録画面では、送信前のクライアント側チェックに加えて、バックエンドから返されたバリデーションエラーも各入力フィールドに表示する構成になっています。
また、登録や完了後のメッセージにはInlineNotificationが使用され、元のStrutsアプリケーションに近い操作の流れが再現されていました。
ビルド後にアプリケーションを起動すると、一覧、登録、詳細などの画面が問題なく表示されました。
今回はワークフロー実行時、フロントエンドデザインシステムとしてCarbon Design Systemを選択したため、見やすくてシンプルなUIになっています。
変換前後の比較
今回のモダナイゼーションによって、アプリケーション構成は次のように変わりました。
変換前
Browser
↓
Struts Action
↓
Service
↓
Repository
↓
H2 Database
Struts Action
↓
JSP
↓
Browser
変換後
Reactフロントエンド
↓ JSON / HTTP
Quarkus REST API
↓
Service
↓
Repository
↓
H2 Database
JSPとStruts Actionに集中していたUI処理が、ReactコンポーネントとREST APIに分離されました。
一方、Service、Repository、Domain、Validatorなどは再利用されており、アプリケーション全体を作り直すのではなく、主にUI層とその境界を置き換える構成になりました。
検証結果
今回の結果をまとめると、次のようになります。
分析
Struts Action、JSP、Service、Repositoryなどの構造が分析され、移行前のアーキテクチャと移行先候補が出力されました。
コード変更に入る前に分析結果を確認できるため、移行範囲や再利用対象を把握しやすいと感じました。
バックエンド
Struts Actionの処理は、Quarkus上のREST APIへ移行されました。
既存のService、Repository、Domain、Validatorは、おおむねその役割を維持したまま再利用されています。
生成されたバックエンドはビルドに成功し、起動も確認できました。
フロントエンド
React、TypeScript、Carbon Design Systemを使用したフロントエンドが生成されました。
一覧、登録、詳細、完了処理などがREST APIへ接続され、移行前の主要な機能を利用できました。
JSPの繰り返し表示や条件付き表示はReactコンポーネントへ、Strutsの画面遷移はクライアントサイドルーティングへ置き換えられています。
手作業とレビュー
今回の検証では、Bobが段階的にコード生成とビルドを進めましたが、生成直後からすべての画面機能が完成していたわけではありません。
最初にプロジェクトの基本構造が生成され、その後のサブタスクでコンポーネント実装やAPI接続が行われました。
また、生成されたコードについては、少なくとも次の点を開発者が確認する必要があります。
- 業務ロジックが維持されているか
- 入力チェックがバックエンドにも残っているか
- エラー処理が適切か
- APIが不要な情報を返していないか
- 認証や認可が正しく実装されているか
- 依存ライブラリーに問題がないか
- 変換前後で動作に差がないか
UI Modernization Workflowの便利だと感じた点
既存アプリケーションの調査から始められる
Strutsアプリケーションを手作業で調査する場合、struts.xml、Action、JSP、Service、Repository、web.xmlなどを横断して確認する必要があります。
UI Modernization Workflowでは、最初にアプリケーションを分析し、構造や移行候補をファイルとして出力します。
分析結果が常に完全とは限りませんが、既存コードを調査する際の出発点として利用できます。
UIとバックエンドの分離方針を整理できる
今回の検証では、JSPとStruts ActionをReactとREST APIへ置き換えながら、ServiceやRepositoryは再利用されました。
このように、どのコードを移行し、どのコードを維持するかを整理しながら進められる点は、単純なコード生成とは異なるメリットです。
計画を確認しながら段階的に進められる
UI Modernization Workflowは、最初からすべてのコードを一度に書き換えるのではなく、分析、移行先の選択、バックエンド生成、フロントエンド生成という流れで進みます。
各段階で生成内容を確認できるため、AIの提案をそのまま採用するのではなく、開発者がレビューするためのたたき台として利用できます。
注意が必要な点
生成されたコードのレビューは必要
ビルドや起動に成功しても、本番環境でそのまま利用できるとは限りません。
特に、認証・認可、入力チェック、例外処理、ログ、セキュリティ、性能などは、アプリケーションの要件に沿って確認する必要があります。
UI Modernization Workflowは、レビューやテストを不要にするものではなく、モダナイズ作業を進めるための支援機能として捉えるのがよさそうです。
元のアプリケーション構造によって難易度が変わる
今回使用したアプリケーションは、Action、Service、Repositoryなどの責務をあらかじめ分離しています。
一方、実際のレガシーアプリケーションでは、次のような実装が含まれる可能性があります。
- Actionから直接SQLを実行している
- JSPにスクリプトレットや業務ロジックが含まれている
- セッションに多くの状態を保持している
- 独自のJSPタグを使用している
- 複数画面が巨大なActionに依存している
- 外部システムと密接に連携している
このようなケースでは、今回の検証よりも多くの分析、修正、テストが必要になると考えられます。
まとめ
今回は、Struts+JSPで作成したタスク管理アプリケーションを使用して、IBM BobのUI Modernization Workflowを試しました。
今回確認できた主な内容は次のとおりです。
- 既存のStruts+JSPアプリケーションを分析できた
- 移行前のアーキテクチャと移行先候補が出力された
- Struts ActionがQuarkusのREST APIへ移行された
- Service、Repository、Domain、Validatorが再利用された
- JSPがReact+Carbon Design SystemのUIへ置き換えられた
- 一覧、登録、詳細、完了処理が新しい構成で動作した
- コード生成後も、開発者によるレビューとテストが必要だった
特に便利だと感じたのは、単にJSPをReactへ変換するのではなく、既存アプリケーションを分析し、UIとバックエンドの分離方針を確認しながら進められる点です。
一方で、実際の業務アプリケーションには、認証・認可、セッション、複雑な画面遷移、独自タグ、外部システム連携など、今回のサンプルには含まれていない要素があります。
そのため、導入時は小規模なアプリケーションや一部の画面から試し、分析結果や生成コードの品質、必要な手作業の範囲を確認したうえで、段階的に対象を広げるのがよさそうです。
IBM BobのUI Modernization Workflowは、レガシーJavaアプリケーションの調査と移行をすべて自動化するものではありません。しかし、既存構造の把握、移行計画の作成、最初のコード生成を支援することで、モダナイゼーションを開始しやすくする機能だと感じました。


















