ABAP extensibility - ERP Q&A https://www.erpqna.com/tag/abap-extensibility/ Trending SAP Career News and Guidelines Tue, 28 Apr 2026 09:14:06 +0000 en-US hourly 1 https://wordpress.org/?v=7.0 https://www.erpqna.com/wp-content/uploads/2026/05/cropped-erpqna-32x32.png ABAP extensibility - ERP Q&A https://www.erpqna.com/tag/abap-extensibility/ 32 32 SAP RAP Unmanaged scenario example-Simplified https://www.erpqna.com/sap-rap-unmanaged-scenario-example-simplified/?utm_source=rss&utm_medium=rss&utm_campaign=sap-rap-unmanaged-scenario-example-simplified Thu, 04 Jul 2024 11:24:06 +0000 https://www.erpqna.com/?p=86138 SAP RAP (ABAP RESTful Application Programming Model) has two main flavors: managed and unmanaged. Let’s focus on the unmanaged version. Unmanaged SAP RAP refers to a development approach where developers have more control over the data persistence and business logic compared to the managed approach. Here are some key aspects Overall, unmanaged SAP RAP provides […]

The post SAP RAP Unmanaged scenario example-Simplified appeared first on ERP Q&A.

]]>
SAP RAP (ABAP RESTful Application Programming Model) has two main flavors: managed and unmanaged. Let’s focus on the unmanaged version.

Unmanaged SAP RAP refers to a development approach where developers have more control over the data persistence and business logic compared to the managed approach. Here are some key aspects

  1. Custom Logic: In unmanaged RAP, developers write their own custom logic for handling data retrieval, manipulation, and persistence. This gives more flexibility in how data is processed and stored.
  2. Direct Database Access: Developers can directly access the database tables and define their own data models using Core Data Services (CDS) views or ABAP classes.
  3. Explicit Service Definition: Unlike managed RAP, where service definitions are automatically generated based on annotations, unmanaged RAP requires developers to explicitly define service implementations and behaviors.
  4. Manual CRUD Operations: CRUD (Create, Read, Update, Delete) operations need to be implemented explicitly in unmanaged RAP, giving full control over how data is managed.
  5. Integration with Existing Systems: Unmanaged RAP is often used when integrating with existing systems or when there is a need for complex business logic that cannot be easily handled by the managed approach.
  6. Flexibility: Developers have more freedom to implement complex validation rules, authorization checks, and other custom requirements directly in the application logic.

Overall, unmanaged SAP RAP provides a more hands-on approach to application development compared to the managed approach, allowing developers to leverage their expertise in ABAP programming and database handling while building modern RESTful APIs.

Top of Form

In this example, we will show a simple application for Employee build with RAP Unmanaged flavors.

Development steps.

To be summarized below object will be created for Unmanaged scenario.

Table ZT01_EMPLOYEE

Base CDS View Z_I_EMPLOYEES_U

Consumption CDS view Z_C_EMPLOYEES_U

Behavior Definition

Bottom of Form

Behavior definition

Implement the Create method

Implement Update Method

Implement Delete Method

Implement Adjust_Numbers method.

Implement Save method.

Test

1. Open the Application.

2. Click on Create. Give Input value and Create.

3. New Record got created.

4. Select any Row , click on Edit.

5. Change the value and Save.

6. Record will be updated.

7. Select the Rows and click on Delete.

8. Records will be deleted.

9. In the Database table also you can see the records.

So, all the CRUD operation is successful using RAP Unmanaged flavors.

Rating: 0 / 5 (0 votes)

The post SAP RAP Unmanaged scenario example-Simplified appeared first on ERP Q&A.

]]>
Upload and modify OpenXML documents via RAP App in SAP BTP ABAP Environment https://www.erpqna.com/upload-and-modify-openxml-documents-via-rap-app-in-sap-btp-abap-environment/?utm_source=rss&utm_medium=rss&utm_campaign=upload-and-modify-openxml-documents-via-rap-app-in-sap-btp-abap-environment Thu, 13 Jun 2024 13:00:06 +0000 https://www.erpqna.com/?p=85513 Introduction In this blog post, I would like to share some insights for generating OpenXML documents by use of the RESTful Application Programming Model with Cloud-released development objects. With this app, you will be able to upload .docx templates and fill them with information from you CDS view (could be used for generating invoices, business […]

The post Upload and modify OpenXML documents via RAP App in SAP BTP ABAP Environment appeared first on ERP Q&A.

]]>
Introduction

In this blog post, I would like to share some insights for generating OpenXML documents by use of the RESTful Application Programming Model with Cloud-released development objects. With this app, you will be able to upload .docx templates and fill them with information from you CDS view (could be used for generating invoices, business documents and so on…).

Prerequesites

  • SAP BTP ABAP environment or an S/4 system to your disposal.
  • Eclipse IDE installed on your local machine with the ABAP Development Tools.

Shortcut with abapGit:

For those who are using abapGit, feel free to check out the code from my GitHub repo!

Step 1:

Create a database table with the following config (hint: do not forget to generate custom domains for mime type and attachment type)

@EndUserText.label : 'Invoice for document generation'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zmri_invoice {

  key client            : abap.clnt not null;
  key invoice           : ebeln not null;
  comments              : abap.char(30);
  attachment            : zmriattachment;
  mimetype              : zmimetype;
  filename              : zfilename;
  purchaseorder         : abap.char(30);
  price                 : abap.dec(8,2);
  local_created_by      : abp_creation_user;
  local_created_at      : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}

Step 2:

Generate ABAP repository objects by right-clicking on the previously created database table.
Choose the ABAP RESTful Application Programming Model (OData UI Service) variant.

Step 3

Create a custom action in your Behavior Definition:

managed implementation in class ZBP_R_MRI_INVOICE unique;
strict ( 2 );
with draft;
define behavior for ZR_MRI_INVOICE alias ZrMriInvoice
persistent table ZMRI_INVOICE
draft table ZMRI_INVOIC000_D
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master( global )

{
  field ( mandatory : create )
   Invoice;

  field ( readonly )
   LocalCreatedBy,
   LocalCreatedAt,
   LocalLastChangedBy,
   LocalLastChangedAt,
   LastChangedAt;

  field ( readonly : update )
   Invoice;


  create;
  update;
  delete;

  action ( features : global ) createMSWordInvoice ;

  draft action Activate optimized;
  draft action Discard;
  draft action Edit;
  draft action Resume;
  draft determine action Prepare;



  mapping for ZMRI_INVOICE
  {
    Invoice = invoice;
    Comments = comments;
    Attachment = attachment;
    Mimetype = mimetype;
    Filename = filename;
    PurchaseOrder = purchaseOrder;
    Price = price;
    LocalCreatedBy = local_created_by;
    LocalCreatedAt = local_created_at;
    LocalLastChangedBy = local_last_changed_by;
    LocalLastChangedAt = local_last_changed_at;
    LastChangedAt = last_changed_at;
  }
}

Step 4:

Implement the custom action in your behaviour implementation class:

CLASS lhc_zr_mri_invoice DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.

    CLASS-DATA: mt_data TYPE zmri_invoice.

    DATA:
          lv_content   TYPE xstring,
          lo_zip       TYPE REF TO cl_abap_zip.

    METHODS:
      get_global_authorizations FOR GLOBAL AUTHORIZATION
        IMPORTING
        REQUEST requested_authorizations FOR ZrMriInvoice
        RESULT result,

      get_global_features FOR GLOBAL FEATURES
        IMPORTING
        REQUEST requested_features FOR ZrMriInvoice
        RESULT result,

      createMSWordInvoice FOR MODIFY
        IMPORTING keys FOR ACTION ZrMriInvoice~createMSWordInvoice.

ENDCLASS.

CLASS lhc_zr_mri_invoice IMPLEMENTATION.

  METHOD get_global_authorizations.
*  This method does not need an implementation
  ENDMETHOD.

  METHOD createMSWordInvoice.

*     Select document to be filled
    SELECT * FROM zc_mri_invoice
     FOR ALL ENTRIES IN @keys
     WHERE invoice      = @keys-invoice
     INTO CORRESPONDING FIELDS OF @MT_data.
    ENDSELECT.

*     Create zip class instance
    lo_zip = NEW cl_abap_zip( ).

*     Search for main document part
    DATA lv_index TYPE string VALUE 'word/document.xml'.

*     Load attachment into zip class object
    lo_zip->load( zip = mt_data-attachment check_header = abap_false ).

*     Fetch the binaries of the XML part in the attachment
    lo_zip->get(
    EXPORTING
      name   = lv_index
    IMPORTING
      content = lv_content
    ).


* Convert the binaries of the xml into a string
    DATA(lv_string) = xco_cp=>xstring( lv_content
      )->as_string( xco_cp_character=>code_page->utf_8
      )->value.

* Search for the text to be replaced and fill with the information in your data set
    REPLACE FIRST OCCURRENCE OF '<InvoiceNumber>' IN lv_string
    WITH mt_data-Invoice.

    REPLACE FIRST OCCURRENCE OF '<Purchase Order>' IN lv_string
    WITH mt_data-PurchaseOrder.

    REPLACE FIRST OCCURRENCE OF '<Comments>' IN lv_string
    WITH mt_data-Comments.

    DATA lv_price TYPE string.
    lv_price = mt_data-Price.

    REPLACE FIRST OCCURRENCE OF '<Price>' IN lv_string
    WITH lv_price.

* Convert the changed XML string into binaries
    DATA(lv_new_content) = xco_cp=>string( lv_string )->as_xstring( xco_cp_character=>code_page->utf_8
    )->value.

* Delete "old" main document part from the zip file
    lo_zip->delete(
    EXPORTING
      name   = lv_index
    ).

* Add "new" main document part to the zip file
    lo_zip->add(
    EXPORTING
      name   = lv_index
      content = lv_new_content
    ).

* Save the new zip file
    DATA(lv_new_file) = lo_zip->save( ).

* Upload changed docx file
    MODIFY ENTITIES OF zr_mri_invoice IN LOCAL MODE ENTITY ZrMriInvoice
      UPDATE SET FIELDS WITH
      VALUE #( (
          Invoice = mt_data-Invoice
          Attachment = lv_new_file
      )  )
    FAILED failed.

    APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = 'Template successfully filled...' ) ) TO reported-ZrMriInvoice.
  ENDMETHOD.

  METHOD get_global_features.
* This method does not need to be implemented
  ENDMETHOD.


ENDCLASS.

Explanation: In this implementation class, the cl_abap_zip class (which is released for cloud development) is used to load the .docx template. If you didn’t already know, a .docx file is basically a ZIP-file. In order to get the main document part, we need to fetch the “word/document.xml” file within the zip object by applying the lo_zip->get() method. This method returns an XSTRING which has to be converted into an UTF-8 encoded string, for us to modify the content of the main document part. For the binary-to-string conversions the xco_cp class is used, which is part of the XCO library (I can only recommend using this library as it has some great features). Afterwards the converted XML-string has to be modified with the invoice details from your CDS view. The modified XML-string has to be converted back into binaries, by use of the same class. The last step is to delete the “old” main document part from the zip object and add the new document content to the zip object. Now update the attachment field in your CDS entity and that’s it. Your app should now be able to populate a .docx-file with information from your CDS view.

Step 5:

Create a metadata extension and a service binding for your Fiori Frontend and test the application:

@Metadata.layer: #CORE
@UI: { headerInfo: {
typeName: 'Invoice',
typeNamePlural: 'Invoices',
title: { type: #STANDARD, value: 'Invoice' },
         description: { type: #STANDARD, value: 'Invoice' } },
         presentationVariant: [{
         sortOrder: [{ by: 'Invoice', direction: #ASC }],
         visualizations: [{type: #AS_LINEITEM}] }] }
annotate view ZC_MRI_INVOICE with
{
  .facet: [    {
                label: 'General Information',
                id: 'GeneralInfo',
                type: #COLLECTION,
                position: 10
                },
                     { id:            'Invoicedet',
                    purpose:       #STANDARD,
                    type:          #IDENTIFICATION_REFERENCE,
                    label:         'Invoice Details',
                    parentId: 'GeneralInfo',
                    position:      10 } ]

  : { lineItem:       [ { position: 10, importance: #HIGH , label: 'Invoice Number'} ] ,
          identification: [ { position: 10 , label: 'Invoice Number' } ] }
  Invoice;
  : { lineItem:       [ { position: 20, importance: #HIGH , label: 'Purchase Order'} ] ,
           identification: [ { position: 20 , label: 'Purchase Order Number' } ] }
  PurchaseOrder;
  : { lineItem:       [ { position: 20, importance: #HIGH , label: 'Price'} ] ,
           identification: [ { position: 20 , label: 'Price' } ] }
  Price;
  : { lineItem:       [ { position: 20, importance: #HIGH , label: 'Comments'} ] ,
           identification: [ { position: 20 , label: 'Comments' } ] }
  Comments;
  :
  { lineItem:       [ { position: 30, importance: #HIGH , label: 'Attachment'}, { type: #FOR_ACTION, dataAction: 'createMSWordInvoice' , label: 'Create Invoice' } ], 
    identification: [ { position: 20 , label: 'Attachment' }] 
  }
  Attachment;

  .hidden: true
  MimeType;

  .hidden: true
  Filename;


}

Test the application by creating an entry and uploading a docx-template.

The template could look something like this:

Now select the entry and use the custom action to fill the template with your data:

After the success message, click on the attachment (template.docx) and verify that the placeholders have been filled:

Rating: 0 / 5 (0 votes)

The post Upload and modify OpenXML documents via RAP App in SAP BTP ABAP Environment appeared first on ERP Q&A.

]]>
AL11: File Management and Inspection in the SAP System https://www.erpqna.com/al11-file-management-and-inspection-in-the-sap-system/?utm_source=rss&utm_medium=rss&utm_campaign=al11-file-management-and-inspection-in-the-sap-system Tue, 11 Jun 2024 11:08:42 +0000 https://www.erpqna.com/?p=85438 Until the job comes from the customer, I think many ABAP developers superficially know the AL11 tcode. When I started to use it in detail, I noticed that the documents on this subject are outdated. Also, I couldn’t find a blog that explains the AL11 process step by step. In this blog post, I will […]

The post AL11: File Management and Inspection in the SAP System appeared first on ERP Q&A.

]]>
Until the job comes from the customer, I think many ABAP developers superficially know the AL11 tcode. When I started to use it in detail, I noticed that the documents on this subject are outdated. Also, I couldn’t find a blog that explains the AL11 process step by step. In this blog post, I will try to share step-by-step information about AL11.

The “AL11” Tcode in the SAP system is a tool used to inspect and manage data and structures in the file system. This Tcode provides access to and the ability to manipulate data in the file system within the SAP system. AL11 Tcode is commonly used to inspect, backup, restore, and perform other file operations in the SAP system.

One of the biggest advantages of AL11 is the ability to process files via ABAP by storing them in the SAP system instead of locally saving files received from third-party systems.

Generally, three operations are carried out via AL11:

1) File Viewing
2) File Uploading
3) File Deletion

Let’s briefly talk about the “CG3Z” and “CG3Y” Tcodes, which are used for file operations in the SAP system. These Tcodes are commonly used for managing and processing data within the file system, including tasks such as file transfer, upload, download, and deletion. “CG3Z” is typically used for uploading files into the SAP system, while “CG3Y” is used for exporting files from the SAP system.

CG3Y and CG3Z:

SAP ABAP Development, SAP ABAP Extensibility

SAP ABAP Development, SAP ABAP Extensibility

EPS2_GET_DIRECTORY_LISTING is a function used in the SAP system to list the files in a specific directory within the file system. This function is used to retrieve a list of files located in the specified directory. EPS2_GET_DIRECTORY_LISTING is used to examine the contents of a specific directory in the file system and retrieve details such as the names, sizes, dates, and other properties of the files within that directory. This information allows users to manage and process files in file operations and data integration processes. The EPS2_GET_DIRECTORY_LISTING function is commonly used when performing file-based operations within the SAP system, serving as a useful tool for file management and processing.

DATA: lt_dir_list  TYPE eps2filis .
    DATA: lv_xstring   TYPE xstring .
    DATA: lv_mess      TYPE string .


    DATA(lv_path) = CONV eps2filnam( '\\test\path\' ). " Path in Al11
    CONCATENATE lv_path  sy-sysid '\in' INTO lv_path .


    CALL FUNCTION 'EPS2_GET_DIRECTORY_LISTING' " this function reads file names from directory to table
      EXPORTING
        iv_dir_name            = lv_path
      TABLES
        dir_list               = lt_dir_list
      EXCEPTIONS
        invalid_eps_subdir     = 1
        sapgparam_failed       = 2
        build_directory_failed = 3
        no_authorization       = 4
        read_directory_failed  = 5
        too_many_read_errors   = 6
        empty_directory_list   = 7
        OTHERS                 = 8.

    IF sy-subrc <> 0 OR lines( lt_dir_list ) EQ 0.
      WRITE 'Directory ist leer'.
    ENDIF.

In ABAP programming language, the “OPEN DATASET” command is used for file operations. This command is used to open the specified file for reading, writing, or other operations. Here is how the “OPEN DATASET” command is used:

1. Opening a File:

OPEN DATASET <file_name> FOR INPUT|OUTPUT|APPENDING|... [IN LEGACY TEXT ENCODING|IN BYTE MODE] [MESSAGE <message_variable>].
  • <file_name>: The name of the file to be processed.
  • FOR INPUT: Open the file for reading.
  • FOR OUTPUT: Open the file for writing. If the file does not exist, it is created; if it exists, it is overwritten.
  • FOR APPENDING: Open the file for appending data at the end.
  • IN LEGACY TEXT ENCODING: Opens the file with legacy text encoding.
  • IN BYTE MODE: Opens the file in byte mode.
  • MESSAGE <message_variable>: Allows returning a message based on the operation.

2. Closing a File:

CLOSE DATASET <file_name>.
  • <file_name>: The name of the file to be closed.

3. Writing to a File:

TRANSFER <data> TO <file_name>.
  • <data>: The data to be written to the file.
  • <file_name>: The name of the file where the data will be written.

4. Reading from a File:

READ DATASET <file_name> INTO <data_variable>.
  • <file_name>: The name of the file to be read.
  • <data_variable>: The variable where the read data will be stored.

These commands are fundamental for file operations in the ABAP programming language and provide a wide range of functionality for file manipulation.

Let’s complete the explanation by providing a complete code example.

DATA: lt_dir_list  TYPE eps2filis .
    DATA: lv_xstring   TYPE xstring .
    DATA: lv_mess      TYPE string .


    DATA(lv_path) = CONV eps2filnam( '\\test\path\' ). " Path in Al11
    CONCATENATE lv_path  sy-sysid '\in' INTO lv_path .


    CALL FUNCTION 'EPS2_GET_DIRECTORY_LISTING' " this function reads file names from directory to table
      EXPORTING
        iv_dir_name            = lv_path
      TABLES
        dir_list               = lt_dir_list
      EXCEPTIONS
        invalid_eps_subdir     = 1
        sapgparam_failed       = 2
        build_directory_failed = 3
        no_authorization       = 4
        read_directory_failed  = 5
        too_many_read_errors   = 6
        empty_directory_list   = 7
        OTHERS                 = 8.

    IF sy-subrc <> 0 OR lines( lt_dir_list ) EQ 0.
      WRITE 'Directory ist leer'.
    ENDIF.


    LOOP AT lt_dir_list INTO DATA(ls_dir_file).
      CLEAR : lv_xstring , lv_mess .
      DATA(lv_file) = lv_path && '\' && ls_dir_file-name .

      OPEN  DATASET lv_file FOR INPUT IN BINARY MODE MESSAGE lv_mess .
      READ  DATASET lv_file INTO lv_xstring .
      CLOSE DATASET lv_file .

      APPEND VALUE #( file_name    = ls_dir_file-name
                      file_content = lv_xstring
                      customer     = 'CustomerName'
                      path         = lv_path ) TO mt_files.  " mt_files is coming from class as attribute
    ENDLOOP.

In the code example above:

1) We retrieve the names of the files located in the directory ‘\\test\path\’ using the ‘EPS2_GET_DIRECTORY_LISTING’ function and store them in the table ‘lt_dir_list’.
2) By looping through the ‘lt_dir_list’ table, we retrieve the file names along with their respective directories.
3) We open, read, and close the file using the OPEN, READ, CLOSE DATASET commands, and after reading the content, we store it in ‘lv_xstring’.
4) Finally, we transfer the read data into a table.

Rating: 0 / 5 (0 votes)

The post AL11: File Management and Inspection in the SAP System appeared first on ERP Q&A.

]]>
Custom Fields and Logics – Create and Capturing the Changes into Transport Request https://www.erpqna.com/custom-fields-and-logics-create-and-capturing-the-changes-into-transport-request/?utm_source=rss&utm_medium=rss&utm_campaign=custom-fields-and-logics-create-and-capturing-the-changes-into-transport-request Mon, 13 May 2024 10:09:02 +0000 https://www.erpqna.com/?p=84740 Custom fields and logics are strong tools that enable users to modify software systems to meet their unique requirements, increasing efficiency and functionality. Custom fields and logics are frequently implemented using the software system’s administration interfaces or configuration tools. Without needing to know programming, users with the proper permissions can use these interfaces to add, […]

The post Custom Fields and Logics – Create and Capturing the Changes into Transport Request appeared first on ERP Q&A.

]]>
Custom fields and logics are strong tools that enable users to modify software systems to meet their unique requirements, increasing efficiency and functionality.

Custom fields and logics are frequently implemented using the software system’s administration interfaces or configuration tools. Without needing to know programming, users with the proper permissions can use these interfaces to add, edit, or remove custom fields as well as define custom logics.

Custom Fields and logic Fiori app can be used by SAP business specialists and implementation consultants can design their own fields and enhance the existing applications that have enabled their extensibility for the key users.

Custom Logic, Data Source Extensions, and Custom Fields tabs are available by default to fulfill the business requirement.

Custom Fields: We can use this process to create and manage custom fields that can be used to improve applications that have allowed key users to extend their functionality.

Data Source Extensions: Create, edit, and delete data source extensions in order to enable the usage of existing fields in predelivered data sources.

Custom Logic: Through this process, We can develop and manage custom logic to improve applications that allow key users to extend the application logic.

We can determine whether it is or not already exists by using the search option. You can register a new filed enablement that is necessary as part of a business requirement by using the Plus (+) button.

Following the click of the + button, you will be able to search the Business context according to your needs. It will display several entries in the business contexts; you can then choose the appropriate entry based on your needs.

Complete the required fields as shown on the screen below, then click the “Create” button and proceed for publish.

Additionally, we can use the other tabs, such as UIs and reports, mail templates, form templates, and business scenarios, and add the field that is necessary to enable into any of the Fiori Apps in accordance with the requirement.

SAP has provided the options below to save changes into a Transport Request (TR) so that they can be moved into higher systems, such as the Preproduction and Production systems.

Using Configure Software Packages App, we can register the development packages that are required for the project development.

We can add our project development packages, which are already in the system, by using the Add Registration button.

and also have the choice to allow tasks and requests to be handled automatically. A Transport Request and associated task will be generated automatically for this package.

To Register the extensions into a Transport request, SAP has provide another app called Register Extensions for Transport. By using this app, the changes that done can be saved into Transport for further landscape systems.

Note: if Automatic Request and Task handling are chosen, this will be generated automatically in the event that there isn’t a transport request. Using the “Assign to Transport Request” button, we can also manually assign the transport request.

Rating: 5 / 5 (1 votes)

The post Custom Fields and Logics – Create and Capturing the Changes into Transport Request appeared first on ERP Q&A.

]]>
Streams in RAP: Uploading PDF, Excel and Other Files in RAP Application https://www.erpqna.com/streams-in-rap-uploading-pdf-excel-and-other-files-in-rap-application/?utm_source=rss&utm_medium=rss&utm_campaign=streams-in-rap-uploading-pdf-excel-and-other-files-in-rap-application Mon, 04 Mar 2024 10:56:50 +0000 https://www.erpqna.com/?p=82070 Uploading Large Object and media such as Excel or Image through your application is a common business requirement and the only way to do it through a RAP application was by extending the application and using UI5 tooling to upload the file. With the latest SAP BTP ABAP 2208 release the RAP framework now supports […]

The post Streams in RAP: Uploading PDF, Excel and Other Files in RAP Application appeared first on ERP Q&A.

]]>
Uploading Large Object and media such as Excel or Image through your application is a common business requirement and the only way to do it through a RAP application was by extending the application and using UI5 tooling to upload the file.

With the latest SAP BTP ABAP 2208 release the RAP framework now supports OData streams. It is now possible to enable your RAP application to maintain and handle Large Objects(LOBs).This feature provides end users an option to upload external files of different file formats such as PDF, XLSX, binary file format and other types hence allowing media handling.

In this Blog we will explore how to upload and handle Large Object such as PDF or Binary files without the need to extend the RAP application in BAS.

Large objects are modeled by means of the following fields:

  • Attachment
  • Mimetype
  • Filename

The field Attachment contains the LOB itself in a RAWSTRING format and is technically bound to the field Mimetype and Filename using semantics annotation.

Mimetype represents the content type of the attachment uploaded and the values for the fields Mimetype and Filename are derived from the field Attachment by the RAP framework based on the maintained CDS annotations. No attachment can exist without its mimetype and vice versa.

For example, when a PDF is uploaded the Mimetype field will be derived and populated with ‘APPLICATION/PDF’.

PDF File Uploaded from RAP application

To try this feature out I have built a simple RAP application to upload files directly using RAP Framework.

Database Table

A Database table was built as per code snippet below.

The field attachment has a data type of RAWSTRING. In BTP ABAP environment you cannot use RAWSTRING domain directly so create a custom domain with data type as RAWSTRING and Length as ‘0’ . This is important as length being ‘0’ would indicate that the RAWSTRING has No length restriction and can accommodate file of larger size. ZMIMETYPE and ZFILENAME are both of type Character and length 128.

@EndUserText.label : 'Invoice Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zinvoicetable {
  key client            : abap.clnt not null;
  key invoice           : ebeln not null;
  comments              : char30;
  attachment            : zattachment;
  mimetype              : zmimetype;
  filename              : zfilename;
  local_created_by      : abp_creation_user;
  local_created_at      : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}

Interface View

CDS annotation @Semantics.largeObject technically binds the MimeType and Filename to the Attachment.

The annotation contentDispositionPreference can be used to define whether, depending on the browser settings, the file attachment is either displayed in the browser (setting #INLINE) or downloaded when selected (option #ATTACHMENT).

Annotation @Semantics.largeObject.acceptableMimeTypes can be used to restrict the Media types which can be uploaded. The validation and Error handling on upload of unsupported media type is handled by the RAP framework.

CDS annotation @Semantics.mimeType: true was used to define the field MimeType as such.

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Invoice Table'
define root view entity ZI_INVOICETABLE
  as select from zinvoicetable
{
  key invoice               as Invoice,
      comments              as Comments,
      @Semantics.largeObject:
      { mimeType: 'MimeType',
      fileName: 'Filename',
      contentDispositionPreference: #INLINE }
      attachment            as Attachment,
      @Semantics.mimeType: true
      mimetype              as MimeType,
      filename              as Filename,
      @Semantics.user.createdBy: true
      local_created_by      as LocalCreatedBy,
      @Semantics.systemDateTime.createdAt: true
      local_created_at      as LocalCreatedAt,
      @Semantics.user.lastChangedBy: true
      local_last_changed_by as LocalLastChangedBy,
      //local ETag field --> OData ETag
      @Semantics.systemDateTime.localInstanceLastChangedAt: true
      local_last_changed_at as LocalLastChangedAt,

      //total ETag field
      @Semantics.systemDateTime.lastChangedAt: true
      last_changed_at       as LastChangedAt
}

Consumption View

@EndUserText.label: 'Invvoice Table'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
define root view entity ZC_INVOICE_TABLE
  provider contract transactional_query
  as projection on ZI_INVOICETABLE
{
  key Invoice,
      Comments,
      Attachment,
      MimeType,
      Filename,
      LocalLastChangedAt
}

Metadata Extension

From an UI perspective the User only needs to interact with the Attachment and hence Mimetype and Filename is hidden.

@Metadata.layer: #CORE
@UI: { headerInfo: {
typeName: 'Invoice',
typeNamePlural: 'Invoices',
title: { type: #STANDARD, value: 'Invoice' },
         description: { type: #STANDARD, value: 'Invoice' } },
         presentationVariant: [{
         sortOrder: [{ by: 'Invoice', direction: #ASC }],
         visualizations: [{type: #AS_LINEITEM}] }] }
annotate entity ZC_INVOICE_TABLE with
{
  @UI.facet: [    {
                label: 'General Information',
                id: 'GeneralInfo',
                type: #COLLECTION,
                position: 10
                },
                     { id:            'Invoicedet',
                    purpose:       #STANDARD,
                    type:          #IDENTIFICATION_REFERENCE,
                    label:         'Invoice Details',
                    parentId: 'GeneralInfo',
                    position:      10 },
                  {
                      id: 'Upload',
                      purpose: #STANDARD,
                      type: #FIELDGROUP_REFERENCE,
                      parentId: 'GeneralInfo',
                      label: 'Upload Invoice',
                      position: 20,
                      targetQualifier: 'Upload'
                  } ]

  @UI: { lineItem:       [ { position: 10, importance: #HIGH , label: 'Invoice Number'} ] ,
          identification: [ { position: 10 , label: 'Invoice Number' } ] }
  Invoice;
  @UI: { lineItem:       [ { position: 20, importance: #HIGH , label: 'Comments'} ] ,
           identification: [ { position: 20 , label: 'Comments' } ] }
  Comments;
  @UI:
  { fieldGroup:     [ { position: 50, qualifier: 'Upload' , label: 'Attachment'} ]}
  Attachment;

  @UI.hidden: true
  MimeType;

  @UI.hidden: true
  Filename;

}

I have created a managed Behavior definition with Draft and Created a Service definition and Service binding to expose this as a V4 UI .

managed implementation in class zbp_i_invoicetable unique;
strict ( 2 );
with draft;

define behavior for ZI_INVOICETABLE alias Invoice
persistent table ZINVOICETABLE
draft table zinvoicetdraft
lock master
total etag LocalLastChangedAt
authorization master ( instance )
etag master LastChangedAt
{

 // administrative fields: read only
  field ( readonly ) LastChangedAt, LocalLastChangedBy, LocalLastChangedAt , LocalCreatedBy ,
                      LocalCreatedAt;

  create;
  update;
  delete;

  draft action Edit ;
  draft action Activate;
  draft action Discard;
  draft action Resume;

  draft determine action Prepare ;
}

Once the OData is published through service binding, we can preview the application.

List Page

You can click on create to Create a new Instance.

Object page With Upload Option

On “Upload File” the File Open Dialog comes up to select the file from Presentation Server .

File Selection Dialog

Once the File is uploaded the Hyperlink can be used to access the file and based on annotation contentDispositionPreference the file would either open in a new window or downloaded when selected.

After File Upload

Once the Instance is saved we can see the new file encoded in RAWSTRING format along with its Mimetype and Name saved in the database.

Database table after Upload

In Conclusion, with the Support of OData streams, we can now handle LOBs directly using RAP framework, this really caters to a lot of missing features for which extensions were needed before. The above application is a very simple example of how this feature can be used.

Rating: 0 / 5 (0 votes)

The post Streams in RAP: Uploading PDF, Excel and Other Files in RAP Application appeared first on ERP Q&A.

]]>