ABAP RESTful Application Programming Model (RAP) Samples

repository·main·Indexed 20 days ago

https://github.com/sap-samples/abap-platform-rap-opensap

A collection of hands-on exercises designed for the openSAP course 'Building Apps with the ABAP RESTful Application Programming Model (RAP)'. The repository is organized into a 5-week curriculum covering RAP architecture, read-only List Report apps, transactional behavior, unmanaged business object runtime for brownfield scenarios, and service consumption via Web APIs.

Tokens
61.5K
Snippets
91
Records
160
Agent score
68%

What's inside abap-platform-rap-opensap

  1. Overview of ABAP RESTful Application Programming Model (RAP) Samples

    main

    This repository contains hands-on exercises designed for the openSAP course Building Apps with the ABAP RESTful Application Programming Model (RAP).

    ⚠️ CAUTION: The associated openSAP course is no longer available, and the exercises in this repository may not be up to date. For current getting-started materials, refer to the SAP Community topic page for ABAP RAP.

  2. Week 1: Introduction to ABAP RESTful Application Programming Model (RAP)

    main

    Week 1 provides an introduction to the RAP architecture and the technologies involved. While the first four units are theoretical, hands-on development begins in Unit 5.

    Hands-on Exercise Roadmap:

    • Unit 5: Preparing your ABAP development environment.
    • Unit 6: Creating your first ABAP Cloud console application.
  3. What is a Business Object Projection in RAP?

    main

    In the ABAP RESTful Application Programming Model (RAP), the projection layer is the first layer in the development flow that is service-specific. It is used to fine-tune the data model for specific consumption needs without altering the general data model layer.

    Key uses of the projection layer:

    • Service-specific fine-tuning: Adding UI annotations, value helps, calculations, or defaulting.
    • Multiple Service Types: Enabling the same Business Object to be exposed via different OData service types (e.g., a SAP Fiori UI vs. a stable Web API).
    • Role-based Access: Managing access by creating different projections for different roles (e.g., one projection for full CRUD access, another that only allows 'Approve' or 'Reject' actions).
  4. What is a Custom CDS Entity in RAP?

    main

    In the ABAP RESTful Application Programming Model (RAP), a Custom Entity acts as a wrapper for a code-based implementation that provides data, rather than reading directly from a database table or a standard CDS view.

    Custom entities are used when you need to consume data from external sources, such as a remote OData service. To make a custom entity functional, you must:

    1. Define the custom entity structure (fields).
    2. Implement the query logic in an ABAP class that implements the interface if_rap_query_provider.
    3. Link the entity to the implementation class using the @ObjectModel.query.implementedBy annotation.
  5. Create a Service Consumption Model for OData

    main

    A Service Consumption Model is an ABAP repository object that allows you to consume remote services (currently supporting OData and SOAP). It uses an external interface description (like an OData $metadata file or a WSDL) to automatically generate repository objects, including a Service Definition and an Abstract Entity. These generated objects (OData Client proxies or SOAP proxies) enable you to write ABAP code to interact with remote services.

    To create one:

    1. In ADT, right-click your package and select New > Other ABAP Repository Object.
    2. Search for and select Service Consumption Model.
    3. In the wizard, provide a name (e.g., ZSC_RAP_AGENCY_####) and set the Remote Consumption Model to OData.
    4. Upload the downloaded $metadata XML file.
    5. Provide a Prefix (e.g., RAP_####) to influence the naming of the generated abstract entities.
    6. Review the generated ABAP Artifact Name and the list of objects to be created (Service Definition and Abstract Entity).
    7. Complete the wizard by selecting a transport request.
    Generated Objects:
    - Service Consumption Model: ZSC_RAP_AGENCY_####
    - Service Definition: ZSC_RAP_AGENCY_####
    - Abstract Entity: ZRAP_####Z_TRAVEL_AGENCY_ES5
  6. Use Semantics Annotations in CDS Views

    main

    In RAP CDS views, @Semantics annotations are used to enrich fields for uniform data processing on the consumer side. Key uses include:

    • Currency Reference: Link amount fields to a currency key field using @Semantics.amount.currencyCode: 'CurrencyCode'. This ensures the system knows which currency applies to the amount.
    • Administrative Data: Prepare fields for automatic transactional updates (required for Week 3) using:
      • @Semantics.user.createdBy: true
      • @Semantics.systemDateTime.createdAt: true
      • @Semantics.user.lastChangedBy: true
      • @Semantics.systemDateTime.lastChangedAt: true
      • @Semantics.systemDateTime.localInstanceLastChangedAt: true
  7. Understand Metadata Layers and Priority

    main

    When multiple metadata extensions are defined for a single CDS entity, the @Metadata.layer annotation determines which annotations take precedence.

    • #CORE: The lowest priority layer, typically used by the application provider.
    • #CUSTOMER: The highest priority layer, used for customer-specific enhancements.

    Annotations in a higher-priority layer will override those in a lower-priority layer.

  8. Define the Business Object Composition Model

    main

    To transform a standard CDS data model into a Business Object (BO) structure capable of transactional behavior, you must define a composition tree (parent-child relationship).

    1. Define the Root Node (Parent)

    In the parent CDS view (e.g., ZI_RAP_Travel_####), change the definition to a root view and replace the standard association to the child with a composition:

    define root view entity ZI_RAP_Travel_####
      ... 
      composition [0..*] of ZI_RAP_Booking_#### as _Booking

    2. Define the Child Node

    In the child CDS view (e.g., ZI_RAP_Booking_####), replace the standard association to the parent with an association to parent:

    association to parent ZI_RAP_Travel_#### as _Travel on $projection.TravelUUID = _Travel.TravelUUID

    3. Activation

    After modifying both files, use Activate All (Ctrl+Shift+F3) to activate both the parent and child views simultaneously.

    // In Parent (Travel)
    define root view entity ZI_RAP_Travel_####
      composition [0..*] of ZI_RAP_Booking_#### as _Booking
    
    // In Child (Booking)
    association to parent ZI_RAP_Travel_#### as _Travel on $projection.TravelUUID = _Travel.TravelUUID
  9. Implement the if_rap_query_provider~select method

    main

    The select method is responsible for handling incoming OData requests and providing the corresponding data and metadata to the RAP framework.

    Key Request Objects and Methods:

    • io_request: Used to retrieve OData-specific query parameters.
      • io_request->get_paging()->get_page_size(): Retrieves the number of records requested (top).
      • io_request->get_paging()->get_offset(): Retrieves the starting position (skip).
      • io_request->get_filter()->get_as_ranges(): Retrieves the filter conditions as ranges.
      • io_request->is_data_requested(): Returns true if the client requested business data.
      • io_request->is_total_numb_of_rec_requested(): Returns true if the client requested a $count.

    Key Response Requirements:

    • io_response->set_data( ... ): Mandatory if is_data_requested() is true. This passes the retrieved business data back to the framework.
    • io_response->set_total_number_of_records( ... ): Required if is_total_numb_of_rec_requested() is true. This sets the total count of entities.
    METHOD if_rap_query_provider~select.
        DATA business_data TYPE t_business_data.
        DATA(top)     = io_request->get_paging( )->get_page_size( ).
        DATA(skip)    = io_request->get_paging( )->get_offset( ).
        DATA(requested_fields)  = io_request->get_requested_elements( ).
        DATA(sort_order)    = io_request->get_sort_elements( ).
        DATA count TYPE int8.
        TRY.
            DATA(filter_condition) = io_request->get_filter( )->get_as_ranges( ).
    
            get_agencies(
                     EXPORTING
                       filter_cond        = filter_condition
                       top                = CONV i( top )
                       skip               = CONV i( skip )
                       is_data_requested  = io_request->is_data_requested( )
                       is_count_requested = io_request->is_total_numb_of_rec_requested( )
                     IMPORTING
                       business_data  = business_data
                       count     = count
                     ) .
    
            IF io_request->is_total_numb_of_rec_requested(  ).
              io_response->set_total_number_of_records( count ).
            ENDIF.
            IF io_request->is_data_requested(  ).
              io_response->set_data( business_data ).
            ENDIF.
    
          CATCH cx_root INTO DATA(exception).
            DATA(exception_message) = cl_message_helper=>get_latest_t100_exception( exception )->if_message~get_longtext( ).
        ENDTRY.
      ENDMETHOD.
  10. Configure Projection View Annotations and Semantics

    main

    When defining a CDS projection view, use the following annotations to control behavior and UI capabilities:

    View-Level Annotations

    • @Metadata.allowExtensions: true: Enables the use of separate Metadata Extension (MDE) files to keep the CDS view clean.
    • @Search.searchable: true: Enables full-text (freestyle) search capabilities for the view.
    • @AccessControl.authorizationCheck: #CHECK: Specifies the authorization check level.

    Element-Level Annotations

    • @Search.defaultSearchElement: true: Marks a field as a searchable element for the freestyle search.
    • @Consumption.valueHelpDefinition: [{ entity: { name: 'ENTITY_NAME', element: 'ELEMENT_NAME' } }]: Defines a value help (F4 help) for a field by linking it to a target CDS entity.
    • @ObjectModel.text.element: ['FieldName']: Specifies which field contains the textual description for a given ID field (e.g., linking AgencyName to AgencyID).
    • @Semantics.amount.currencyCode: 'CurrencyField': Links a numeric amount field to its corresponding currency code field.

    Association Redirection

    To maintain the RAP hierarchy in a projection, you must redirect composition associations to their respective projection views using the redirected to composition child statement:

    _Booking : redirected to composition child ZC_RAP_Booking_####
  11. Naming conventions for Service Definitions and Bindings

    main

    When building services in RAP, use specific prefixes in your object names to indicate the intended consumption pattern:

    • UI: Use this prefix when the service is intended for UI-based consumption (e.g., ZUI_RAP_Travel_U_####).
    • API: Use this prefix when the service is intended to be consumed as a Web API.
    • Protocol Versioning: It is common practice to include the OData protocol version in the name (e.g., ZUI_RAP_Travel_U_####_O2 for OData V2).