Skip to Content
Technical Articles

The RAP Generator

Updates

  • 19.05.2020 – added link to GitHub repo
  • 31.05.2020 – added the demo from my SAP Online Track talk [SOT114] The RAP generator
  • 05.06.2020 – changed the code of the RAP Generator so that it works again after HFC3 has been applied
  • 10.06.2020 – Published new version that offers the following
    • Object oriented design
      • BO node class
      • BO generator class
    • Support for multiple child, grandchild, … nodes
    • Unit tests
    • Exception class

Introduction

When preparing hands-on sessions for the ABAP RESTful Programming Model (RAP) I always faced the problem that we had to start from scratch.

That means that the participants were forced to create all objects of the stack usch as table(s), Interface CDS View(s), Projection View(s), Metadata Extension View, Behavior Definition and Behavior Implementations, service definition and service binding.

Most of what a developer has to do here is to write boiler plate coding such the use of the insert all elements option when creating a CDS view based on a table or another CDS view.

For educational purposes it’s OK that you learn how to develop all the objects step by step. But if you want to provide a deep dive session it is not much fun if you have to create lots of boiler plate coding before having the chance to dive into the more interesting topics.

Also for a normal developer it would be nice to have the chance to speed up the development process by getting an up- and running starter business object.

So I was very pleased when I saw in an SAP internal review the new XCO framework (“Extension Components”) which allows you to generate various ABAP repository objects via ABAP API’s.

So I started to develop a class zcl_rap_bo_generator that allows you to generate nearly the complete stack of a RAP business object based on one (header) and multiple child and grandchild tables which is available on GitHub https://github.com/SAP-samples/cloud-abap-rap.

The second version is now available and can be tested on the trial systems where we have made the XCO framework available for you.

Special thanks for all the discussions go to Soeren Schlegel that suggested to use an object oriented approach to get to a scalable architecture as we have it now.

While the first version was only able to generate a header item scenario the second version is much more flexible.

The XCO framework is not yet available by default in customer systems but can be made available setting an appropriate feature toggle. We plan to make it available without a feature toggle in an upcoming release (2008). (as always this is our planning that can be changed at any time).

I won’t explain the XCO framework as such in great detail because this will be done by my colleague Sebastian Michler who is the product owner of this library.

What does it do?

Lets have a look at the famous flight sample and assume that you have developed four tables

  • ZRAP_TRAVEL_DEMO
  • ZRAP_BOOK_DEMO
  • ZRAP_BOOK_DEMO
  • ZRAP_BOOKS_DEMO

Based on these four tables the generator will create the following repository objects, provided you have named the entities as follows

Table name Entity Name
ZRAP_TRAVEL_DEMO Travel
ZRAP_BOOK_DEMO Booking
ZRAP_BOOK_DEMO Booking2
ZRAP_BOOKS_DEMO BookingSuppl

From these objects and names the generator builds all objects based on the naming conventions of SAP S/4HANA:

  • CDS views
  • Metadata Extensions
  • Behavior Definition
  • Behavior implementation

as shown in the following screen shot

 

 

In the console tab you will find hints how to proceed

todo:
1. create and activate service definition: ZUI_RAP_Travel_M_001
2. add the following line(s) to the service definition:
expose ZC_RAP_Travel_001 as Travel;
expose ZC_RAP_Booking_001 as Booking;
expose ZC_RAP_Booking2_001 as Booking2;
expose ZC_RAP_BookingSuppl_001 as BookingSuppl;
3. Create and activate service binding: ZUI_RAP_Travel_M_001
4. Activate local service endpoint
5. Double-click on ZC_RAP_Travel_001

In an upcoming version of the XCO framework it will also be possible to generate the service definition and the service binding.

Please note that the generated artefacts follow the naming convention which is used for the development in SAP S/4HANA.

 

How does it work?

Create a package

The generator needs a package where the ABAP artefacts that are going to be generated are stored.

Create the table(s)

Header- Travel

@EndUserText.label : 'travel data'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zrap_travel_demo {
  key client      : abap.clnt not null;
  key uuid        : sysuuid_x16 not null;
  travel_id       : /dmo/travel_id;
  agency_id       : /dmo/agency_id;
  customer_id     : /dmo/customer_id;
  begin_date      : /dmo/begin_date;
  end_date        : /dmo/end_date;
  @Semantics.amount.currencyCode : 'zrap_travel_demo.currency_code'
  booking_fee     : /dmo/booking_fee;
  @Semantics.amount.currencyCode : 'zrap_travel_demo.currency_code'
  total_price     : /dmo/total_price;
  currency_code   : /dmo/currency_code;
  description     : /dmo/description;
  overall_status  : /dmo/overall_status;
  created_by      : syuname;
  created_at      : timestampl;
  last_changed_by : syuname;
  last_changed_at : timestampl;

}

Item – Booking

@EndUserText.label : 'Booking data'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zrap_book_demo {
  key client     : abap.clnt not null;
  key uuid       : sysuuid_x16 not null;
  parent_uuid    : sysuuid_x16 not null;
  booking_id     : /dmo/booking_id;
  booking_date   : /dmo/booking_date;
  customer_id    : /dmo/customer_id;
  carrier_id     : /dmo/carrier_id;
  connection_id  : /dmo/connection_id;
  flight_date    : /dmo/flight_date;
  @Semantics.amount.currencyCode : 'zrap_book_demo.currency_code'
  flight_price   : /dmo/flight_price;
  currency_code  : /dmo/currency_code;
  booking_status : /dmo/booking_status;

}

Since this is a managed scenario where UUID’s are used as key fields for both, the header as well as the item table, the generator expects that the tables fulfill certain prerequisites:

The key field uuid must be a Universally Unique Identifier (UUID). This mandatory for a managed scenario where early numbering is used. That means where the ABAP framework automatically generates values for the key field when creating the data.

The last four fields of the header table

  • created_by
  • created_at
  • last_changed_by
  • last_changed_at

are also mandatory in a managed scenario for a root object. The framework expects these type of fields (with appropriate annotations in the root CDS interface view) so that it is able to check when data has been created and changed.

The usual process of development would be that you as a developer would now start to manually create the following repository objects

  • CDS interface view
  • CDS projection view
  • Metadata Extension view
  • Behavior definition(s)
  • Behavior implementation(s)

before you can start with the implementation of the business logic.

To speed up the process I have developed this helper class that does all the heavily lifting for you and generates this boiler plate coding for you so that we can concentrate on the implementation of the extension scenario.

Download the classes from Github

The tool now contains a large number of classes that you can download from Github.

Call the generator using a console application

So you can simply create the following console application that starts the RAP generator with appropriate parameters.

This code is also available on GitHub alongside with three sample tables.

CLASS zcl_call_rap_generator DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
  PROTECTED SECTION.
  PRIVATE SECTION.
    METHODS get_root_exception
      IMPORTING
        !ix_exception  TYPE REF TO cx_root
      RETURNING
        VALUE(rx_root) TYPE REF TO cx_root .
ENDCLASS.



CLASS zcl_call_rap_generator IMPLEMENTATION.

  METHOD if_oo_adt_classrun~main.
    TRY.

        DATA(root_bo) = NEW zcl_rap_node_m_uuid_root( 'Travel' ).

        "optional settings
        root_bo->set_prefix( 'RAP_' ).
        root_bo->set_suffix( CONV #( '_001' ) ).
        "mandatory settings
        root_bo->set_namespace( 'Z' ).
        root_bo->set_table( iv_table = 'ZRAP_TRAVEL_DEMO' ).
        root_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'TRAVEL_ID' ) ) ).
        root_bo->finalize( ).

        DATA(child1_bo) = root_bo->add_child( 'Booking' ).
        child1_bo->set_table( iv_table = 'zrap_book_demo' ).
        child1_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'BOOKING_ID' ) ) ).

        DATA(child2_bo) = root_bo->add_child( 'Booking2' ).
        child2_bo->set_table( iv_table = 'zrap_book_demo' ).
        child2_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'BOOKING_ID' ) ) ).

        DATA(child11_bo) = child1_bo->add_child( 'BookingSuppl' ).
        child11_bo->set_table( iv_table = 'zrap_books_demo' ).
        child11_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'BOOKING_SUPPL_ID' ) ) ).

        DATA(my_bo_generator) = NEW zcl_rap_bo_generator(
          iv_package          = 'ZRAP_GENERATED_OBJECTS_AF'
          io_rap_bo_root_node = root_bo
        ).

        DATA(lt_todos) = my_bo_generator->generate_bo(  ).
        out->write( lt_todos ).

      CATCH cx_xco_gen_put_exception  INTO DATA(lx_put_exception).
        out->write( 'XCO Generation: PUT exception:' ).
        DATA(lo_findings) = lx_put_exception->findings.
        DATA(lt_findings) = lo_findings->get( ).
        LOOP AT lt_findings INTO DATA(ls_findings).
          out->write( ls_findings->message->get_text(  ) ).
        ENDLOOP.
        EXIT.
      CATCH zcx_rap_generator  INTO DATA(lx_rap_generator).
        out->write( 'RAP Generator: Exception occured' ).
        out->write( lx_rap_generator->get_text(  ) ).
        IF root_bo->lt_messages IS NOT INITIAL.
          out->write( 'Additional messages:' ).
          out->write( root_bo->lt_messages ).
        ENDIF.
        EXIT.
      CATCH cx_root INTO DATA(lx_root).
        out->write( 'Other exception:' ).
        out->write( get_root_exception( lx_root )->get_longtext( ) ).
    ENDTRY.

  ENDMETHOD.

  METHOD get_root_exception.
    rx_root = ix_exception.
    WHILE rx_root->previous IS BOUND.
      rx_root ?= rx_root->previous.
    ENDWHILE.
  ENDMETHOD.

ENDCLASS.

 

This is a console application implements the interface if_oo_adt_classrun that can be used as a replacement for reports that are not available in SAP Cloud Platform, ABAP environment.

The class first instantiates the class zcl_rap_node_m_uuid_root and creates the object root_bo. This object is a container for the information of our root node object.

The root node needs the name of the root entity (here Travel) as a mandatory parameter for the constructor. Afterwards you must specify the following parameters:

  • The namespace (here ‘Z’)
  • The table used by the root entity (‘ZRAP_TRAVEL_DEMO’)
  • The semantic key field of the table (TRAVEL_ID)

In addition you can specify a prefix and a suffix that are used to generate the object names of the CDS views, behavior definition, classes and so on.

        DATA(root_bo) = NEW zcl_rap_node_m_uuid_root( 'Travel' ).

        "optional settings
        root_bo->set_prefix( 'RAP_' ).
        root_bo->set_suffix( CONV #( '_001' ) ).
        "mandatory settings
        root_bo->set_namespace( 'Z' ).
        root_bo->set_table( iv_table = 'ZRAP_TRAVEL_DEMO' ).
        root_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'TRAVEL_ID' ) ) ).
        root_bo->finalize( ).

After you have created the root node object add a child node simply by using the method add_child which takes the name of the child entity (here Booking) as a parameter and which returns an object of type zcl_rap_node_m_uuid_child.

Both classes zcl_rap_node_m_uuid_child and  zcl_rap_node_m_uuid_root inherit from the base class zcl_rap_node.

For other scenarios (unmanaged with semantic keys) I plan to provide two other classes that will also inherit from zcl_rap_node.

After having created the child node object you have to specify the table and the semantic key.

 

        DATA(child1_bo) = root_bo->add_child( 'Booking' ).
        child1_bo->set_table( iv_table = 'zrap_book_demo' ).
        child1_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'BOOKING_ID' ) ) ).

Only after having provided these mandatory parameters you can add a grand child node child11bo.

        DATA(child11_bo) = child1_bo->add_child( 'BookingSuppl' ).
        child11_bo->set_table( iv_table = 'zrap_books_demo' ).
        child11_bo->set_semantic_key_fields( it_semantic_key = VALUE #( ( 'BOOKING_SUPPL_ID' ) ) ).

 

After having created the business object the RAP generator can be called that takes the root node object and the name of a package where the repository objects are generated as mandatory parameters.

        DATA(my_bo_generator) = NEW zcl_rap_bo_generator(
          iv_package          = 'ZRAP_GENERATED_OBJECTS_AF'
          io_rap_bo_root_node = root_bo
        ).

 

The generator reads the names of the entities of header (and optionally item(s) or grand child nodes) from the root node objects and its sub node objects.

The names of the CDS views can be more meaningful as the names of the tables since the length of a CDS view name can be up to 30 characters whereas the names of DDIC tables are limited to 16 characters.

In a managed scenario that uses UUID’s as the key field we expect to have a semantic key in addition that is more human readable . (For example TravelId or BookinId as in our case or InventoryId if we would only use one table to store inventory data).

These names are needed for the metadata extension fields, they govern that these fields are marked as readonly and that appropriate methods are generated in the behavior implementation class(es) in order to calculate their values.

Since I developed this class so that it can be used in SAP CodeJams or at SAP TechEd the class accepts a suffix that contains out of an underscore and four characters, for example ‘_demo’ or ‘_0123’.

 

What is generated?

CDS – Interface view(s)

The interface view was generated such that based on the ABAP field names aliases have been created such that the ABAP field name was converted into camelCase notation.

@AbapCatalog: {
  sqlViewName: 'ZRAP_TRAVE00_001', 
  compiler.compareFilter: true, 
  preserveKey: true
}
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'CDS View forTravel'
define ROOT view ZI_RAP_TRAVEL_001
  as select from ZRAP_TRAVEL_DEMO
  composition [0..*] of ZI_RAP_Booking_001 as _Booking
  composition [0..*] of ZI_RAP_Booking2_001 as _Booking2
{
  key UUID as Uuid,
  
  TRAVEL_ID as TravelId,
  
  AGENCY_ID as AgencyId,
  
  CUSTOMER_ID as CustomerId,
  
  BEGIN_DATE as BeginDate,
  
  END_DATE as EndDate,
  
  BOOKING_FEE as BookingFee,
  
  TOTAL_PRICE as TotalPrice,
  
  CURRENCY_CODE as CurrencyCode,
  
  DESCRIPTION as Description,
  
  OVERALL_STATUS as OverallStatus,
  
  @Semantics.user.createdBy: true
  CREATED_BY as CreatedBy,
  
  @Semantics.systemDateTime.createdAt: true
  CREATED_AT as CreatedAt,
  
  @Semantics.user.lastChangedBy: true
  LAST_CHANGED_BY as LastChangedBy,
  
  @Semantics.systemDateTime.lastChangedAt: true
  LAST_CHANGED_AT as LastChangedAt,
  
  _Booking,
  
  _Booking2
}

Behavior Definition

The behavior implementation was generated such that the semantic key was marked as readonly.

also a mapping was added that maps the ABAP field names to the field names of the CDS views.

And we find a determination that was generated for the semantic key field (that has to be implemented though).

implementation managed;
define behavior for ZI_RAP_TRAVEL_001 alias Travel
implementation in class ZBP_RAP_Travel_001 unique
persistent table ZRAP_TRAVEL_DEMO
lock master
{
 field ( readonly ) TravelId;
 field ( numbering : managed ) Uuid;
 create; update; delete;

 mapping for ZRAP_TRAVEL_DEMO
{
Uuid = UUID;
TravelId = TRAVEL_ID;
AgencyId = AGENCY_ID;
CustomerId = CUSTOMER_ID;
BeginDate = BEGIN_DATE;
EndDate = END_DATE;
BookingFee = BOOKING_FEE;
TotalPrice = TOTAL_PRICE;
CurrencyCode = CURRENCY_CODE;
Description = DESCRIPTION;
OverallStatus = OVERALL_STATUS;
CreatedBy = CREATED_BY;
CreatedAt = CREATED_AT;
LastChangedBy = LAST_CHANGED_BY;
LastChangedAt = LAST_CHANGED_AT;
}
 association _Booking { create; }
 association _Booking2 { create; }
 determination CalculateSemanticKey on modify
 { create; }
}

define behavior for ZI_RAP_BOOKING_001 alias Booking
implementation in class ZBP_RAP_Booking_001 unique
persistent table zrap_book_demo
lock dependent by _Travel
{
 field ( readonly ) ParentUuid, BookingId;
 field ( numbering : managed ) Uuid;
 update; delete;

 mapping for zrap_book_demo
{
Uuid = UUID;
ParentUuid = PARENT_UUID;
BookingId = BOOKING_ID;
BookingDate = BOOKING_DATE;
CustomerId = CUSTOMER_ID;
CarrierId = CARRIER_ID;
ConnectionId = CONNECTION_ID;
FlightDate = FLIGHT_DATE;
FlightPrice = FLIGHT_PRICE;
CurrencyCode = CURRENCY_CODE;
BookingStatus = BOOKING_STATUS;
}
 association _Travel ;
 association _BookingSuppl { create; }
 determination CalculateSemanticKey on modify
 { create; }
}

define behavior for ZI_RAP_BOOKING2_001 alias Booking2
implementation in class ZBP_RAP_Booking2_001 unique
persistent table zrap_book_demo
lock dependent by _Travel
{
 field ( readonly ) ParentUuid, BookingId;
 field ( numbering : managed ) Uuid;
 update; delete;

 mapping for zrap_book_demo
{
Uuid = UUID;
ParentUuid = PARENT_UUID;
BookingId = BOOKING_ID;
BookingDate = BOOKING_DATE;
CustomerId = CUSTOMER_ID;
CarrierId = CARRIER_ID;
ConnectionId = CONNECTION_ID;
FlightDate = FLIGHT_DATE;
FlightPrice = FLIGHT_PRICE;
CurrencyCode = CURRENCY_CODE;
BookingStatus = BOOKING_STATUS;
}
 association _Travel ;
 determination CalculateSemanticKey on modify
 { create; }
}

define behavior for ZI_RAP_BOOKINGSUPPL_001 alias BookingSuppl
implementation in class ZBP_RAP_BookingSuppl_001 unique
persistent table zrap_books_demo
lock dependent by _Travel
{
 field ( readonly ) ParentUuid, RootUuid, BookingSupplId;
 field ( numbering : managed ) Uuid;
 update; delete;

 mapping for zrap_books_demo
{
Uuid = UUID;
ParentUuid = PARENT_UUID;
RootUuid = ROOT_UUID;
BookingSupplId = BOOKING_SUPPL_ID;
Article = ARTICLE;
}
 association _Travel ;
 determination CalculateSemanticKey on modify
 { create; }
}

Behavior implementation(s)

The behavior implementation contains already the definition of the method that needs to be implemented to calculate the semantic key.

Header entity Travel

CLASS LHC_TRAVEL DEFINITION INHERITING FROM CL_ABAP_BEHAVIOR_HANDLER.
  PRIVATE SECTION.
    METHODS:
      CALCULATE_SEMANTIC_KEY FOR DETERMINATION Travel~CalculateSemanticKey
        IMPORTING
          IT_KEYS FOR Travel.
ENDCLASS.

CLASS LHC_TRAVEL IMPLEMENTATION.
  METHOD CALCULATE_SEMANTIC_KEY.
  " Determination implementation goes here
  ENDMETHOD.
ENDCLASS.

Item entity Booking

CLASS LHC_BOOKING DEFINITION INHERITING FROM CL_ABAP_BEHAVIOR_HANDLER.
  PRIVATE SECTION.
    METHODS:
      CALCULATE_SEMANTIC_KEY FOR DETERMINATION Booking~CalculateSemanticKey
        IMPORTING
          IT_KEYS FOR Booking.
ENDCLASS.

CLASS LHC_BOOKING IMPLEMENTATION.
  METHOD CALCULATE_SEMANTIC_KEY.
  " Determination implementation goes here
  ENDMETHOD.
ENDCLASS.

Metadata Extension View(s)

Last not least you will find it handy that also a Metadata Extension View has been generated that automatically publishes all field on the list page as well as on the object page by setting appropriate @UI annotations. Also the administrative fields such as the UUID based key and fields like created_at are hidden by setting @UI.hidden to true.

@Metadata.layer: #CUSTOMER
@UI: {
  headerInfo: {
    typeName: 'Travel', 
    typeNamePlural: 'Travels', 
    title: {
      type: #STANDARD, 
      label: 'Travel', 
      value: 'TravelId'
    }
  }
}
annotate view ZRAP_C_TRAVEL_DEMO with
{
  @UI.lineItem: [ {
    position: 30 , 
    importance: #HIGH, 
    label: 'AgencyId'
  } ]
  @UI.identification: [ {
    position: 30 , 
    label: 'AgencyId'
  } ]
  AgencyId;
  
  @UI.lineItem: [ {
    position: 50 , 
    importance: #HIGH, 
    label: 'BeginDate'
  } ]
  @UI.identification: [ {
    position: 50 , 
    label: 'BeginDate'
  } ]
....

 

Feel free to check out more of the generated code.

 

Limitations

There are some limitations that will be fixed once the XCO framework will provide convenient API’s that I had to implement myself for the time being.

  • The tables are currently being analyzed by creating structures so that I can use RTTI API’s to read the details of the underlying fields.
    It is hence not possible to create objects in different software components. You would have thus to create the class in the software component.
  • Service Definitions and service bindings cannot yet be generated. But these are only a few mouse clicks in ADT.

Roadmap

I plan to add the following features when the next release of SAP Cloud Platform ABAP Environment is available.

  • Generation of CDS views for domain fixed values
  • Generation of Service Definition and Service Binding

 

Where can I get the source code?

The source code for the classes

  • zcl_call_rap_generator
  • zcl_rap_bo_generator
  • zcl_rap_node
  • zcl_rap_node_m_uuid_child
  • zcl_rap_node_m_uuid_root

can be found on GitHub

https://github.com/SAP-samples/cloud-abap-rap 

/
17 Comments
You must be Logged on to comment or reply to a post.
  • Great blog post Andre Fischer. This will make things substantionally easier when faced with creating several config tables for example.  I’ll test it out in the next few days.

    I guess I’ll have to edit my blog post after that as well 🙂

    Cheers

    Ian

  • Can I ask what gets generated when you have a header and an item table e.g. sales order header and sales order item?

    The reason I ask is that every blog (often from different SAP employees) I read seems to have a different take on what CDS views need to be created in such a case. Sometimes one (or more) each for both tables, and one (or more) combined CDS view(s), sometimes just one combined view, or any combination of the above options.

    This is a wonderful step forward by the way. People are going to want to use this as a normal thing, not just for TechEd demos. It is just like the table control generator in DYNPROS or all the generated code in Web Dynpro or indeed the code that gets auto-generated when you want to call a BRF+ rule.

    In every case you do not want to do the exact same thing again and again, month after month, year after year, possibly doing it slightly differently each time and missing something, when your aim to to write the exact same code as you did before.

    Cheersy Cheers

    Paul

  • Very interesting approach, thanks for sharing. Are there any prerequisites before creating the class zrap_cl_bo_generator?

    We are getting Errors since use of the sxco* elements is not permitted.

    • As I wrote the XCO framework is currently only available via a feature toggle. But we plan to make it available for all Steampunk system soon as well as for future on premise systems.

  • If I get this in console:

    start
    XCO Generation: PUT exception:
    “action | association | create | delete | determination | determine |
    draft | factory | field | function | internal | mapping | static |
    update | validation | }” expected, not “;”.
    “action | association | create | delete | determination | determine |
    draft | factory | field | function | internal | mapping | static |
    update | validation | }” expected, not “;”.
    “field | mapping | use | }” expected, not “;”.
    “action | association | create | delete | determination | determine |
    draft | factory | field | function | internal | mapping | static |
    update | validation | }” expected, not “;”.

    what has failed?

    • The generator has failed because it contained coding that I had to implement to provide a workaround for a tiny bug in the XCO framework.

      This bug was fixed with Hotfix Collection 3 that has now been applied to the trial systems.

      I have updated the code in GitHub.

      Just pull it again.

      It should work now.

      Best regards,

      Andre

       

  • Hi Andre,

    I’ve just tested your rap code in my Abap trial account, and its brilliant.

    I’ve uploaded your code in the following package:

    Rap%20code%20in%20cloud

    Rap code in cloud

    and i’ve generated my own tables and its generated successfully:

     

    Thanks!!!