ABAP to Full Stack: Making Sense of What’s Behind a Fiori App (OData, Class, Virtual Element)
Share

[[{“value”:”

Hello! I’m Andréa Molina. After more than 20 years in SAP, the new SAP world left me completely lost, so I decided to share my experience and learn together. I’m moving from classic ABAP to the SAP full stack, one real project at a time, drama included.

From overwhelmed to curious, my journey had (and still has) a lot of bumps. You can check my other posts here. I hope you find understanding and empathy here, and maybe a few laughs.

If you’re in the same boat, this series is for you. In this post: I will share my experience creating a List Report (a Fiori floorplan) built on a CDS view exposed as OData V4, with a virtual element calculated by an ABAP class. Plus a plot twist in Step 5.

A bit of background

On my journey I always try to use case studies that are real and will add value to the business. The library and ice cream examples just give me more anxiety and make no sense to me. So this time I’m turning an existing query/infoset (SQ01/SQ02) into a Fiori app, to understand how much effort and time it would take.

So far I have worked with the Basic template and one CDS KPI app, and I knew there were more template options to explore. This time I thought the List Report Page would work best (well, not really, but let’s move forward for now… surprise at Step 5 of this blog).

Before we move on, read this if you are asking “What on earth is List Report Page and Basic Template?”
When you create a new app from a template, you can choose among a lot of frameworks. Each framework provides a set of prebuilt files, structure and more.

deiamolina_0-1792675706790.png

You can read more about FloorPlans here: https://www.sap.com/design-system/fiori-design-web/v1-136/page-types/floorplans/when-to-use-which-floorplan

The project

Transform an existing Query/InfoSet (SQ01/SQ02) into a Fiori application. 

Does SAP Make This Easy?

In my research and studying I couldn’t find a tool that automatically converts queries into Fiori applications. If you know of a better approach, please share it in the comments. I’d genuinely love to learn. 

The Challenge

… because I have never done before this project

  • Create a CDS view that delivers the data exactly the way I want it to be displayed, with logic and not just selection from the database
  • Create an ABAP class that is called by the CDS
  • Understand how the ABAP class and the CDS work together
  • Create a KPI on top of the report list

The best way to learn: get your hands dirty! A simple learning exercise 

I am suggesting here a very simple example of CDS, class and app: create a List Report Page based on a CDS.

The result should show all the Sales Orders created in the last 30 days and flag the ones created today.

Step 0: Eclipse

The way to create backend objects for apps is using the ABAP Development Tools (ADT) in Eclipse. If you are new here, check this tutorial to set up your Eclipse ADT: https://developers.sap.com/tutorials/abap-install-adt/ 

Step 1: The CDS Views

To get familiar with frontend and backend (together, they make the full stack), here is what is what.

  • Backend: where the data comes from.
  • Frontend: the screen the user interacts with. This part of the development is the backend.

What is backend: Where the data comes from. Put in very simple words.  it’s the data that will populate the frontend. 

The CDS will select from I_SalesOrder, and we will use a virtual element (calculated by an ABAP class) to flag the orders created today. It will only return the last 30 days, so we don’t select hundreds of records. 🥴 

Why I_SalesOrder and not VBAK?

If you grew up in ECC like I did, you might be asking: why not use VBAK?

  • Tables move, CDS adapts. Moving from ECC to S/4HANA changed a lot of tables. Take VBUK, where we used to read the order status. Its fields now live in VBAK, so every program that selected from VBUK needs to change. But a program reading the status through I_SalesOrder will keep working, because SAP updated the view and left the interface alone. That’s the idea behind released CDS views: SAP can rearrange it, and your app doesn’t notice.
  • Clean core. Clean core is the promise of updating the system faster and more often than before, allowing companies to use the new technologies instead of waiting years for a hard and difficult system upgrade. To do that, you need to use standard objects. If you have already migrated to S/4, you know what I am talking about needing to adapt the system considering all changes. Using CDS views instead of tables is one step in the clean core approach. 
  • It already speaks Fiori. SAP does the hard work of the joins and associations, so you just use it the way you need, and it’s all ready for the day you want an Object Page.

Yes, I know. It’s not our language YET, we don’t know those CDS names yet, and it’s so easy to use a table we know. But remember when VBAK sounded just as weird as I_SalesOrder does now? It stuck because we used it every day. This will stick too, if we choose to start.

Now we have AI to help us speed up our knowledge and search for the right object to select from.  But I always use AI as a co-worker and never as the builder and be sure you add on the prompt to use best practices and use Standard objects whenever possible

So let’s go for it! Creating the CDS on Eclipse…

deiamolina_1-1792676073518.png

deiamolina_2-1792676097554.png

CDS Code 

@AccessControl.authorizationCheck: #NOT_REQUIRED //Authorization is not required
@EndUserText.label: ‘Demo for ABAP Class’ //Just a text
@Metadata.ignorePropagatedAnnotations: true //
define view entity ZC_DEMO
as select from I_SalesOrder
{
@UI.lineItem: [{ position: 10, importance: #HIGH }] //The field below will be the first (10) column on the report
@UI.selectionField: [{ position: 10 }] //The field below will be on the app as a search field
key SalesOrder,
@UI.lineItem: [{ position: 20 }]
SalesOrderType,
@UI.lineItem: [{ position: 30 }]
SalesOrganization,
@UI.lineItem: [{ position: 40 }]
@UI.selectionField: [{ position: 20 }]
CreationDate,
@UI.lineItem: [{ position: 50, label: ‘Created Today’ }]
@ObjectModel.virtualElement: true //The field below will use an virtual Element
@ObjectModel.virtualElementCalculatedBy: ‘ABAP:ZCL_VIRT_DEMO’ //This is the Class you use to calculate the field below
cast( ‘ ‘ as abap.char(1) ) as CreatedToday
}
where CreationDate >= dats_add_days( $session.system_date, -30, ‘NULL’ ) //Just select the last 30 days

UI annotations: how the backend tells the frontend what to draw

The Fiori app doesn’t know anything about our fields. The annotations in the CDS are instructions that travel with the OData service, and Fiori elements reads them to build the screen.

In plain English: the CDS doesn’t only deliver the data, it also sends instructions to the screen the user interacts with: “Hey, look, here is what you show in the table and here is what you show in the filters.” 

 In our code:

  • @UI.lineItem: this field becomes a column in the report.
  • @UI.selectionField: this field becomes a filter in the filter bar at the top.

The position number sets the order: 10 comes first, then 20, and so on.

Note: I prefer using a Metadata Extension (a separate file that keeps the annotations out of the CDS view), but I really want to keep this very simple here.

Step 2: Create the Virtual Class

Note: I know we could get this logic using a CASE in the CDS, but the idea here is to show how to use the class in a very simple example that everybody understand 😉

This part here is important, so let’s translate what this part of the code is saying: 

deiamolina_3-1792676242350.png

“Hey CDS, this field will use a virtual element. The value will be calculated by an ABAP class called ZCL_VIRT_DEMO. If nothing is returned, the value is blank. The field will contain a value of 1 char (ABAP CHAR1) and will be exposed as CreatedToday. Nice. See you in the class!” 

So now we need to create the virtual class. 

deiamolina_4-1792676278613.png

 

deiamolina_5-1792676278613.png

The code

CLASS zcl_virt_demo DEFINITION
PUBLIC “Can be used by other objects
FINAL “Cannot be inherited
CREATE PUBLIC.
PUBLIC SECTION.
“This makes the class a calculator for virtual elements
INTERFACES if_sadl_exit_calc_element_read.
ENDCLASS.
CLASS zcl_virt_demo IMPLEMENTATION.
“STEP 1 – Runs FIRST, before the database read.
“Which real fields do you need to calculate your virtual field?”
METHOD if_sadl_exit_calc_element_read~get_calculation_info.
“Only if the app really asked for CreatedToday (names come in UPPERCASE)
IF line_exists( it_requested_calc_elements[ table_line = ‘CREATEDTODAY’ ] ).
“Tell SADL to also read CreationDate from the database
APPEND ‘CREATIONDATE’ TO et_requested_orig_elements.
ENDIF.
ENDMETHOD.
“STEP 2 – Runs AFTER the database read, once per package of rows.
“Here we fill the virtual field.
METHOD if_sadl_exit_calc_element_read~calculate.
“Table typed with the CDS view, so we can access fields by name
DATA lt_orders TYPE STANDARD TABLE OF zc_demo WITH DEFAULT KEY.
“Copy the generic data into our typed table
lt_orders = CORRESPONDING #( it_original_data ).
“Read the date once, outside the loop (no need to ask on every row)
DATA(lv_today) = cl_abap_context_info=>get_system_date( ).
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<order>).
“Created today? Mark with ‘X’
IF <order>-creationdate = lv_today.
<order>-createdtoday = ‘X’.
ENDIF.
ENDLOOP.
“Give the result back to SADL (same rows, same order)
ct_calculated_data = CORRESPONDING #( lt_orders ).
ENDMETHOD.
ENDCLASS.

How to debug it

Go to SE24 and search for the class you created. 

deiamolina_6-1792676367387.png

Double-click the method you want to debug and create an EXTERNAL breakpoint. 

deiamolina_7-1792676367388.png

Important

You can preview the data in Eclipse, right? Yes, but there the class will not be called, and the virtual element comes back blank. Don’t do what I did: I thought my class wasn’t working and spent a long time trying to understand why! Let me save you the trouble: to see the class running, you need to create the service definition, the service binding and the app. 

Step 3: Service Definition and Service Binding

Service Definition – You tell the OData service (the object that selects the data) what you want to be displayed in the result. 

deiamolina_8-1792676464746.png

The Code

@EndUserText.label: ‘Service Definition for ZC_DEMO’
define service ZUI_DEMO {
expose ZC_DEMO;
}

Service Binding – You expose the service definition as an OData V4 UI service, so the app can consume your CDS data. 

deiamolina_9-1792676500187.png

deiamolina_10-1792676500188.png

Activate

When it does not activate

Depending on the architecture of your system, you might not be able to publish your service in Eclipse. If this is your case and you are using V4, you need to go to tcode /n/IWFND/V4_ADMIN. 

deiamolina_11-1792676542526.png

Search for your Service Binding, select it and publish it. 

deiamolina_12-1792676542527.png

Go back to Eclipse and you will see that the binding is now published.

deiamolina_13-1792676542527.png

Step 4: Creating a List Report Page

deiamolina_14-1792676608847.png

deiamolina_15-1792676608848.png

deiamolina_16-1792676608850.png

deiamolina_17-1792676608851.png

deiamolina_18-1792676608851.png

Just leave the project attributes as they are and finish the project.

You will get a message like the one below:

deiamolina_19-1792676608852.png

When it finishes, you will get this message:

  • Open Folder means you will only get this project in BAS.
  • Add Project to Workspace means it will be added to your other projects in BAS. I always use this option. 

deiamolina_20-1792676608853.png

Then you can preview the application by right clicking on webapp

deiamolina_21-1792676608853.png

deiamolina_22-1792676608854.png

The terminal will run and another tab will open with your app! Voilá!

deiamolina_23-1792676608854.png

Step 5 – Adding a UI5 element on top of the report

 Until here things went smoothly, but I want to add a Radial Micro Chart on top of the report. So my first instinct was to look for the controller and the view, but there was no MVC… WHAT??????? 

But first, what is MVC?

If you don’t know what MVC means and you are an ABAPer, please read this blog post:  Getting cozy with familiar ABAP terms on your new BTP neighborhood 

It was a surprise to me, and then I thought: “Wait… does every template have completely different code and a completely different way of developing?” Gosh! 😅 (Actually, I said a bad word, but let’s keep this blog civilized.)

But, as I mentioned in my previous blog Overwhelmed by SAP’s new everything? Read this before you give up! I moved from being overwhelmed to being curious, and this time I was curious about how I would add the logic in the backend and not in the frontend.

So I asked Claude and, after a long discussion and a lot of changes, we decided that the best option was to create a Basic app because it was more familiar to me (my first 2 apps were created using Basic Template; be aware that to get to those 2 apps I created like 10 hahahaha).

The main point was that it was very simple to achieve parts of this using the List Report Page, but I couldn’t make my UI5 element show up in the app using a custom UI5 extension (a controller file I added to the app), which probably says more about me than about the template. If you know the trick, please tell me. And with the Basic Template, I was trying to reinvent the wheel way too hard.

Then I was like: “There is NO WAY no one wanted to do this before and it is this hard!!”

Trust AI but learn your stuff

I started investigating it. I have taken lots and lots of SAP courses over the course of my career, and many were focused on UX, so I knew about the floorplans. Let’s be honest here: it’s so easy to think that AI knows more than you do! I think this is going to be the learning curve with this tool: understanding that your expertise matters more than you think.

So I learned that there is something called the Analytical List Page (ALP). The ALP is exactly the combination I was after: KPIs on top, report below. EXACTLY what I need. Claude never suggested it to me until I suggested it to Claude, and then it said that it was obvious that ALP was the best option 😅

What did I learn from this project? 

The nicest thing about being new at something is that once you overcome the first aversion to the new, you learn a lot very fast and mostly by making mistakes. With this project I tried a custom UI5 extension, two new floorplans, an ABAP class in a CDS, an analytical data definition and more.

Now I know when to use an Analytical List Page and when to use a List Report Page. List Report when the goal is to list and filter. ALP when you want KPIs and charts on top, working together with the list below. 

I tried to summarize it all here so you could learn from my experience. Let me know if it worked! 😉

——————

While this post might be basic to some, I added here everything that was getting me overwhelmed for years and all my questions related to those things. My goal with these posts is to demystify the new SAP development world together with you.

I’ll continue sharing simple posts based on real discoveries, real questions and real experiences, sharing my journey, my learnings and my bumps along the way so you don’t need to go through some of them yourself.

If you’re in the same boat, stay tuned. There will be many more posts about this journey.

If you’re further along than this, pretty please help us in the comments.

To be continued

I’m on holiday now, in Brazil to be more exact , so there’s no ALP update yet (yes, I’m still writing here, apparently I can’t help it 😅). But I will write about the Analytical List Page as soon as I’m back and get it sorted. And I promise to tell you honestly what worked and what didn’t. 

Thanks for reading!

 

“}]] 

  Read More Technology Blog Posts by Members articles 

#abap

By ali

Leave a Reply