Monday, 6 July 2020

Custom Entities – SAP Cloud Platform

Custom entities are data definitions, which does not have a select statement on data source but we define return fields and their types. In case of custom entities their data model is invoked manually at runtime. The logic is defined in a class, we could not only retrieve data using custom entities but also do some other useful and awesome stuff with these good little tools.

For example without invoking an entire behaviour definition we need to update certain field in one of our tables which is frequently being accessed but entire data retrieval is costly due to the number of columns. In some cases we might need to trigger some specific action but we just don’t want to pass all the data from the frontend, for example we need to automate the process of completing a purchase document and all the data is readily available on our tables so fetching those data from tables and passing it again to our system would take time as well as would have an huge impact on the system. Instead we could pass the purchase order number and the rest could be handled in the class for custom entity thus minimising the backend interaction.

Why Custom Entities?


Yes , we have many other options for parameterised access (Data definitions with parameters) or executing a certain set of actions by invoking a data service (Data definitions with AMDP Functions) but these could not be exposed as a service or could be consumed by the frontend as a service.

Creating Custom Entities:


Step 1: Navigate to your Project Package.

Step 2:  Navigate to Core Data Services -> Data Definitions

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 3: Right click -> New Data definition

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 4: Choose a name and description.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 5: Attach it to a Transport Request.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 6: Choose Define Custom Entity with Parameters, then choose Finish.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 7: It should look like this, let’s just ignore the errors for now.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Now the Data Definition part of the custom entity is done, now we have to create the class to be executed while invoking the data definition.

Step 8: Navigate to Source Code Library -> Classes

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 9: Right click -> New ABAP Class

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

Step 10: Choose a name and description (Same as step 4).

Step 11: Attach it to a Transport Request (Same as step 5).

Now we have both our halves Data Definition and Class , now we have to link both .In order to this we should add a line of code at top of our Data Definition :

@ObjectModel.query.implementedBy  : 'ABAP:Name of class to be invoked'

As of step 7, our Data Definition is showing errors since we didn’t assign any parameter names, return element names and their types.

In this example I am only using one parameter, as of the blog date Data Definitions only allows three parameters to be passed. In case if we want to pass more than three parameters, check the tips part at the end of this blog. I am only returning two elements in this program and literally I haven’t met any limitation for number of elements to be returned.  The Custom Entities could return many number of records which is also not limited, just like an ordinary Data Definition.

Code after above changes:

@ObjectModel.query.implementedBy  : 'ABAP:ZCL_CUSTOMENTITY'
define custom entity ZCustomEntity 
 with parameters param1 : abap.char(10) 
 {
  key id : abap.char(10); // Returning fields are mentioned between {} just like ordinary CDS 
  name : abap.char(100); // Returning field set must contain a key or key combination 
  
}

We have connected our Data Definition with our class but the class won’t work as of now, for the class to work and access the parameters passed from the definition our class must implement the standard interface IF_RAP_QUERY_PROVIDER.

Since we are implementing IF_RAP_QUERY_PROVIDER , we should try and catch two standard exceptions CX_A4C_RAP_QUERY_PROVIDER and CX_RFC_DEST_PROVIDER_ERROR.

We should also get our parameter value using io_request() and we should return our result using io_response.

Code after above changes:

class ZCL_CUSTOMENTITY definition
  public
  final
  create public .

  public section.
    interfaces  IF_RAP_QUERY_PROVIDER .
  protected section.
  private section.
endclass.

class ZCL_CUSTOMENTITY implementation.
  method IF_RAP_QUERY_PROVIDER~SELECT.
    data:IT_RESULT   type  table of ZCUSTOMENTITY. "Internal table to be returned , easier to handle return if internal table is as same type of our data definition
    data: LV_PARAM    type STRING."Local variable to fetch and save parameter value
    try.
        try.
            if IO_REQUEST->IS_DATA_REQUESTED( ). "Fetching incoming data
              IO_REQUEST->GET_PAGING( ).

              data(LT_FILTER_COND) = IO_REQUEST->GET_PARAMETERS( ). "Setting the filter condition, fetching parameter names from data definition

              LV_PARAM = value #( LT_FILTER_COND[ PARAMETER_NAME   = 'param1' ]-VALUE optional ). "Fetching the parameter value
              "Using the parameter we could do whatever we want , like selecting from a table , doing certain calculations etc
              select * from ZEMPLOYEE where ID = LV_PARAM into IT_RESULT.
                IO_RESPONSE->SET_TOTAL_NUMBER_OF_RECORDS( LINES( IT_RESULT  ) ). "setting the total number of records which will be sent
                IO_RESPONSE->SET_DATA( IT_RESULT  ). "returning the data as internal table
              endif.
            catch CX_A4C_RAP_QUERY_PROVIDER into data(LX_EXC). "CX_A4C_RAP_QUERY_PROVIDER is now deprecated so use CX_RAP_QUERY_PROVIDER

          endtry.
        catch CX_RFC_DEST_PROVIDER_ERROR into data(LX_DEST).
      endtry.
    endmethod.

endclass

In order to use the custom entity we should expose the custom entity in a service binding just like our other data definitions.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Certification, SAP ABAP Exam Prep

After exposing and activating the custom entity data definition in service definition, it will be available in the service binding. Details about exposing, consumption and debugging will be in next blogs.

Conclusion: Custom Entities are very handy tools which helps in achieving many complex tasks easily, we could invoke the custom entity whenever we want. As I mentioned it could be used for executing a simple task like querying a table, updating a table or even triggering a complex action sequence.

Tip: In our example, we have only one parameter param1, but we need to pass four parameters. As of the blog date, we could only pass maximum of three parameters, so we could add param2, param3 to our parameter list but still we need to pass one more parameter. In order to achieve this we will concatenate our parameters separated by a flag for example ZZZ.

Ex: we need to pass four document number as a single parameter, we will be concatenating document numbers like 1001ZZZ1002ZZZ1003ZZZ1004           and will be passed to custom entity. Remember to increase the length of param1 enough to accommodate the changes.

At our class we will split the value of param1 like:

LV_PARAM1 = value #( LT_FILTER_COND[ PARAMETER_NAME   = 'PARAM1' ]-VALUE optional ). “Fetching the value of parameter
split LV_PARAM1 at 'ZZZ' into table IT_PARAM1.

No comments:

Post a Comment