RAP CDS Pattern : Architecture simplifiée avec Table Entities

Catégorie
RAP
Publié
Auteur
Johannes

Le RAP classique nécessite plusieurs couches : table de base de données, Interface CDS View, Projection View, Behavior Definition et Service Definition. Le RAP CDS Pattern (aussi appelé CDS-only Pattern) simplifie considérablement cette architecture - avec les Table Entities comme élément central.

Le problème : Trop d’objets

Pour une simple application CRUD, le stack RAP classique nécessite :

1. Table de base de données (ZFLIGHT_BOOK)
2. Interface CDS View (ZI_FlightBooking)
3. Projection CDS View (ZC_FlightBooking)
4. Behavior Definition (ZI_FlightBooking)
5. Behavior Implementation (ZBP_I_FLIGHTBOOKING)
6. Service Definition (ZUI_FLIGHTBOOKING)
7. Service Binding (ZUI_FLIGHTBOOKING_O4)

Pour un simple objet de données, ce sont sept objets de développement - beaucoup de surcharge pour des opérations CRUD.

La solution : Table Entities

Avec les Table Entities (introduites avec ABAP Cloud 2024), la table elle-même devient l’entité :

1. Table Entity (ZI_FlightBooking) - Table + View en un
2. Behavior Definition (ZI_FlightBooking)
3. Service Definition (ZUI_FLIGHTBOOKING)
4. Service Binding (ZUI_FLIGHTBOOKING_O4)

Seulement quatre objets - et souvent aucune Behavior Implementation nécessaire.

Classique vs. CDS Pattern

AspectStack RAP classiqueCDS Pattern
Objets5-73-4
Définition tableDDL séparéDans Table Entity
Interface ViewCDS View propreTable Entity elle-même
Projection ViewRequisOptionnel
FlexibilitéMaximaleCRUD standard
Champs calculésOuiNon
AliasLibrement choisisIdentiques aux colonnes
Recommandé pourBOs complexesCRUD simple

Exemple complet : Réservation de vol

Étape 1 : Définir la Table Entity

La Table Entity combine définition de table et CDS View :

@EndUserText.label: 'Réservation de vol"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table entity zi_flightbooking {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
// Données métier
flight_date : abap.dats;
carrier_id : abap.char(3);
connection_id : abap.numc(4);
customer_id : abap.numc(10);
// Détails réservation
@Semantics.amount.currencyCode: 'zi_flightbooking.currency_code"
flight_price : abap.curr(15,2);
currency_code : abap.cuky;
booking_status : abap.char(1);
// Champs administratifs (important pour RAP !)
@Semantics.user.createdBy: true
created_by : abap.uname;
@Semantics.systemDateTime.createdAt: true
created_at : abap.utclong;
@Semantics.user.lastChangedBy: true
last_changed_by : abap.uname;
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at : abap.utclong;
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed : abap.utclong;
}

Important : Les annotations Semantics pour les champs administratifs permettent un remplissage automatique par le framework RAP.

Étape 2 : Behavior Definition

La Behavior Definition référence directement la Table Entity :

managed implementation in class zbp_i_flightbooking unique;
strict ( 2 );
define behavior for zi_flightbooking alias FlightBooking
lock master
authorization master ( instance )
etag master local_last_changed
{
// CRUD standard - le framework gère tout
create;
update;
delete;
// Champs en lecture seule
field ( readonly ) booking_id;
field ( readonly ) created_by, created_at, last_changed_by, last_changed_at;
field ( readonly : update ) carrier_id, connection_id, flight_date;
// Numérotation automatique
field ( numbering : managed ) booking_id;
// Actions simples
action confirmBooking result [1] $self;
action cancelBooking result [1] $self;
// Validation
validation validateFlightDate on save { field flight_date; }
validation validateCustomer on save { field customer_id; }
// Determination pour statut
determination setInitialStatus on modify { create; }
// Mapping - identique car Table Entity
mapping for zi_flightbooking corresponding;
}

Étape 3 : Service Definition

@EndUserText.label: 'Service Réservation Vol"
define service ZUI_FLIGHTBOOKING {
expose zi_flightbooking as FlightBooking;
}

Étape 4 : Service Binding

Name: ZUI_FLIGHTBOOKING_O4
Service: ZUI_FLIGHTBOOKING
Binding Type: OData V4 - UI

Après activation et publication, l’application Fiori Elements est prête.

Behavior Implementation (optionnelle)

Pour les Actions et Validations, vous avez besoin d’une classe d’implémentation :

CLASS zbp_i_flightbooking DEFINITION PUBLIC ABSTRACT FINAL
FOR BEHAVIOR OF zi_flightbooking.
ENDCLASS.
CLASS zbp_i_flightbooking IMPLEMENTATION.
ENDCLASS.
CLASS lhc_flightbooking DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS:
confirmBooking FOR MODIFY
IMPORTING keys FOR ACTION FlightBooking~confirmBooking
RESULT result,
cancelBooking FOR MODIFY
IMPORTING keys FOR ACTION FlightBooking~cancelBooking
RESULT result,
validateFlightDate FOR VALIDATE ON SAVE
IMPORTING keys FOR FlightBooking~validateFlightDate,
validateCustomer FOR VALIDATE ON SAVE
IMPORTING keys FOR FlightBooking~validateCustomer,
setInitialStatus FOR DETERMINE ON MODIFY
IMPORTING keys FOR FlightBooking~setInitialStatus.
ENDCLASS.
CLASS lhc_flightbooking IMPLEMENTATION.
METHOD confirmBooking.
" Mettre le statut sur 'Confirmé"
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
UPDATE FIELDS ( booking_status )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky
booking_status = 'C' ) ).
" Retourner le résultat
READ ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
result = VALUE #( FOR booking IN bookings
( %tky = booking-%tky
%param = booking ) ).
ENDMETHOD.
METHOD cancelBooking.
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
UPDATE FIELDS ( booking_status )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky
booking_status = 'X' ) ).
READ ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
result = VALUE #( FOR booking IN bookings
( %tky = booking-%tky
%param = booking ) ).
ENDMETHOD.
METHOD validateFlightDate.
READ ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
FIELDS ( flight_date )
WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking).
IF booking-flight_date < cl_abap_context_info=>get_system_date( ).
APPEND VALUE #(
%tky = booking-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'La date de vol doit être dans le futur' )
%element-flight_date = if_abap_behv=>mk-on
) TO reported-flightbooking.
APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD validateCustomer.
" Implémenter la validation client
READ ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
FIELDS ( customer_id )
WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking).
IF booking-customer_id IS INITIAL.
APPEND VALUE #(
%tky = booking-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Le client doit être spécifié' )
%element-customer_id = if_abap_behv=>mk-on
) TO reported-flightbooking.
APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD setInitialStatus.
READ ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
FIELDS ( booking_status )
WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE
ENTITY FlightBooking
UPDATE FIELDS ( booking_status )
WITH VALUE #( FOR booking IN bookings
WHERE ( booking_status IS INITIAL )
( %tky = booking-%tky
booking_status = 'O' ) ).
ENDMETHOD.
ENDCLASS.

Limitations actuelles

Le CDS Pattern est puissant, mais a des restrictions (février 2026) :

ENUMs non directement supportés

" ❌ Ne fonctionne PAS dans les Table Entities
booking_status : zbooking_status_enum;
" ✅ Solution de contournement : Champ CHAR avec Value Help
booking_status : abap.char(1);

Les valeurs Enum doivent être fournies via une Value Help séparée ou une annotation CDS.

Gestion Draft limitée

" ❌ Draft nécessite le stack RAP classique avec Projection View
with draft;
" ✅ Dans le CDS Pattern : Uniquement sans Draft possible
" Table Entity ne supporte pas draft table

Pour la fonctionnalité Draft, vous avez toujours besoin de la structure RAP classique avec Interface View et Projection View.

Pas de champs calculés

" ❌ NON possible dans Table Entity
calculated_field : abap.char(10) = concat(carrier_id, connection_id);
" ✅ CDS View classique
define view entity ZI_FlightBooking as select from zflight_book {
key booking_id,
concat(carrier_id, connection_id) as FlightNumber
}

Pas d’associations vers d’autres Table Entities

" ❌ Table Entity ne peut pas définir d'associations
association [1..1] to zi_customer as _Customer;
" ✅ Solution de contournement : CDS View séparée pour les associations

Quel pattern utiliser ?

CDS Pattern recommandé

  • Applications CRUD simples sans relations complexes
  • Maintenance données de base (clients, produits, configurations)
  • Prototypes rapides et MVPs
  • Applications sans exigence Draft
  • Entités autonomes sans hiérarchies

Stack RAP classique recommandé

  • Business Objects complexes avec hiérarchies Parent-Child
  • Gestion Draft requise
  • Champs calculés nécessaires dans la view
  • Alias de champs pour meilleure lisibilité
  • Associations entre Entities
  • Projections différentes pour différentes apps

Migration : Du CDS Pattern au stack classique

Lorsque les exigences augmentent, vous pouvez migrer :

" 1. La Table Entity reste comme table de base de données
" (Renommer en ztable_flightbooking)
" 2. Créer une nouvelle Interface CDS View
define root view entity ZI_FlightBooking
as select from ztable_flightbooking
{
key booking_id as BookingId,
" ... autres champs avec alias
}
" 3. Adapter la Behavior Definition
define behavior for ZI_FlightBooking
persistent table ztable_flightbooking
" ...

Conclusion

Le RAP CDS Pattern réduit considérablement l’effort de développement pour les applications RAP simples :

CritèreCDS PatternClassique
Objets de développement3-45-7
Temps d’apprentissagePlus courtPlus long
FlexibilitéStandardMaximum
Support DraftNonOui
AssociationsLimitéesComplètes

Pour les débutants et les applications CRUD simples, le CDS Pattern est le chemin le plus rapide vers une application Fiori fonctionnelle. Avec des exigences croissantes, on peut migrer vers le stack classique.

Articles connexes : RAP Grundlagen pour le pattern classique, Tabellen in ABAP Cloud pour les définitions de tables, RAP Managed vs Unmanaged pour la décision d’architecture et CDS Views pour les modèles de données complexes.