Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
AbhishekSharma
Active Contributor
16,876
 

Hello,

In this beginner blog post we are going to see how we can use Large Objects (LOBs) in ABAP Restful Application Programming Model.

 

In this blog post we are going to see how to Upload File in ABAP Restful Application Programming Model.

Annotation used to to work with Large Objects is @Semantics.largeObject

 

Ref: https://help.sap.com/docs/btp/sap-abap-restful-application-programming-model/working-with-large-obje...




Previous Blog Posts


ABAP RAP – Instance Authorization


ABAP RAP – Global Authorization


ABAP RAP – #CHANGE_SET


ABAP RAP - #ISOLATED


 

Demo use case


In this demo application we are going cover below requirements:

  • Create Student management system where we can upload multiple documents for each student.


 

File Upload in any Business application is very common requirements, which was not available through ABAP RAP framework till the release of SAP BTP ABAP 2208.

 


Large Objects


 

As per our scenario we are going to create Student Record and will upload multiple documents for created Student.


Create persistent table for Student as below.

 
@EndUserText.label : 'Student Table Header'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zstudent_hdr_tab {

key client : abap.clnt not null;
key id : sysuuid_x16 not null;
firstname : abap.char(100);
lastname : abap.char(100);
age : abap.numc(4);
course : abap.char(50);
courseduration : abap.numc(4);
status : abap_boolean;
gender : abap.char(1);
dob : abap.dats;
lastchangedat : timestampl;
locallastchangedat : timestampl;
}

 

Create Persistent table for Attachments for Students

 
@EndUserText.label : 'Attachment Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zstudent_att_tab {

key client : abap.clnt not null;
key attach_id : char32 not null;
id : sysuuid_x16 not null;
comments : char30;
attachment : zattachment1;
mimetype : char128;
filename : char128;

}

 

We are seeing field with name attachment of type zattachment1. Data type of attachment is very Important and since we are going to save file or Binary data or raw data in this field the field type must be RAWSTRING with length 0. 

Length 0 is not mandatory but if length is not 0 then there will be restriction on the size of file that can be uploaded. 0 length means big files can be uploaded with no file size restriction.

 



Interface View for Student Header


 

Create Interface views for both Student and Attachments table.

 
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface View Entity for Student'
define root view entity zstudent_hdr_tab_I as select from zstudent_hdr_tab
composition[1..*] of zstudent_att_tab_i as _Attachments
{
@EndUserText.label: 'Student ID'
key zstudent_hdr_tab.id as Id,
@EndUserText.label: 'First Name'
zstudent_hdr_tab.firstname as Firstname,
@EndUserText.label: 'Last Name'
zstudent_hdr_tab.lastname as Lastname,
@EndUserText.label: 'Age'
zstudent_hdr_tab.age as Age,
@EndUserText.label: 'Course'
zstudent_hdr_tab.course as Course,
@EndUserText.label: 'Course Duration'
zstudent_hdr_tab.courseduration as Courseduration,
@EndUserText.label: 'Status'
zstudent_hdr_tab.status as Status,
@EndUserText.label: 'Gender'
zstudent_hdr_tab.gender as Gender,
@EndUserText.label: 'DOB'

zstudent_hdr_tab.dob as Dob,
zstudent_hdr_tab.lastchangedat as Lastchangedat,
zstudent_hdr_tab.locallastchangedat as Locallastchangedat,


_Attachments // Make association public
}

 

Interface View for Attachment Header


 

@semantics.LatgeObject is used to add file upload option on Student header Interface View.

contentDispositionpreference : This property value will decide If the file should be downloaded or should be opened in Browser's tab when user clicks on File name once Uploaded.

 

#INLINE : File will be opened in Browder tab

#ATTACHMENT : File will be downloaded to users local machine

 
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'View for Attachment'
define view entity zstudent_att_tab_i as select from zstudent_att_tab
association to parent zstudent_hdr_tab_I as _Student
on $projection.Id = _Student.Id {

key zstudent_att_tab.attach_id as AttachId,
zstudent_att_tab.id as Id,
@EndUserText.label: 'Comments'
zstudent_att_tab.comments as Comments,

@EndUserText.label: 'Attachments'
@Semantics.largeObject:{
mimeType: 'Mimetype',
fileName: 'Filename',
contentDispositionPreference: #INLINE
}
zstudent_att_tab.attachment as Attachment,
@EndUserText.label: 'File Type'
zstudent_att_tab.mimetype as Mimetype,
@EndUserText.label: 'File Name'
zstudent_att_tab.filename as Filename,

_Student.Lastchangedat as LastChangedat,
_Student // Make association public
}

 

Projection View for Student Header Interface View


Create projection view and add UI annotations for Fiori application.

 


 
@EndUserText.label: 'Projection view for Header table'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define root view entity zstudent_att_tab_p
provider contract transactional_query
as projection on zstudent_hdr_tab_I
{
@UI.facet: [{
id: 'StudentData',
purpose: #STANDARD,
label: 'Student Data',
type: #IDENTIFICATION_REFERENCE,
position: 10
},{
id: 'Upload',
purpose: #STANDARD,
label: 'Upload Attachments',
type: #LINEITEM_REFERENCE,
position: 20,
targetElement: '_Attachments'
}]

@UI: {
selectionField: [{ position: 10 }],
lineItem: [{ position: 10 }],
identification: [{ position: 10 }]
}

key Id,
@UI: {
lineItem: [{position: 20 }],
identification: [{position: 20 }]
}
Firstname,
@UI: {
lineItem: [{position: 30 }],
identification: [{position: 30 }]
}
Lastname,
@UI: {
lineItem: [{position: 40 }],
identification: [{position: 40 }]
}
Age,
@UI: {
lineItem: [{position: 50 }],
identification: [{position: 50 }]
}
Course,
@UI: {
lineItem: [{position: 60 }],
identification: [{position: 60 }]
}
Courseduration,
@UI: {
lineItem: [{position: 70 }],
identification: [{position: 70 }]
}
Status,
@UI: {
lineItem: [{position: 80 }],
identification: [{position: 80 }]
}
Gender,
@UI: {
lineItem: [{position: 90 }],
identification: [{position: 90 }]
}
Dob,
Lastchangedat,
Locallastchangedat,
/* Associations */
_Attachments : redirected to composition child zstudent_att_tabl_p
}

 

Projection View for Attachment Interface View


 


 


 


 
@EndUserText.label: 'Projection for Attachment'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity zstudent_att_tabl_p
as projection on zstudent_att_tab_i
{

@UI.facet: [{
id: 'StudentData',
purpose: #STANDARD,
label: 'Attachment Information',
type: #IDENTIFICATION_REFERENCE,
position: 10
}]

@UI: {
lineItem: [{ position: 10 }],
identification: [{ position: 10 }]
}

key AttachId,
@UI: {
lineItem: [{ position: 20 }],
identification: [{ position: 20 }]
}
Id,
@UI: {
lineItem: [{ position: 30 }],
identification: [{ position: 30 }]
}
Comments,
@UI: {
lineItem: [{ position: 40 }],
identification: [{ position: 40 }]
}
Attachment,
Mimetype,
Filename,
LastChangedat,
/* Associations */
_Student : redirected to parent zstudent_att_tab_p
}

 

Create behavior Definition for Student Header Interface View


 

Once Projection Views are ready, now we are going to create Behavior Definition. To add different actions to Object.

 

Right click on Student Header Interface View and create Behavior Definition. refer below pic.

 


 


 

In behavior Definition we are using Draft capability. Update behavior Definition for Student and Attachments as per below code.

 
managed implementation in class zbp_student_hdr_tab_i unique;
strict ( 1 ); with draft;
define behavior for zstudent_hdr_tab_I alias Student
persistent table zstudent_hdr_tab
draft table zstudent_h_d_tab
lock master
total etag Locallastchangedat
authorization master ( global )
etag master Lastchangedat
{
create;
update;
delete;
association _Attachments { create; with draft; }
field ( numbering : managed, readonly ) Id;
draft action Edit;
draft action Activate;
draft action Discard;
draft action Resume;
draft determine action Prepare;
mapping for zstudent_hdr_tab
{
Id = id;
Firstname = firstname;
Lastname = lastname;
Age = age;
Course = course;
Courseduration = courseduration;
Dob = dob;
Gender = gender;
Lastchangedat = lastchangedat;
Locallastchangedat = locallastchangedat;
Status = status;
}
}

define behavior for zstudent_att_tab_i alias Attachments
persistent table zstudent_att_tab
draft table zstudent_a_d_tab
lock dependent by _Student
authorization dependent by _Student
etag master LastChangedat
{
update;
delete;
field ( readonly ) Id;
association _Student { with draft; }
mapping for zstudent_att_tab{
AttachId = attach_id;
Attachment = attachment;
Comments = comments;
Filename = filename;
Id = id;
Mimetype = mimetype;
}
}

 

Save and Activate behavior Definition

 

Create Behavior Implementation of Behavior Definition


 


 

Behavior Implementation Class is ready. Since we are not performing any custom operation so no changes are needed at this point of time.

 


 

Create Behavior Definition for Student Header Projection View


Create Behavior Definition for Student Header Projection View as well. No changes are needed once created just Activate.

 


 

projection View behavior Definition will be created.

 


 
projection;
strict ( 1 );
use draft;

define behavior for zstudent_att_tab_p //alias <alias_name>
{
use create;
use update;
use delete;

use action Edit;
use action Activate;
use action Discard;
use action Resume;
use action Prepare;

use association _Attachments { create; with draft; }
}

define behavior for zstudent_att_tabl_p //alias <alias_name>
{
use update;
use delete;

use association _Student { with draft; }
}

 

Save and Activate behavior Definition

 

Create Service Definition to Expose both Projection Views


 

Select Attachment Projection View and create new Service Definition


 

 
@EndUserText.label: 'Service Defination'
define service ZSTUDENT_ATT_SD {
expose zstudent_att_tabl_p;
expose zstudent_att_tab_p;
}

 

Save and Activate behavior Definition

 

Create Service Bindings for created Service Definition


 

To create new Service Binding right click on Service Definition and select New Service Bindings

 


 

Must select binding Type as OData V4 - UI, since we want to have Create EDIT and Delete operations available along with Attachments Upload.

 


 

Add to Transport and click on Finish button.

Click on Activate Service Binding and once Activated we need to Publish new created Service Binding. Once Published then only Service URL will be available to be used to create Fiori Application.

 


 

Once created Service Bindings and Published it should look like below

 


 

Final application structure looks like below :



 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Run and Test Application for File Upload


 


 

Application Initial screen will look like below. with Action buttons to Create and Delete Records

 



 

Click on Create button to add new Student Record, below screen will be displayed. Update all required student Information and click on Create button on Upload Attachment Facet to upload Resume file.


Since Id field of Attachment is not an Auto generated field and Not null, in this case RAP Framework will display popup asking unique number for Attachment ID

 


 

Provide Comments for Attachment file and Use Upload Button to select file to Upload, once done click on Apply Button which will save file temporarily

 


 

Once done click on Save Button and File will be Uploaded and Saved for created Student Record

 


 

Upload another file. Multiple files are uploaded successfully



 

Notes:



  • Service Binding Type must be OData V4 - UI.

  • Attachment field type must be RAWSTRING.

  • Attachment field data type length should be 0 otherwise there will be restriction on file size to be uploaded, 0 means no restriction.


 

 

Thanks-

Abhishek

 
9 Comments
PrasanthPadmanabhan
Product and Topic Expert
Product and Topic Expert

Good use case Abhishek. Thanks for Sharing

issabella_martin1995
Participant
0 Kudos
Hi Abhishek ,

Can we use @Semantics.largeObejct in Custom Entities [In cases of Unmanaged query ] ?

There can be scenario where we are getting documents from a remote Odata call and we need to fetch the documents stored there.

I have tried , but we cannot expose a large object in main/root Custom Entity .. is there any way we can do that ?
mukeshjadhav08
Explorer
0 Kudos
Hi Abhishek,

Thank you for this blog.
It's working perfectly fine for me, except one thing that FileName is not getting saved and UI shows file name as "Open File", do you think it is because of UI5 version or something else?

Thanks,

Mukesh
former_member127881
Discoverer
0 Kudos

Hi Mukesh,

I have the same problem. Have you solved it?

Thanks,

Li Mingqi

former_member851399
Discoverer
Great blog, I've implemented your code tested it for many different types of file.  I had to use /iwfnd/v4_admin to publish the service group and ran into authorization issues but worked perfectly.  Before we had to use SEGW transaction OData Stream service.  Possibly we can use both technology for different functions.  Thanks.
Andynguyen
Discoverer
0 Kudos

Dear Abhishek,

Thanks for sharing,

Is this possible to select multiple files to upload at once? If so, how can I achieve this? Thanks 

eViloria
Discoverer
0 Kudos

Thanks for the contribution.
I have not been able to add in the facet of the root entity the imageURL, when relating the Attachment field, it does not add the image that has the Attachment , do you think it is because the type of ODATA is V2.

eViloria_0-1737526272615.png

As the first image (SAP example) I want it to be.

eViloria_1-1737526383191.png

But it appears as the second photo.

@AbhishekSharma 

SanketGode45
Explorer
0 Kudos

Hi @everyone ,

Do any one have implemented create header to item relation with unmanged scenario where 

The "create" operation cannot be enabled for an association ("project") that is "to parent" or for which "dependent by" is used.

SANKET20_0-1744277370159.png

SANKET20_1-1744277421013.png

Here I have Implemented composition to child. where I have used association to parent. but actual unmanged operation is not getting trigger due to an error The "create" operation cannot be enabled for an association ("project") that is "to parent" or for which "dependent by" is used.

 

 

Sourabh_Kumar27
Newcomer
0 Kudos

Hi All,

I have implemented the same approach for File Upload LOB
In my object page when am trying to upload an attachment it uploading file but without file name ,

Sourabh_Kumar27_0-1750418475429.png

But after click on apply its showing name in table , 
Can anyone suggest what changes needs to be done to show the file name while uploading and before clicking of apply button ?