コンテンツにスキップ

REST API 応用(子リソース・作成更新・フレームワークバージョン・エラー)

対象 URL の形 例
子のコレクション /<親>/{親キー}/child/<子> /invoices/300100001/child/invoiceLines
子の 1 件 /<親>/{親キー}/child/<子>/{子キー} /invoices/300100001/child/invoiceLines/1
孫 /child/ を重ねる /<親>/{キー}/child/<子>/{キー}/child/<孫>
親と子を一度に取得 expand と fields /invoices/300100001?expand=invoiceLines
  • 複合キーのリソースでは、URL のキーに長い 16 進の値(キーをエンコードした値)が入ることがあります。キーは自分で組み立てず、GET の応答に含まれる links(rel が self や child のもの)の href をたどります。
  • 子リソースの名前は、describe の children で確認します。

Framework Version によって変わること

Section titled “Framework Version によって変わること”
観点 Version 1〜2 Version 3 以降
expand した子の形 配列([ {...}, {...} ]) コレクション({ "items": [...], "count", "hasMore", ... })
観点 Version 1〜3 Version 4 以降
エラー応答 メッセージの文字列 エラーコード・エラーパスなどを含む JSON

設定・実装の手順(作成・更新・削除)

Section titled “設定・実装の手順(作成・更新・削除)”
  1. describe で必須属性(mandatory)と、値リストの属性を確認します。
  2. コレクションに POST します。本文の Content-Type は application/vnd.oracle.adf.resourceitem+json です。
  3. 成功すると 201 Created が返り、Location ヘッダーに作成されたリソースの URL が入ります。
  4. 子(明細など)は、親の本文に配列で含めて一緒に作成できます。あとから追加する場合は、子のコレクション(/child/<子>)に POST します。
  • Upsert-Mode ヘッダー:Upsert-Mode: true を付けた POST は、一致するデータがあれば更新、なければ作成します。作成に必要な必須属性はすべて含めます。
  • PATCH は 本文に書いた属性だけ を更新します。成功すると 200 OK と更新後のデータが返ります。
  • updatable が false の属性(ID、承認状況など)は更新できません。
  • 子の更新は、子の 1 件の URL に PATCH します。
  • 単一リソースの URL に DELETE します。成功すると本文なしの 204 No Content が返ります。
  • 業務ルール上、削除できない状態があります(例:会計処理済みのデータ)。その場合は業務側の取消・無効化の手段を使います。

DFF(付加フレックスフィールド)

Section titled “DFF(付加フレックスフィールド)”
  • DFF は、REST では親リソースの 子リソース として公開されるのが一般的です。子リソースの名前と属性名(セグメントのコード)は、環境の DFF 定義に依存します。
  • DFF を追加・変更したら、デプロイ後に describe で子リソースと属性を確認します。OIC の ERP Cloud アダプタでも、DFF・EFF を選択してマッピングできます。
  • 公開前のサンドボックスで確認したいときは、Metadata-Context: sandbox="<サンドボックス名>" ヘッダーで、そのサンドボックスの定義を使って呼び出せます。

DFF の設計は フレックスフィールドと値セット を参照してください。

ヘッダー REST-Framework-Version: <番号> で指定します。省略すると Version 1 です。各 Version の変更は 後方互換ではない ため、要件に合う Version を選んで固定します。SCIM と BPM のリソースには適用されません。

Version 主な変更点(公式「Set the REST Framework Version」より)
1 基本の Version。q は検索例(Query by Example)形式で、演算子が限られ、子での絞り込みは不可
2 q が式の形式になる。演算子の追加、子リソースの属性での絞り込み、UPPER 関数
3 expand した子がコレクション(items・hasMore などのページング情報付き)で返る
4 エラー応答に、アプリケーション固有のエラーコード、エラーの場所を示すパス、原因となった詳細が入る
5 カスタム・メソッドの戻り値が実際のデータ型で返る。一部の従属 LOV が子からルート・リソースに移る
6 各項目に @context(キー・ヘッダー・リンク・警告)が付く。リンクは @context に移る
7 行レベルの LOV(URL に lov を含む子)が隠れ、ルートの LOV だけになる
8 CLOB を Base64 ではなく文字列で扱う。複数選択の固定選択リストを配列で扱う。URL のキーの特殊文字をエンコードする
9 高精度の数値を文字列で返す。有効でないアクセサーへの fields・expand などを 400 にする。LIKE で \ によるエスケープが可能
  • リソースが対応する Version は、コンテキスト・ルートへの GET の応答(adf:extension の defaultFrameworkVersion と allowedFrameworkVersions)で確認できます。
  • 公式は最新の Version の利用を推奨しています。新規の連携は最新に近い Version で開発し、Version を上げるときは回帰テストを行います。
ステータス 主な原因 対処
400 Bad Request 必須値の不足、検証エラー、q の文法・属性の誤り データ・要求を直す。再試行しない
401 Unauthorized 認証情報がない・誤り・期限切れ 資格情報・トークンを確認、取り直す
403 Forbidden ロール・権限の不足 統合ユーザーのロールを確認
404 Not Found URL・バージョンの誤り、存在しないキー URL を確認。データセキュリティで見えない場合もある
412 Precondition Failed If-Match の ETag が一致しない(他で更新済み) 再取得してから更新し直す
500・502・503・504 サーバー側の一時的な問題、過負荷、タイムアウト 指数バックオフで再試行

Version 4 以降のエラー応答は、次のような構造の JSON です(値は説明用の例です。モック API も同じ構造で返します)。

Version 4 以降のエラー応答の構造(値は例)
{
"title": "Bad Request",
"status": "400",
"o:errorDetails": [
{
"detail": "(エラーの説明文。例:この属性は更新できません)",
"o:errorCode": "(アプリケーション固有のエラーコード)",
"o:errorPath": "(エラーが起きた場所。例:/invoices/300100001)"
}
]
}

エラー処理では、o:errorDetails の detail と o:errorCode をログに残します。Version 1〜3 では本文がメッセージの文字列だけなので、JSON として解析できない前提でコードを書きます。

複数の操作を 1 回の HTTP 要求にまとめる仕組みです。

  • 送り先はバージョンのルート(例:/fscmRestApi/resources/11.13.18.05)で、Content-Type は application/vnd.oracle.adf.batch+json です。
  • 本文の parts に、id・path・operation(get・create・update・replace・delete)・payload を並べます。
  • 全件成功か全件失敗(all-or-none) です。1 つでも失敗すると、全体が処理されません。応答には失敗した部分だけが返ります。
  • カスタム・アクションの中には、バッチで実行できないものがあります。
バッチ要求の本文(例)
{
"parts": [
{ "id": "part1", "path": "/invoices/300100001", "operation": "get" },
{ "id": "part2", "path": "/invoices/300100002", "operation": "update",
"payload": { "Description": "10月分 保守料(修正)" } }
]
}
  • GET の応答ヘッダー ETag に、リソースの版を表す値が入ります(Version 6 以降は本文の @context.headers.ETag にも入ります)。
  • If-None-Match: <ETag> 付きの GET は、変更がなければ 304 Not Modified(本文なし)を返します。
  • If-Match: <ETag> 付きの PATCH は、他で更新されていれば 412 Precondition Failed で拒否されます。
  • どちらも 単一リソース に対してのみ使えます。

CRUD に当てはまらない処理(検証、取消、クローズなど)は、カスタム・アクションとして公開されています。

  • POST で実行します。URL は /<リソース>/{キー}/action/<アクション名> の形です。
  • 要求の Content-Type は application/vnd.oracle.adf.action+json、応答は application/vnd.oracle.adf.actionresult+json です。
  • URL にアクション名を含める場合、本文には引数だけを書きます。URL に含めない場合は、本文に name と parameters を書きます。公式は前者を推奨しています。
  • 使えるアクション名と引数は、describe の actions と各リソースのドキュメントで確認します。

公式の Integration Playbook(調達)の推奨事項に、実装時の注意を加えてまとめます。

  1. 件数を絞る:q で行を、fields で属性を絞り、onlyData=true で links を省きます。
  2. ページングする:limit と offset を使います。1 回に返るのは最大 500 件です。
  3. 往復を減らす:可能なら複数の要求をまとめます(バッチ要求、expand)。
  4. 再試行を実装する:500・502・503・504 はタイムアウト処理と 指数バックオフ で再試行します。503 の応答に「Maintenance」とある場合は、メンテナンス中なので、合計で最大 8 時間程度の待機も考慮します。
  5. 並列度を抑える:公式な上限値は今回確認した範囲では公開されていません。少ない並列数から始め、503・504 やタイムアウトが増えない範囲にします。件数が多いなら FBDI に切り替えます。
  6. ログを残す:呼び出しの正確な時刻と、入力・出力のペイロードを記録します。サポートへの問い合わせ(SR)で必要になります。
  7. 公開 API だけを使う:ドキュメントにない REST API は、予告なく変更・廃止されることがあります。
  8. 読み取りが多い更新処理には ETag を使う:古いデータでの上書きを防げます。

モック API で、作成・更新・削除とエラーを試します(練習用 API プレイグラウンド でも同じことができます)。モックは保存しないため、結果は毎回の応答だけです。

モック API:作成(201)と重複エラー(400)
export BASE="https://<このサイトのURL>/api/mock/fscmRestApi/resources/11.13.18.05"
curl -s -i -u learner:welcome1 -X POST "$BASE/invoices" \
-H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
-H "REST-Framework-Version: 4" \
-d '{
"InvoiceNumber": "SMP-2026-1001",
"InvoiceCurrency": "JPY",
"InvoiceAmount": 110000,
"InvoiceDate": "2026-10-15",
"BusinessUnit": "JP01 Business Unit",
"Supplier": "サンプル商事株式会社",
"SupplierSite": "TOKYO",
"invoiceLines": [
{ "LineNumber": 1, "LineType": "Item", "LineAmount": 100000 },
{ "LineNumber": 2, "LineType": "Freight", "LineAmount": 10000 }
]
}'
# → HTTP/1.1 201 Created。同じ仕入先・同じ InvoiceNumber が既存なら 400
モック API:更新・読取専用属性のエラー・削除
# 支払条件の変更(200)
curl -s -u learner:welcome1 -X PATCH "$BASE/invoices/300100001" \
-H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
-d '{ "Description": "10月分 保守料", "PaymentTerms": "Net 30" }'
# 読取専用属性を送る → 400。Version 4 なので o:errorDetails 付きの JSON
curl -s -u learner:welcome1 -X PATCH "$BASE/invoices/300100001" \
-H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
-H "REST-Framework-Version: 4" \
-d '{ "ApprovalStatus": "APPROVED" }'
# 削除:未検証(Not validated)の請求書だけ 204、それ以外は 400(モックは実際には削除しません)
curl -s -o /dev/null -w "%{http_code}\n" -u learner:welcome1 -X DELETE "$BASE/invoices/300100026" # → 204(Not validated)
curl -s -o /dev/null -w "%{http_code}\n" -u learner:welcome1 -X DELETE "$BASE/invoices/300100001" # → 400(Validated)

上の例の値(JP01 Business Unit、Net 30、請求書 ID)は、このサイトのモック API のデータに合わせたものです。実機では、自社の営業単位・支払条件・請求書 ID に読み替えます。

モック API:Version 2 と 3 で expand の形が変わる
curl -s -u learner:welcome1 -H "REST-Framework-Version: 2" \
"$BASE/invoices/300100001?expand=invoiceLines&onlyData=true" # invoiceLines は配列
curl -s -u learner:welcome1 -H "REST-Framework-Version: 3" \
"$BASE/invoices/300100001?expand=invoiceLines&onlyData=true" # invoiceLines は items を持つオブジェクト
実機:ETag を使った安全な更新
API="$FA_HOST/fscmRestApi/resources/11.13.18.05"
ETAG=$(curl -s -D - -o /dev/null -u "$FA_USER:$FA_PASS" "$API/invoices/300100001" \
| awk 'tolower($1)=="etag:" {print $2}' | tr -d '\r')
curl -s -i -u "$FA_USER:$FA_PASS" -X PATCH "$API/invoices/300100001" \
-H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
-H "If-Match: $ETAG" \
-d '{ "Description": "10月分 保守料" }'
# 他で更新されていれば 412 Precondition Failed → 再取得してやり直す
retry.py:一時的なエラーだけを指数バックオフで再試行する
import os
import random
import time
import requests
RETRYABLE = {500, 502, 503, 504}
def call_with_retry(method: str, url: str, max_attempts: int = 5, **kwargs) -> requests.Response:
kwargs.setdefault("timeout", 60)
kwargs.setdefault("auth", (os.environ["FA_USER"], os.environ["FA_PASS"]))
kwargs.setdefault("headers", {}).setdefault("REST-Framework-Version", "4")
for attempt in range(1, max_attempts + 1):
try:
r = requests.request(method, url, **kwargs)
except (requests.ConnectionError, requests.Timeout):
r = None
if r is not None and r.status_code not in RETRYABLE:
return r # 2xx と 4xx はそのまま返す(4xx は再試行しない)
if attempt == max_attempts:
break
wait = min(2 ** attempt, 60) + random.uniform(0, 1) # 2, 4, 8, 16... 秒+ゆらぎ
time.sleep(wait)
raise RuntimeError(f"{method} {url} は {max_attempts} 回失敗しました")

POST を再試行するときは、二重登録に注意します。再送の前に業務キー(例:仕入先+請求書番号)で GET して、作成済みかどうかを確かめます。

落とし穴とベストプラクティス

Section titled “落とし穴とベストプラクティス”
  • 対応する試験:OIC 模擬テスト(REST リソースの子リソース・DFF の扱い、エラー処理と再試行の設計)
  • 覚えるポイント
    • Version 2 で q の構文、Version 3 で子のコレクション化、Version 4 でエラー詳細、Version 6 で @context
    • バッチ要求は all-or-none、Content-Type は application/vnd.oracle.adf.batch+json
    • ETag:If-None-Match → 304、If-Match → 412
    • カスタム・アクションは POST、application/vnd.oracle.adf.action+json
  • 手を動かして確認:REST 演習2:子リソースの取得と作成・更新・エラー

本サイトは学習目的で個人が作成した非公式の教材であり、Oracle Corporation およびその関連会社とは関係ありません。内容の正確性は保証しません。最新の仕様・試験範囲は必ず公式ドキュメントと Oracle University の情報で確認してください。

模擬テストの問題は公開されている出題範囲(Exam Topics)と公式ドキュメントをもとに独自に作成したもので、実際の試験問題ではありません。

Oracle、Java、MySQL は Oracle Corporation およびその子会社、関連会社の米国およびその他の国における登録商標です。その他の製品名・会社名は各社の商標です。

© 2026 Fusion ERP 実装ラボ