Minibank Architecture:Javaサービスを全体へ置く
最後に、Next.js、Spring Boot Payment Service、PostgREST、PostgreSQL RPC、Ledgerの責任を1本の処理としてつなぎます。現在の実装範囲と、まだ保証されていない部分も区別します。
Java / Spring Bootを入口に、金融システムのService・Repository・Transaction設計を読む。
先に学ぶ内容 — Prerequisite: ソフトウェア工学 / 銀行システム学ぶこと — LEARNING GOALS
このページで学ぶこと
- Payment Serviceの全体位置
- 1件の振込依頼とOTP確認の流れ
- 現在の実装範囲と次に必要な検証
体験19 · JAVA MINIBANK ARCHITECTURE(全体への位置づけ)
Javaが失敗したとき、自動で別経路に切り替わるか確かめよう
まずは予想をひと言。本文を読んだ後、教材内の参照元で実際のJavaコードを確認します。
- 01まず予想する — PREDICT
まずここだけ:思ったことをひと言書く
新しく追加されたJavaのサービスが動かなくなったら、既存の仕組み(Next.js)は自動的にそちらを迂回してくれるでしょうか?
正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。
ヒント1を見る
処理が本当に成功したか分からないとき、別の経路でもう一度実行してよいでしょうか?
ヒント2を見る
JavaがLedgerや残高を直接管理していたら、既存の仕組みとの責任分担はどうなっていたでしょうか?
もっと詳しく:この問いで使う専門用語
- 段階的移行は、既存機能を保ちながら新しい経路を小さく追加することです。
- fail-closedは、結果が不明なときに処理を続けず失敗として止める考え方です。
- 責任境界は、各部品が決めることと決めないことを分けることです。
日常語で理解する — PLAIN LANGUAGE
まず、ここだけつかむ
Payment Serviceは既存Minibankを置き換えず、振込処理を段階的にJava化する追加のAPI境界です。
Next.jsは設定で入口を選び、Javaがうまく動かないときも、確認できない結果を「動いたことにしない」よう自動では別経路へ切り替えません。
Spring BootはHTTPと型付きユースケースを担当し、正式な認可・残高・冪等性・Ledgerは既存PostgreSQL RPCへ残します。
コードが存在することと運用可能であることは別です。統合・競合・障害・監視・デプロイの検証が必要です。
振込を実際に処理する仕組みは2種類のうちどちらかが設定で選ばれており、途中で自動的に切り替わることはありません。どちらが使われているかは、この教材だけでは確認できません。
順番に理解する — DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
段階的移行
既存機能を保ちながら新しい経路を小さく追加します。
一括置換の障害範囲と戻しにくさを抑えるためです。
PAYMENT_BACKENDで既存経路とJava Payment Serviceを明示的に切り替えます。
fail-closed
結果が不明な時に、別経路で処理を続けず失敗として止めます。
DB commit後の通信断で自動fallbackすると二重送金になり得るためです。
Java障害をlegacy処理へ自動fallbackしません。
責任境界
各部品が決めることと決めないことを分けます。
同じ規則の重複と迂回経路を防ぐためです。
JavaはHTTP、DB RPCは金融判断を担当します。
End-to-End検証
入口から正式記録まで一連の経路を試すことです。
各部品単体が動いてもtokenや変換の接続で失敗するためです。
Java APIからPostgREST、RPC、Ledgerまで確認が必要です。
発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。
Java経路の実装と稼働確認を分ける
request/confirmはPAYMENT_BACKENDで選択します。未設定・空文字・legacyはNext.js→PostgREST RPC、javaはNext.js→Java Payment Service→PostgREST RPCです。不正な値はエラー、Javaのtimeout・5xx・通信断でもlegacyへ自動fallbackしません。旧OTP再発行はこの切替の対象外で、v7のRPCは常に42501で拒否します。TOTPの認可準備はNext.jsの/api/v1/transfers/mfaが担います。コードの存在は確認済みですが、本番・PreviewでJavaが選択されているかはUNKNOWNです。
- 01Next.jsがPAYMENT_BACKENDを読む
- 02legacy:呼出者tokenでPostgRESTへ / java:Java Payment ServiceへHTTP
- 03request_transfer / confirm_transfer_otpでDB処理
- 04Javaの@TransactionalではHTTP先のcommitを取り消せない
- 05応答消失時は結果不明。別backendへ自動fallbackしない
追加されたJavaサービスは、既存システムを置き換えない
Payment Serviceは既存Next.js API、Supabase RPC、PostgreSQL関数と並行する段階的な追加です。正式な金融ルールとLedgerは既存DB側に残します。
JavaはHTTP APIの別入口、型付きのユースケース層、PostgRESTへのGatewayを提供します。既存Web教材や既存実装を統合・削除するものではありません。
| 構成要素 | 主な責任 | 持たない責任 |
|---|---|---|
| Next.js | 画面・既存API・利用者体験 | Javaプロセスの実行 |
| Spring Boot | Payment HTTP契約・型・オーケストレーション | 残高lock・Ledger直接更新 |
| PostgREST | HTTP RPCとtoken文脈の橋渡し | UI表示 |
| PostgreSQL RPC | 認可・状態・lock・transaction・idempotency | HTTP DTO |
| Ledger | 資金移動の正式な会計記録 | OTP画面 |
PAYMENT_BACKENDで入口を段階的に切り替える
Next.jsのTransferServiceはPAYMENT_BACKENDを読み、未設定または空ならlegacy、javaならJavaPaymentBackendへ振込依頼とOTP確認を委譲します。javaを選ぶ場合はPAYMENT_SERVICE_URLが必須で、未知の値は起動時設定エラーとして閉じます。
これは既存経路を残しながら新経路を選択可能にする、strangler fig patternの実践例です。切り戻しは設定をlegacyへ明示的に戻して行い、1件の処理途中で経路を混ぜません。
| 設定・結果 | Next.jsの動作 |
|---|---|
| 未設定 / legacy | 既存TypeScript経路を使用 |
| java | Java Payment ServiceへBearer token、requestId、Idempotency-Keyを転送 |
| 不正な設定値 | 設定エラーとしてfail-closed |
| Javaのtimeout・5xx・通信断 | 呼出元へ失敗を返し、legacyへ自動fallbackしない |
振込依頼を作る経路
- 01呼出元がBearer token・Idempotency-Key・振込入力を送る
- 02PaymentControllerが形式を検証しCommandを作る
- 03PaymentApplicationServiceがMoneyを生成
- 04PaymentRpcGatewayがrequest_transfer引数へ変換
- 05SupabaseRpcClientがtoken付きでPostgREST RPCを呼ぶ
- 06PostgreSQLが本人・KYC・口座・残高・冪等性を検査
- 07PendingPaymentを201 responseへ変換
認可を消費して振込を完了する経路
- 01paymentIdを受け取る(6桁OTP欄は互換用で、v7のDBは検証に使わない)
- 02Controllerが形式を検証
- 03ServiceがconfirmOtpを呼ぶ
- 04Gatewayがconfirm_transfer_otp RPCを呼ぶ
- 05DBが所有者・依頼期限と、TOTPで認可済みのintent(同じsession・60秒以内・未消費・内容一致)を検査
- 06成功時に振込・Ledger・残高・監査を原子的に確定
- 07completedまたは期待される業務outcomeを200 responseへ変換
現在の境界と未実装を混同しない
- Payment作成とOTP確認のController・Service・Gatewayは存在する
- Next.jsからJava APIへ切り替えるTransferServiceとJavaPaymentBackendが存在する
- reverse操作とGET系Payment APIは現在の対象外
- JavaはJPA/JDBCでDBへ直接接続しない
- Java側とNext.js adapter側には自動テストがある
- Actuator healthやadapter単体テストは業務処理のend-to-end保証ではない
コードリーディング演習
| 演習 | 確認する証拠 |
|---|---|
| 小数の円を送る | DTOの@DigitsとMoney.ofYen |
| 同じキーで金額を変えて再送 | TR009とRpcErrorMapper |
| 期限切れOTPを確認 | PaymentOtpConfirmationのoutcome |
| DBが未知のSQLSTATEを返す | INTERNAL_ERRORへの閉じ方 |
| 同時に残高を使う | Javaのステートレス性とDB RPCのlock |
体験学習の続き · LEARNING LOOP
ここまで読めましたか?続けて確認してみましょう
Javaサービスの全体位置を読んだところで、教材内の参照元で実際のコードを確認し、自分の言葉で説明してみます。
- 02仕組みを確かめる — CONCEPT CHECK
画面操作なしで、仕組みを確かめる
この仕組みは、Mini Bankの画面には現れません。次のEvidenceとCode Trail、教材本文だけで理解を進めます。
- 03証拠を確認する — EVIDENCE
何を見たか、1つずつ確かめる
Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。
画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。
- 04コードの処理経路を追う — CODE TRAIL
コードを書く必要はありません
ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。
まずJavaの入口となるユースケース層を見て、次に既存RPCへどう委譲しているかを見ます。
教材の参照元を確認する — Source Trail ↓Javaの入口となるユースケース層。既存経路を置き換えず追加する構造を探します。
services/payment-service/src/main/java/com/minibank/payment/application/PaymentApplicationService.java既存PostgreSQL RPCへそのまま委譲する境界。Javaが持たない責任を探します。
services/payment-service/src/main/java/com/minibank/payment/repository/PaymentRpcGateway.java - 05自分の言葉で説明する — EXPLAIN
LEVEL 1 — やさしい説明(まずここだけ)
なぜJavaの処理が失敗したとき、自動的に別経路(legacy)へ切り替えないのでしょうか? 短い2文を目安に説明してください。
日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。
ヒント1を見る
「fail-closed」と「自動fallback」という2つの言葉を使って書いてみましょう。
ヒント2を見る
結果が不明なまま処理を続けると何が起こり得るか考えてみましょう。
もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)
段階的移行、fail-closed、責任境界、End-to-End検証の4つを使って、Javaサービスの追加方針を説明してみましょう。
挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。
説明の確認ポイント — Checkpoint- Javaが既存経路を置き換えるものではないと説明できる
- 結果不明な失敗を自動で回避しない設計だと説明できる
理解を確かめる — CHECK YOUR UNDERSTANDING
4問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1Javaのコードがあれば本番で稼働中ですか?
request/confirmはPAYMENT_BACKENDで選択します。未設定・空文字・legacyはNext.js→PostgREST RPC、javaはNext.js→Java Payment Service→PostgREST RPCです。不正な値はエラー、Javaのtimeout・5xx・通信断でもlegacyへ自動fallbackしません。旧OTP再発行はこの切替の対象外で、v7のRPCは常に42501で拒否します。TOTPの認可準備はNext.jsの/api/v1/transfers/mfaが担います。コードの存在は確認済みですが、本番・PreviewでJavaが選択されているかはUNKNOWNです。
Q2Javaサービスは既存Next.js APIを削除しますか?
いいえ。現在は並行して追加する段階です。
Q3JavaがLedgerを直接管理しますか?
いいえ。既存PostgreSQL RPC内のLedger処理を利用します。
Q4Java呼出しがtimeoutしたらlegacyへ自動fallbackしますか?
しません。Java側でcommit済みか判別できないためfail-closedとし、同じIdempotency-Keyを使う明示的な再試行として扱います。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
教材の参照元 — SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)
Runtime Verification Status: UNKNOWN(本番・Previewでの経路選択)
- 現在の実装 — CURRENT IMPLEMENTATION — Primary Source
src/lib/config/paymentBackend.tsgetPaymentBackend切替の許容値・default・不正値拒否。稼働環境の値はUNKNOWN。 - 現在の実装 — CURRENT IMPLEMENTATION — Primary Source
src/services/TransferService.tsrequestTransfer / confirmTransferOtp / reissueTransferOtprequest/confirmのみbackend切替。残存createTransfer関数のコメントは現ACLの根拠にしない。 - 現在の実装 — CURRENT IMPLEMENTATION
src/services/JavaPaymentBackend.tsJavaへのHTTP adapterとエラー処理。自動fallbackなし。 - 未確認 — UNKNOWN
services/payment-service/README.md仕様資料。現行実装との一致は未確認。Payment Serviceの目的と起動方法 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/controller/PaymentController.javaJava APIの入口 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/application/PaymentApplicationService.javaユースケース層 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/repository/PaymentRpcGateway.java既存PostgreSQL RPCとの接続 - 現在の実装 — CURRENT IMPLEMENTATION
src/lib/config/paymentBackend.tslegacy / javaを検証する設定境界 - 現在の実装 — CURRENT IMPLEMENTATION
src/services/JavaPaymentBackend.tsNext.jsからJavaへ渡すadapter - 現在の実装 — CURRENT IMPLEMENTATION
src/services/TransferService.test.ts経路選択とfail-closedの自動テスト - 現在の実装 — CURRENT IMPLEMENTATION
src/app/api/v1/transfers/既存Next.js側の振込API