Appearance
Lesson 2 Companion
Use this companion to explore the architecture and implementation from Lesson 2 in more depth.
It contains:
- deeper architecture explanations;
- technical distinctions that are useful when reviewing the lesson;
- complete reference implementations;
- practice-assignment reference solutions;
- troubleshooting guidance;
- current SAP documentation references.
How to use this companion
Complete the main lesson and practice work first when possible. Use this file to compare designs, review a complete implementation, or investigate why a particular choice was made.
Related Lesson 2 files:
1. Lesson 2 in the course architecture
Lesson 1 established:
text
Runner
↓
Reader
↓
ABAP SQL
↓
Database TableLesson 2 changes only the Reader's data-source dependency:
text
Runner
↓
Reader
↓
ABAP SQL
↓
CDS View Entity
↓
Database TableThat makes CDS a concrete architectural improvement rather than an isolated syntax topic.
From Lesson 1, you already know:
- OOP;
- Reader/Runner separation;
- ABAP SQL;
- SQL Console;
- Data Preview;
- internal tables;
- host variables.
The genuinely new concepts are:
- Data Definitions;
- CDS DDL;
- CDS View Entities;
- CDS element aliases;
- CDS keys;
- CDS activation;
- CDS Data Preview;
- consuming the CDS entity instead of persistence.
2. Why CDS belongs after basic SELECT
Because you have already read database data, CDS now solves a concrete problem.
Lesson 1 creates that context:
abap
SELECT FROM /dmo/carrierThat leads to a useful question:
Should every consumer couple itself directly to the persistence representation?
CDS introduces a reusable model:
text
Persistence
↓
CDS
↓
ConsumersThis sequencing keeps the abstraction motivated.
3. Current SAP direction: View Entities
Current SAP documentation describes CDS View Entities as the modern CDS view type used to define reusable data models over sources such as database tables.
This lesson therefore uses:
abap
define view entityand avoids the obsolete DDIC-based form for new development:
abap
define viewA CDS View Entity does not require the old @AbapCatalog.sqlViewName pattern used by DDIC-based CDS views.
4. Data Definition vs entity
This distinction is important because ADT presents a Data Definition repository object, while developers commonly talk about the CDS entity defined inside it.
Use:
text
Data Definition
= repository object / source container
CDS View Entity
= modeled entity defined in the sourceActivation makes the entity available to consumers.
SAP's ADT documentation describes creation of an inactive Data Definition followed by activation of the CDS entity.
5. Why the first CDS header is small
This lesson uses:
abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Carrier'ADT templates can include additional annotations depending on the backend/template.
Keeping the first header compact means you do not need to memorize annotations whose purpose has not yet been introduced.
SAP's own ABAP Flight Reference Scenario carrier example uses a similarly compact base:
text
@AccessControl.authorizationCheck
@EndUserText.label
define view entity /DMO/I_Carrier ...It additionally includes semantic text metadata for its scenario.
Semantic annotations are introduced later in this course.
6. @AccessControl.authorizationCheck
#NOT_REQUIRED is intentional because this tutorial entity has no CDS access-control role.
However, #NOT_REQUIRED does not mean:
text
"CDS should always use #NOT_REQUIRED"CDS access control is an important application-security mechanism.
When DCL is added later, Data Preview and SQL Console results can reflect CDS access controls.
7. Why use a source alias?
The source declaration:
abap
as select from /dmo/carrier as Carrierallows:
abap
Carrier.carrier_idinstead of an unqualified field name.
This creates a habit that scales naturally when later lessons introduce:
text
joins
associations
multiple data sourcesSource aliases also make CDS code easier to read.
8. CDS element aliases as a model contract
Persistence:
text
carrier_id
currency_codeCDS:
text
CarrierId
CurrencyCodeThe alias is not just cosmetic.
Consumers of the CDS entity see the CDS element names.
For example:
abap
SELECT FROM zi_carrier_###
FIELDS CarrierId,
CurrencyCodeThe consumer does not select carrier_id from that entity.
9. Why CDS View Entities list elements explicitly
Current CDS View Entity syntax does not use * in the element list to expose all source fields.
That is a useful modeling property.
A CDS data model should state the elements that belong to the entity.
It also prevents accidental exposure of new persistence fields merely because the underlying table changes.
10. CDS key semantics
The line:
abap
key Carrier.carrier_id as CarrierIdmarks CarrierId as a key element of the view entity.
Important distinction:
text
CDS key
= entity/model key semantics
database-table key
= persistence uniqueness/index semanticsThe CDS keyword does not add a unique database constraint to the source table.
For /DMO/CARRIER, the model key aligns naturally with the persisted key.
11. Activation model
The Data Definition is created inactive.
Activation:
text
Ctrl + F3creates/updates the active CDS entity in the backend.
A successful syntax check is required before activation succeeds.
The latest editor text is not automatically the active model merely because it has been typed.
If Data Preview shows an older version, check whether the latest edit was activated.
12. Data Preview vs SQL Console
Both are valuable, but they answer different developer questions.
Data Preview
Useful for:
text
What data does this CDS entity expose?
Which columns are visible?
How does filtering/sorting look?Current ADT Data Preview supports CDS DDL sources and normally retrieves a limited result set, with 100 records as the default.
SQL Console
Useful for:
text
Can I write this ABAP SQL query against the CDS entity?
What happens with WHERE / ORDER BY?
What element names does the consumer see?A good sequence is:
text
Activate CDS
↓
Data Preview
↓
SQL Console
↓
Reader13. Why keep the Reader?
It might be tempting after introducing CDS to remove the Reader and query CDS directly from the Runner.
That would weaken the OOP organization introduced in Lesson 1.
The architecture therefore keeps:
text
Runner
↓
Reader
↓
CDSbecause each layer has a different role:
text
Runner = execution/output
Reader = application data-access contract
CDS = reusable data model
Table = persistenceLater, RAP will change the application architecture significantly, but this separation makes the responsibilities clear now.
14. Why the Runner does not change
The key design lesson is that the internal implementation changes:
text
Reader → tablebecomes:
text
Reader → CDSwhile the Runner still calls:
abap
reader->get_all( )
reader->get_by_currency( ... )
reader->get_by_id( ... )This demonstrates encapsulation with a concrete example.
15. Why the Reader uses ABAP SQL aliases
The existing Reader API returns:
text
carrier_id
name
currency_codeThe CDS model exposes:
text
CarrierId
Name
CurrencyCodeThe Reader maps them:
abap
FIELDS CarrierId AS carrier_id,
Name AS name,
CurrencyCode AS currency_codeThat keeps the Reader's public contract stable.
Without those aliases, a change to the internal source could unnecessarily ripple into the Runner.
16. Reference CDS source
abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Carrier'
define view entity ZI_Carrier_###
as select from /dmo/carrier as Carrier
{
key Carrier.carrier_id as CarrierId,
Carrier.name as Name,
Carrier.currency_code as CurrencyCode
}Expected concepts:
text
Data Definition
View Entity
source alias
key
element alias
annotations17. Reference SQL Console query
abap
SELECT FROM zi_carrier_###
FIELDS CarrierId,
Name,
CurrencyCode
ORDER BY CarrierIdThe important observation is that the query uses CDS element names.
18. Reference Reader implementation
The public Reader API can remain from Lesson 1:
abap
CLASS zcl_carrier_reader_### DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_carrier,
carrier_id TYPE /dmo/carrier-carrier_id,
name TYPE /dmo/carrier-name,
currency_code TYPE /dmo/carrier-currency_code,
END OF ty_carrier,
tt_carriers TYPE STANDARD TABLE OF ty_carrier
WITH EMPTY KEY.
METHODS get_all
RETURNING VALUE(carriers) TYPE tt_carriers.
METHODS get_by_currency
IMPORTING
currency TYPE /dmo/carrier-currency_code
RETURNING
VALUE(carriers) TYPE tt_carriers.
METHODS get_by_id
IMPORTING
carrier_id TYPE /dmo/carrier-carrier_id
EXPORTING
carrier TYPE ty_carrier
found TYPE abap_bool.
ENDCLASS.The implementation changes to CDS:
abap
CLASS zcl_carrier_reader_### IMPLEMENTATION.
METHOD get_all.
SELECT FROM zi_carrier_###
FIELDS CarrierId AS carrier_id,
Name AS name,
CurrencyCode AS currency_code
ORDER BY CarrierId
INTO TABLE @carriers.
ENDMETHOD.
METHOD get_by_currency.
SELECT FROM zi_carrier_###
FIELDS CarrierId AS carrier_id,
Name AS name,
CurrencyCode AS currency_code
WHERE CurrencyCode = @currency
ORDER BY CarrierId
INTO TABLE @carriers.
ENDMETHOD.
METHOD get_by_id.
CLEAR:
carrier,
found.
SELECT SINGLE FROM zi_carrier_###
FIELDS CarrierId AS carrier_id,
Name AS name,
CurrencyCode AS currency_code
WHERE CarrierId = @carrier_id
INTO @carrier.
IF sy-subrc = 0.
found = abap_true.
ENDIF.
ENDMETHOD.
ENDCLASS.19. Runner reference
No architectural change is required.
For example:
abap
METHOD if_oo_adt_classrun~main.
DATA(reader) = NEW zcl_carrier_reader_###( ).
DATA(carriers) = reader->get_all( ).
out->write( carriers ).
ENDMETHOD.The Runner does not need to know whether the Reader reads:
text
table
CDS entity
external sourceThe Reader's public contract is what matters to the caller.
20. Practice assignment reference: Airport CDS
The practice assignment creates:
text
ZI_AIRPORT_###Reference source:
abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Airport'
define view entity ZI_Airport_###
as select from /dmo/airport as Airport
{
key Airport.airport_id as AirportId,
Airport.name as Name,
Airport.city as City,
Airport.country as Country
}21. Airport SQL Console reference
abap
SELECT FROM zi_airport_###
FIELDS AirportId,
Name,
City,
Country
ORDER BY AirportId22. Airport Reader reference implementation
Assuming the Lesson 1 practice Reader has this contract:
text
airport_id
name
city
countrythe CDS-based implementation can preserve it.
abap
CLASS zcl_airport_reader_### IMPLEMENTATION.
METHOD get_all.
SELECT FROM zi_airport_###
FIELDS AirportId AS airport_id,
Name AS name,
City AS city,
Country AS country
ORDER BY AirportId
INTO TABLE @airports.
ENDMETHOD.
METHOD get_by_country.
SELECT FROM zi_airport_###
FIELDS AirportId AS airport_id,
Name AS name,
City AS city,
Country AS country
WHERE Country = @country
ORDER BY AirportId
INTO TABLE @airports.
ENDMETHOD.
METHOD get_by_id.
CLEAR:
airport,
found.
SELECT SINGLE FROM zi_airport_###
FIELDS AirportId AS airport_id,
Name AS name,
City AS city,
Country AS country
WHERE AirportId = @airport_id
INTO @airport.
IF sy-subrc = 0.
found = abap_true.
ENDIF.
ENDMETHOD.
ENDCLASS.The Runner can remain unchanged if its public Reader contract is unchanged.
23. Practice conceptual answers
Why introduce CDS if the Reader already works?
Because the Reader currently depends directly on persistence. CDS creates a reusable data-model contract that can be shared and enriched independently of individual Reader implementations.
Does CDS replace the database table?
No. In this example /DMO/CARRIER or /DMO/AIRPORT remains the persistence source.
Does CDS replace ABAP SQL?
No. ABAP SQL can consume CDS entities.
Does CDS replace the Reader?
No. They have different responsibilities.
Why can the Runner remain unchanged?
Because the Reader keeps the same public method contract while its internal data source changes.
Why use CDS aliases such as AirportId?
The CDS model defines its own business-oriented element names independently of persistence naming.
24. Common troubleshooting
Data Definition wizard does not show exactly the same template wording
ADT/backend versions can differ.
Choose a template that creates a CDS View Entity and confirm that the generated source uses:
abap
define view entityData Preview shows an older structure
Activate the Data Definition after the latest edit:
text
Ctrl + F3Then refresh/reopen Data Preview.
Reader says CarrierId is unknown
Confirm:
- the CDS entity is active;
- the Reader selects from
ZI_CARRIER_###; - the CDS source exposes
CarrierId; - the
###suffix is consistent.
SQL Console cannot find the CDS entity
Confirm the Data Definition is activated.
Search for the entity with:
text
Ctrl + Shift + AReader compiles against the table instead of CDS
Search the Reader for:
text
/dmo/carrierAfter the refactor, executable SQL in the Reader should select from:
text
zi_carrier_###The /DMO/ type references in the Reader's public type declarations may still exist to preserve the existing public contract.
25. Topics deliberately outside Lesson 2
These topics belong later:
text
CDS joins
CDS associations
cardinality
CDS parameters
aggregations
complex expressions
DCL roles
RAP behavior
projection views
service definitions
service bindings
OData
Fiori ElementsLesson 2 establishes the data-model layer before those capabilities are added.
26. Suggested study time
| Section | Approx. time |
|---|---|
| Why CDS / architecture | 10 min |
| CDS terminology and syntax | 15 min |
| Data Definition creation | 15 min |
| Code completion / activation | 10 min |
| Data Preview | 10 min |
| SQL Console | 10 min |
| Reader refactor | 20 min |
| Run and compare architecture | 10 min |
| Review | 5 min |