「このOData、何ができるAPIなんだろう?」
SAPの開発・導入に関わるエンジニアなら、一度はそう思ったことがあるはずだ。
BAPIであれば、トランザクションSE37を開けば話は早かった。関数モジュール名を入力してEnterを押せば、パラメータの型も、テーブルの構造も、一覧で確認できた。
ところがSAP OData(Web API)の世界では、SE37に相当するトランザクションは存在しない。
「このAPIはどうやって使うんだ?」と途方に暮れるSAPエンジニアは少なくない。
答えは、OData自身が持つ「設計図」にある。それがOData APIの「メタデータ」($metadata)だ。
ブラウザで特定のURLにアクセスするだけで、そのAPIの全貌を見ることができる。
本記事は、BAPIとSE37に慣れたSAPエンジニアを対象に、ODataのメタデータを参照する方法を解説する。
なお、OData APIの例として、購買発注伝票登録を行う標準API「C_PURCHASEORDER_FS_SRV」(V2)と「API_PURCHASEORDER_2(V4)を取り上げる。
ABAPエンジニアが戸惑うこと ― ODataにSE37はない
BAPIならSE37で確認できた
SAPのBAPIを使った開発では、T-Code: SE37(Function Builder)が頼りになる相棒だった。
たとえば購買発注を登録するBAPI「BAPI_PO_CREATE1」を調べるとき、SE37で関数名を入力すれば、以下の情報がすべて画面上で確認できた。
- Import パラメータ:呼び出し時に渡す入力値とその型
- Export パラメータ:処理結果として返ってくる値
- Tables パラメータ:明細データなど、テーブル形式でやり取りする構造体
- ドキュメント:パラメータの説明文
言うなれば、SE37はBAPIの「仕様書閲覧ツール/テストツール」そのものだ。
開発者はSE37を見ながらABAPコードを書き、テストも同じ画面から実行できた。これは非常に強力な開発環境だ。
SE37があったからこそ、SAPエンジニアはBAPIの仕様を短時間で把握し、開発に集中できていた。
その「当たり前」が、ODataの世界では通用しない。
ODataの場合はどこを見ればいいのか?
SAP S/4HANAやSAP BTPの時代になり、外部システムとのインターフェースの主役はOData(Web API)へと移行しつつある。IDocやRFC接続に代わり、RESTfulなWeb APIで連携するケースが増えている。
しかし、SE37のような「APIの仕様書を一覧表示するGUI」はODataには存在しない。SAPが提供する開発ツール(SAP Gateway、SEGW、Business Accelerator Hub)である程度の情報は確認できるが、現場のエンジニアが手早く「このAPIで何ができるか」を調べるには、OData自身が持つメタデータを直接参照するのが最も確実だ。
ODataには、APIの構造を自己記述する仕組みが標準で備わっている。それが$metadataエンドポイントだ。
これを使いこなすことが、OData時代のSAPエンジニアに求められる基本スキルとなる。
OData API の探し方や、Business Accelerator Hub の使い方について解説した記事は以下。
まずはAPIの存在確認
まず、OData API そのものが利用中のS/4に存在するかを確認する。
OData API では以下のT-CDを利用してAPIの存在や有効かどうかを確認できる。APIのバージョンによって使い分けなければならない点が少々面倒だ。
- V2の場合:
/IWFND/MAINT_SERVICE - V4の場合:
/IWBEP/V4_ADMIN
コマンドボックスからT-CDを呼び出す際は、次のように「/n」を先頭に付けて呼び出す。
/n/IWBEP/V4_ADMIN
購買発注APIもV2とV4で分かれており、それぞれ以下の通り。
- V2: API_PURCHASEORDER_PROCESS_SRV
- V4: API_PURCHASEORDER_2
V2の API_PURCHASEORDER_PROCESS_SRV については、登録済みの購買伝票を取得するサンプルを、ABAP版とExcelマクロ版それぞれ以下の記事で公開している。是非参考にしてほしい。

OData APIを有効化する手順について解説した記事は以下。

APIのサービスドキュメント
APIのサービスドキュメントとは
その OData API が何者なのかは、APIのサービスドキュメントを参照すればよい。
APIのサービスドキュメント
- そのAPIでアクセスできるデータの入口(エンティティセット)の一覧
APIのサービスドキュメントをBAPIおよびSE37にたとえると、以下のようなイメージだ。
| OData API | BAPIにたとえると | SE37でいうと |
|---|---|---|
| サービスドキュメント | OData APIの中身の一覧 | IMPORT/EXPORT/TABLE など、どの「タブ」が存在しているか俯瞰しているイメージ |
| エンティティセット | データ単位(ヘッダ・明細など) | どのようなIMPORT(ヘッダ)/EXPORT(出力項目)/TABLE(明細)が実装されているかを確認する |
| $metadata | インターフェース定義 | パラメータ+型定義(SE37の詳細画面 |
APIをブラウザで叩いてみる
ブラウザのURLにAPIを指定して叩くと、APIのサービスドキュメントを参照できる。
たとえば購買発注APIの場合、以下のURLでAPIを指定すれば、サービスドキュメントを呼び出すことができる。
V2: C_PURCHASEORDER_FS_SRV の場合
https://<ホスト(:ポート)>/sap/opu/odata/sap/C_PURCHASEORDER_FS_SRV/
V2のデフォルト書式はXMLのため、上記のURLで表示されるサービスドキュメントはXML形式である。
JSON形式など書式を指定するには ?$format を指定する。
https://<ホスト(:ポート)>/sap/opu/odata/sap/C_PURCHASEORDER_FS_SRV/?$format=json
{
"d": {
"EntitySets": [
"C_BR_CFOPCategoryValHelp",
"C_BR_MaterialOriginValHelp",
"C_BR_MaterialUsageValHelp",
"C_BR_NCMValHelp",
"C_IN_GSTControlCodeValueHelp",
"C_MM_CompanyCodeValueHelp",
"C_MM_CountryValueHelp",
"C_MM_IncotermValueHelp",
"C_MM_MaterialGroupValueHelp",
"C_MM_MaterialValueHelp",
"C_MM_PlantValueHelp",
"C_MM_ProductTypeValueHelp",
"C_MM_RegionValueHelp",
"C_MM_ServicePerformerValueHelp",
"C_MM_StorLocValueHelp",
"C_MM_SupplierValueHelp",
"C_POAccountAssignmentFactSheet",
"C_PODeliveryAddressFactSheet",
"C_POMntnTaxCountryValueHelp",
"C_POScheduleLineFactSheet",
"C_POSupplierAddressFactSheet",
"C_PurchaseContractValHelp",
"C_PurchaseOrderFactSheetNote",
"C_PurchaseOrderFs",
"C_PurchaseOrderGoodsReceipt",
"C_PurchaseOrderItemNoteType",
"C_PurchaseOrderLimitItem",
"C_PurchaseOrderNoteType",
"C_PurchasingDeliveryAddressVH",
"C_PurchasingGroupValueHelp",
"C_PurchasingOrgValueHelp",
"C_PurgCustomerBPShipToAddrVH",
"C_PurOrdActACatValHelp",
"C_PurOrderItemFactSheetNote",
"C_PurOrderItemHierFactSheet",
"C_PurOrderPartnerFactSheet",
"C_PurOrdHierItmCatValueHelp",
"C_PurOrdIntrastatCmmdtyCodeVH",
"C_PurOrdIntrastatSrvcCodeVH",
"C_PurOrdItemCO2eqFootprint",
"C_PurOrdItemEnh",
"C_PurOrdItmCatValHelp",
"C_PurOrdRefPurConItm",
"C_PurOrdSuplrConfDisplay",
"C_PurOrdTaxJurisdictionValHelp",
"C_PurOrdWBSValHelp",
"C_PurReqItemByPurOrder",
"C_SuplInvPurOrdRef",
"C_SupplierPurchOrgVH",
"I_AcctAssignmentCategoryText",
"I_Address",
"I_AssetClassStdVH",
"I_AssetClassText",
"I_BatchVH",
"I_BPCustomerMultiAddrVH",
"I_BudgetPeriodStdVH",
"I_BusinessAreaStdVH",
"I_BusinessPartner",
"I_BusinessPartnerSuplrCo",
"I_BusinessPartnerVH",
"I_BusinessUserVH",
"I_ChartOfAccountsStdVH",
"I_ChartOfAccountsText",
"I_CommitmentItemStdVH",
"I_CompanyCode",
"I_CompanyCodeStdVH",
"I_ControllingArea",
"I_ControllingAreaStdVH",
"I_CostCenterText",
"I_CostCenterVH",
"I_CountryText",
"I_CountryVH",
"I_CreditControlAreaStdVH",
"I_Currency",
"I_CurrencyStdVH",
"I_Customer_VH",
"I_EarmarkedFundsDocEntryStatus",
"I_EarmarkedFundsDocTypeStdVH",
"I_EarmarkedFundsDocumentStdVH",
"I_EarmarkedFunds_DocCategory",
"I_EmrkdFndsDocumentItemStdVH",
"I_EngmntProjSrvcOrgStdVH",
"I_FixedAsset",
"I_FndsMgmtFuncnlAreaStdVH",
"I_FormOfAddressText",
"I_FunctionalAreaText",
"I_FundedProgramStdVH",
"I_FundsCenterStdVH",
"I_FundStdVH",
"I_GLAccountStdVH",
"I_GLAccountText",
"I_GoodsMovementType",
"I_GrantStdVH",
"I_IncotermsClassification",
"I_IncotermsClassificationText",
"I_InternalOrderStdVH",
"I_Language",
"I_MasterFixedAsset",
"I_MasterFixedAssetStdVH",
"I_Material",
"I_MaterialGroup",
"I_MaterialGroupText",
"I_MaterialStdVH",
"I_MaterialText",
"I_MaterialType",
"I_MM_CostCenterValueHelp",
"I_MM_GLAccountVH",
"I_PartnerFunction",
"I_PartnerFunctionText",
"I_PaymentTerms",
"I_PaymentTermsText",
"I_Plant",
"I_Producttype",
"I_ProductTypeCodeText",
"I_ProfitCenterStdVH",
"I_ProfitCenterText",
"I_ProjectNetwork",
"I_ProjectNtwkValueHelp",
"I_PurchaseContractItemStdVH",
"I_PurchaseOrder",
"I_PurchaseOrderEnhanced",
"I_PurchaseOrderItem",
"I_PurchaseOrderItemStdVH",
"I_PurchaseOrderScheduleLine",
"I_PurchaseOrderStatusValueHelp",
"I_PurchaseOrderStdVH",
"I_PurchasingDocumentStatus",
"I_PurchasingDocumentStatusText",
"I_PurchasingDocumentType",
"I_PurchasingDocumentTypeText",
"I_PurchasingGroup",
"I_PurchasingInfoRecordStdVH",
"I_PurchasingOrganization",
"I_PurgDocumentItemCategoryText",
"I_PurOrderPartnerFunctionVH",
"I_Shippinginstructiontext",
"I_StorageLocation",
"I_Supplier",
"I_SupplierConfControlKey",
"I_Supplier_VH",
"I_TaxCalculationProcedure",
"I_TaxCode",
"I_TaxJurisdiction",
"I_TransportationLocationType",
"I_TransportationLocationVH",
"I_UnitOfMeasure",
"I_User",
"I_WBSElementBasicDataStdVH",
"SAP__FormatSet",
"SAP__PDFStandardSet",
"SAP__TableColumnsSet",
"SAP__CoverPageSet",
"SAP__SignatureSet",
"SAP__HierarchySet",
"SAP__PDFHeaderSet",
"SAP__PDFFooterSet",
"SAP__ValueHelpSet",
"SAP__Currencies",
"SAP__UnitsOfMeasure",
"SAP__MyDocumentDescriptions",
"SAP__FileShareSet"
]
}
}
V4: API_PURCHASEORDER_2 の場合
https://<ホスト(:ポート)>/sap/opu/odata4/iwbep/all/srvd_a2x/sap/api_purchaseorder_2/0001/
このURLをブラウザで叩くと、以下のようなサービスドキュメントをJSON形式で取得できる。
{
"@odata.context": "$metadata",
"value": [
{
"name": "POItemReturnNextPlant",
"url": "POItemReturnNextPlant"
},
{
"name": "POSubcontractingComponent",
"url": "POSubcontractingComponent"
},
{
"name": "PurchaseOrder",
"url": "PurchaseOrder"
},
{
"name": "PurchaseOrderAccountAssignment",
"url": "PurchaseOrderAccountAssignment"
},
{
"name": "PurchaseOrderInvoicingPlan",
"url": "PurchaseOrderInvoicingPlan"
},
{
"name": "PurchaseOrderInvoicingPlanItem",
"url": "PurchaseOrderInvoicingPlanItem"
},
{
"name": "PurchaseOrderItem",
"url": "PurchaseOrderItem"
},
{
"name": "PurchaseOrderItemNote",
"url": "PurchaseOrderItemNote"
},
{
"name": "PurchaseOrderItemReturn",
"url": "PurchaseOrderItemReturn"
},
{
"name": "PurchaseOrderNote",
"url": "PurchaseOrderNote"
},
{
"name": "PurchaseOrderPartner",
"url": "PurchaseOrderPartner"
},
{
"name": "PurchaseOrderScheduleLine",
"url": "PurchaseOrderScheduleLine"
},
{
"name": "PurchaseOrderSupplierAddress",
"url": "PurchaseOrderSupplierAddress"
},
{
"name": "PurOrderItemDeliveryAddress",
"url": "PurOrderItemDeliveryAddress"
},
{
"name": "PurOrderItemPricingElement",
"url": "PurOrderItemPricingElement"
}
]
}
ここでは
"name": "PurchaseOrder""name": "PurchaseOrderItem"
がエンティティセットであり、”PurchaseOrder” は購買発注ヘッダ、”PurchaseOrderItem” は購買発注明細に該当する。
この感覚は、BAPI_PO_CREATE1 における ”POHEADER” と “POITEM” と同じだ。


なお、V4のサービスドキュメント書式はJSONに固定されているため、$format による書式指定はできない。
ODataの仕様書:メタデータを覗いてみる
OData API のメタデータ($metadata)とは
SAPのOData APIにおけるメタデータは、BAPIにおけるインターフェースをXMLで表現したものと捉えると分かりやすい。
BAPIではSE37でパラメータやデータ構造を確認していたが、ODataでは$metadataを参照することで、エンティティ(構造)、プロパティ(フィールド)、キー項目などを把握できる。
つまり、メタデータはAPIの仕様書そのもの なのだ。
対応関係はシンプルで、エンティティ=構造、エンティティセット=内部テーブル、CRUD操作=BAPIの処理種別に相当する。
なお、メタデータは OData API をSAP Gatewayでサービス公開時に自動生成される。
ブラウザでメタデータを参照する
ODataのメタデータは、ブラウザだけで確認できる。特別なツールは不要だ。SAP S/4HANA(オンプレまたはCloud)にアクセスできる環境があれば、URLを入力するだけでよい。
たとえば購買発注APIの場合、以下のURLで呼び出すことが可能だ。
V2もV4も、API名称の後に「$metadata」を追加するだけである。
https://<ホスト(:ポート)>/sap/opu/odata4/iwbep/all/srvd_a2x/sap/api_purchaseorder_2/0001/$metadata
BAPIの世界に置き換えると、$metadataは「SE37の全パラメータ定義+構造体定義(SE11)をXMLで書き出したもの」と考えると理解しやすい。
検索・登録・更新・削除の区別は?
BAPIであれば、検索・登録・更新・削除といったデータの操作方法は、汎用モジュール単位に明確に分かれていた。
購買伝票の場合、検索なら BAPI_PO_GETDETAIL、登録なら BAPI_PO_CREATE1、変更なら BAPI_PO_CHANGE … といった具合に、名称によっておよその用途がわかった。
一方、OData API の場合はどうか?
$metadataを読み込んでも、そのAPIが検索・登録・更新・削除のどの機能に対応しているのか、判別はできない。
それもそのはずで、ODataは検索・登録・更新・削除でAPIを分けていない。
HTTPメソッド:検索・登録・更新・削除を指定
BAPIとODataでは、設計思想に大きな違いがある。
OData API は機能別にAPIが用意されているわけではなく、基本的にはデータ構造が定義されているだけだ。
- BAPI: データに対する操作(検索・登録・更新・削除)
- OData: データ構造の定義(メタデータ)
ODataでは、HTTPメソッドが検索・登録・更新・削除の役割を担う。
つまり、APIを呼び出す際に、メソッドによってデータの操作方法を指定する。
各メソッドとCRUD操作の対応は以下の通りだ。
| HTTPメソッド | 操作 | BAPIでのイメージ |
|---|---|---|
| GET | 検索・照会 | BAPI_PO_GETDETAIL |
| POST | 登録・新規作成 | BAPI_PO_CREATE1 |
| PUT / PATCH | 更新(全項目/差分) | BAPI_PO_CHANGE |
| DELETE | 削除 | BAPI_PO_CHANGE(削除フラグ) |
まとめ:SAP ODataの$metadataはSE37の代わり
OData API の$metadaは、Web APIの仕様書そのものであり、Webブラウザだけで呼び出せることを解説した。
また、BAPIでは検索・登録・更新といった処理ごとに汎用モジュールが分かれている。一方、OData API は機能別にAPIが用意されているわけではなく、基本的にはデータ構造が定義されているだけだ。ここが大きな違いである。
BAPIでいう検索・登録・更新は、OData API では API 呼び出し時の HTTP メソッド、つまり GET・POST・PUT などによって制御される。この点も、BAPIに慣れているABAPエンジニアにとっては、考え方をアップデートすべき大きな変化点であり、最初は戸惑うかもしれない。
しかし、SE37で培った「構造を読む目」はそのまま活きる。$metadata は SE37 の代わりになる。そう理解した瞬間から、ODataへの抵抗感は一気に減るはずだ。
次回の記事では、$metadata についてさらに踏み込み、XMLタグを読み取りながら、APIのデータ構造を解読する方法を具体的に解説する。BAPIに慣れたABAPエンジニアが、SE37+SE11でデータ構造を理解し、プログラムを設計・開発するのと同じように OData API を扱えるようになることを目標に、丁寧に解説していく。乞うご期待。





コメント