【RAP】ADTのRAP Generatorを使ってみる

## はじめに
BTP ABAP Environmentの[2111のリリース](https://blogs.sap.com/2021/11/15/sap-btp-abap-environment-release-2111)で、RAP Generatorが使えるようになりました。RAP Generatorとは、RAP(ABAP RESTful Application Programming Model)で必要な各種オブジェクトを自動生成してくれるツールです。

RAPに必要なオブジェクトは以下のように多数あり、マニュアルで生成するのは大変でした。

- CDS View (Interface, Projection)
- Behavior Definition (Interface, Projection)
- Behavior Implementation 
- Service Definition
- Service Binding

### これまでのRAP Generator
これまでは、SAPの[Andre Fischer](https://people.sap.com/andre.fischer)氏が開発した[RAP Generator](https://blogs.sap.com/2020/05/17/the-rap-generator/)があり、JSONの設定を貼り付けたABAPクラスを実行することによって必要なオブジェクトを自動生成することができました。区別のためこれを「既存Generator」と呼ぶことにします。
既存Generatorを使うためには、[Gitリポジトリ](https://github.com/SAP-samples/cloud-abap-rap)から必要なソースをダウンロードしてくる必要があります。会社によってはGitにつなぐことが許可されないため、既存Generatorを使いたくても使えないケースもあると思います。

### 新RAP Generator
新しいRAP GeneratorはADTに組み込まれているので、追加の設定なく使うことができます（※）。なお、ADTのバージョンは最新に上げる必要があります。

※2現在のところサポートされているのはBTP ABAP環境のみです。オンプレミスではS/4HANA 2022以降で使えるようになる予定です。
https://blogs.sap.com/2021/11/15/sap-btp-abap-environment-release-2111/comment-page-1/#comment-607332


### 新旧機能比較
新RAP Generatorは登場したばかりということもあって、機能は限定されています。既存RAP Generatorは2020年から存在し、徐々に拡張されてきたため、新RAP Generatorと比べて機能が充実しています。以下は2021年12月時点の機能比較です。

|項目  |既存Generator  |新Generator  |
|---|---|---|
|サポートするシナリオ  |Managed, Unmanaged  |Managedのみ |
|複数階層のビジネスオブジェクト  |作れる  |作れない |
|ドラフト有無  |選べる  |選べない（ドラフトありになる） |
|ODataバージョン  |V2, V4  |V4のみ |

このほか、既存Generatorは[JSONの設定](https://github.com/SAP-samples/cloud-abap-rap#json-file-parameters)によって生成されるオブジェクトを細かく設定することができます。これに対して新Generatorで設定できるのはオブジェクトの名称だけです。

## 新RAP Generatorを使ってみる
私はRAPについて[OpenSAPのコース](https://open.sap.com/courses/cp13)で学んだものの、自分が作りたいものを一から作った経験はありません。RAPに対しては「作るものが多い」「[EML](https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/af7782de6b9140e29a24eae607bf4138.html?q=eml)など、新しいABAPを覚える必要がある」「なんとなく難しそう」という印象を持っています。
しかし、RAP Generatorは少なくとも、最初のハードルを下げてくれるものにはなりそうです。以降では、RAP Generatorで土台を作り、そこに徐々に機能をつけ足していくことでRAPについて学んでいきます。長くなるので何回かの記事に分ける予定です。

今回は以下を実施します。

1. テーブル定義
1. Generatorで必要なオブジェクトを生成
1. 実行してみる

＜環境＞
・BTPトライアルのABAP環境
・ADTの最新版
　⇒[参考チュートリアル](https://developers.sap.com/tutorials/abap-environment-trial-onboarding.html)

### 1. テーブル定義
以下のテーブルを定義します。

```abap
@EndUserText.label : 'Managed Person'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zperson_m {
  key client            : abap.clnt not null;
  key person_uuid       : sysuuid_x16 not null;
  first_name            : abap.char(100);
  last_name             : abap.char(100);
  email                 : abap.char(120);
  birthday              : abap.dats;
  created_by            : abp_creation_user;
  created_at            : abp_creation_tstmpl;
  last_changed_by       : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}
```
**キー項目について**
キーを自動で生成させるため、データエレメントに`sysuuid_x16`を使用します。

**管理項目について**
created_by, created_atなどの管理項目については事前定義されたデータエレメントを使用します（[RAP Reuse Data Elements](https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/84bd58e2b9354be4a7a1c91cb687815c.html)を参照）。

**last_changed_atとlocal_last_changed_atの違い**
最終更新日時を表す項目が2つありますが、それぞれ以下の意味を持っています。

- last_changed_at：ビジネスオブジェクト全体（子のエンティティも含めて）が最後に更新されたときのタイムスタンプを保持する
- local_last_changed_at：当該のエンティティについて、最後に更新されたときのタイムスタンプを保持する

ビジネスオブジェクト全体が更新されたときのタイムスタンプは、ドラフトの排他制御のため必要になります（詳しくは[Total ETag](https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/f5e8548c241b43ab82bceec030b5dc9a.html)を参照）。当該のエンティティが更新されたときのタイムスタンプは、楽観的排他制御のためのEtag（Etag master）として使われます。
Total EtagとEtag masterは目的が異なるため、別々の項目を用意する必要があります。

### 2. Generatorで必要なオブジェクトを生成
テーブルを右クリックし、"Generate ABAP Repository Objects"をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6243a74a-1ad6-90b7-99f8-0634ddca0950.png)

Generatorが二種類選べますが、ここでは"UI Service"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6724950d-5e7d-2bad-e6fc-e96286d37486.png)
次のウィザードでは、生成するオブジェクトの名称を指定します。今回は以下のように設定しました。
※大文字小文字は関係なくすべて大文字で生成されます

|項目  |設定値  |説明  |
|---|---|---|
|Data Definition Name  |zi_person_m  |CDS View(Interface View)の名前  |
|Alias Name  |Person  |CDS Viewの中で使われるエイリアスの名前  |
|Behavior Implementation Class  |zbp_person_m  |クラス名  |
|Draft Table Name  |zperson_m_d  |ドラフトテーブルの名前  |
|Service Projection Name  |zc_person_m  |CDS View(Consumption View)の名前  |
|Service Definition Name  |zperson_m  |Service Definitionの名前  |
|Service Binding Name  |zui_person_m_04  |Service Bindingの名前  |

名称を入力し終わってNextを押すと、生成されるオブジェクトの一覧が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b4552676-c18e-ef66-d109-9f3d0fc85d85.png)

Nextを押し、最後にFinishを押すとService Bindingの画面が表示されます。Publishを押して公開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/333f5c12-88b8-b926-f45e-85b020cb9879.png)

### 3. 実行してみる
エンティティ"Person"を選択して"Preview"をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/54d57506-b3a3-9c55-93d8-7e2fadf88ac1.png)

List Reportの画面が開きました。Metadata Extensionにデフォルトでアノテーションが入っているので、テーブル項目が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6e3a9e1b-8488-ae82-5b66-e30623dcc71e.png)

Person以外の項目のラベルがないので、ZI_PERSON_Mのビューで`@EndUserText.label`のアノテーションを設定します。Personについてはデータエレメントからラベルが設定されています。

```abap
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '##GENERATED Managed Person'
define root view entity ZI_PERSON_M
  as select from zperson_m as Person
{
  key person_uuid as PersonUUID,
  @EndUserText.label: 'First Name'
  first_name as FirstName,
  @EndUserText.label: 'Last Name'  
  last_name as LastName,
  @EndUserText.label: 'Email' 
  email as Email,
  @EndUserText.label: 'Birthday'
  birthday as Birthday,
  @Semantics.user.createdBy: true
  created_by as CreatedBy,
  @Semantics.systemDateTime.createdAt: true
  created_at as CreatedAt,
  @Semantics.user.localInstanceLastChangedBy: true
  last_changed_by as LastChangedBy,
  @Semantics.systemDateTime.localInstanceLastChangedAt: true
  local_last_changed_at as LocalLastChangedAt,
  @Semantics.systemDateTime.lastChangedAt: true
  last_changed_at as LastChangedAt
  
}
```
ラベルが表示されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9eab30cc-9298-08fb-3bfc-f57d319bc90a.png)

Createボタンを押すとObject Pageが開きます。Metadata Extensionに`@UI.identification`のアノテーションが定義されているので何もしなくても項目が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/511b6ecb-85d9-92f9-949c-c7d9e33ba73f.png)
項目に入力すると、右下に"Draft saved"というメッセージが出ます。"Create"を押すと、データが保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/23bd713a-abd7-e490-0fea-340fd40460f6.png)
List Report画面に戻って"Go"を押すと保存したデータが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6631d05c-72a5-5ff5-7fd7-62e5afccdf05.png)

ここまでで、RAP Generatorを使ってCRUD対応したアプリケーションができました。次回はこのアプリケーションに機能を追加していきます。

## 続編

- [【RAP】Determination, Validationを追加する](https://qiita.com/tami/items/4d0e6b619c4034511f2a)
- [【RAP】Actionを追加する](https://qiita.com/tami/items/595ec6aa30819eaaa833)
- [【RAP】Managed BOでUnmanaged Saveを実装](https://qiita.com/tami/items/f8407c0373e64d23b23e)
- [【RAP】Early Numbering](https://qiita.com/tami/items/e152bad7f82bce45ba7d)
- [【RAP】Late Numbering](https://qiita.com/tami/items/96f20feb5c1f74b22803)

## リファレンス
- [SAP - ABAP RESTful Application Programming Model (Help)](https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/289477a81eec4d4e84c0302fb6835035.html)
- [OpenSAP - Building Apps with the ABAP RESTful Application Programming Model](https://open.sap.com/courses/cp13)
- [既存RAP Generator](https://github.com/SAP-samples/cloud-abap-rap)
- [Youtube - 既存RAP Generatorの使い方](https://www.youtube.com/watch?v=c8IFkjmLhI8)