Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
KazuhikoTakata
Participant

Update on 2024-04-04

Last month SAP CAP team is officially released new feature of attachments file. This @cap-js/attachments plugin provides out-of-box attachment files support with SAP Object Store service. Please check this too.

 

Overview

In this article, I will introduce a sample program for SAP BTP that manages both text and file information. This guide should prove useful for those new to SAP BTP, like myself.

Screenshot of sample programScreenshot of sample program

 

Sample code is hosted on a GitHub repository, and you are free to copy and experiment with it.

Note: Currently SDM is available only in Free Tier environment, not in trial environment (Documentation).

 

Introduction

Over the course of a year developing with SAP BTP, I utilized numerous low-code tools to compensate for my limited programming skills, particularly in web application development. However, not all aspects were covered by these low-code tools.

My first challenge was implementing a simple form to display both text and files. At that time, I struggled with implementing JavaScript code for both the frontend and backend.

After some time, I had the opportunity to implement a similar use case. By then, I had gained some understanding of JavaScript code. I made an effort to analyze the following insightful articles and applied the core principles from their experiences to my project (I would like to express my gratitude to the authors of these articles).

I made several improvements:

  • I stored file content in the Document Management Service (SDM) instead of the HANA Cloud database to reduce database volume.
  • I utilized OData Service V4 and enabled drafts to make use of the Fiori Elements User Interface.
  • I aimed to minimize coding to ensure that those following my project could understand it smoothly.

Moving forward, I will share the key aspects of my project.

 

Key aspects

CAP Integration with SDM

Firstly, I aimed to reduce the amount of backend service code in the SDM integration part. Fortunately, we already have a solution for this: the sap-cap-sdm-plugin. This NPM package translates between the SDM API (CMIS) and the OData service. As a result, I simply requested an OData entity with an SDM-specific annotation. This virtual entity references the SDM repository and consumes the SDM file as if it were text in the HANA Cloud database. 

One notable feature of the "sap-cap-sdm-plugin" is its ability to automatically categorize files by SDM folder. It can even create a new folder for each line of the parent entity automatically.

SAP Fiori tools 

Secondly, for user interface part, SAP Fiori tools VSCode extension supports the implementation of Fiori Elements. With the GUI tool, we can configure the List Report screen and the subsequent Object Page screen. At the same time, annotation CDS file is updated. I appreciate being able to exclude source code from basic UI functions. 

Fiori Elements Flexible Programming Model to implement Upload Set

The final part involves extending the Object Page screen using the Flexible Programming Model. The creation of an extension (a custom section in my case) is handled by the SAP Fiori tool as before, resulting in two files: an XML file for the extension view, and TypeScript code for the extension controller.

Upload Set control is specifically designed for file upload and download, so most standard functions are provided as default configurations in XML file. For instance, uploaded files are displayed with a URL configuration that points to the SDM entity.

My coding effort was primarily focused on implementing two points.

  1. File upload (onAfterItemAdded): OData service does not provide single API request to upload file that Upload Set expects, but two consecutive API requests. I implemented first request to create file container in SDM, and second request to push file content to that container.
  2. File download (onOpenPressed): the URL path to access to the SDM content varies between local (test) environment and Cloud Foundry environment. To deal with both scenarios, I implemented to get the service URL dynamically.

 

 

 

 

 

 

 

 

 

 

import ExtensionAPI from "sap/fe/core/ExtensionAPI";
import UploadSet from "sap/m/upload/UploadSet";
import UploadSetItem from "sap/m/upload/UploadSetItem";
import ODataModel from "sap/ui/model/odata/v4/ODataModel";
import Item from "sap/ui/core/Item";
import { UploadSet$AfterItemAddedEvent } from "sap/m/upload/UploadSet";
import { UploadSetItem$OpenPressedEvent } from "sap/m/upload/UploadSetItem";

export async function onAfterItemAdded(this: ExtensionAPI, event: UploadSet$AfterItemAddedEvent) {
    const model = this.getModel() as ODataModel;
    const item = event.getParameters().item as UploadSetItem;
    const uploadSet = this.byId("UploadSet") as UploadSet;
    const serviceUrl = model.getServiceUrl().replace(/\/$/, ""); // remove last slash if exist

    const path = this.getRouting().getView().getBindingContext()?.getPath(); 
    const binding = model.bindList(`${path}/attachments`);
    const attachment = binding.create({name: item.getFileName()});
    await attachment.created();
    
    item.setUploadUrl(`${serviceUrl}${path}/attachments('${attachment.getObject().ID}')/content`);
    item.addHeaderField(new Item({key: "X-CSRF-Token", text: model.getHttpHeaders()["X-CSRF-Token"]}));    
    uploadSet.uploadItem(item);
}

export function onUploadCompleted(this: ExtensionAPI) {
    const model = this.getModel() as ODataModel;
    model.refresh();
}

export function onOpenPressed(this: ExtensionAPI, event: UploadSetItem$OpenPressedEvent) {
    event.preventDefault();
    const model = this.getModel() as ODataModel;
    const serviceUrl = model.getServiceUrl();    
    const item = event.getParameters().item as UploadSetItem;
    const url = item.getUrl();
    item.setUrl(url.replace("serviceUrl/", serviceUrl));
    item.download(false);
}

 

 

 

 

 

 

 

 

 

 

Setup sample application

Prerequisites 

  • Login SAP BTP subaccount as subaccount administrator role
  • Add Cloud Foundry space developer role in this subaccount
  • Create SAP HANA Cloud service instance in this subaccount: see tutorial
  • Subscribe SAP Build Work Zone, standard edition in this subaccount
  • Create SAP Document Management service (SDM) Integration Option with repository option (not limited to above subaccount): see introduction

Create SDM repository

You can create SDM repository via SDM Integration Option API or SDM Application Option UI. I used latter easier one. When creating repository, you will take care not to activate Versioninig, that is not yet compatible with "sap-cap-sdm-plugin". After saving, note repository ID.

Option to create SDM repositoryOption to create SDM repository

 

Create SDM destination

You will create destination to access to SDM via Integration Option API. Input columns are:

  • Name: SDM (to match with configuration in sample program)
  • URL: endpoints.ecmservice.url in the service key of SDM Integration Option (no need to set path)
  • Proxy Type: Internet
  • Authentication: OAuth2ClientCredentials
  • Client ID: uaa.clientid in the service key of SDM Integration Option
  • Client Secret: uaa.clientsecret
  • Token Service URL: uaa.url + "/oauth/token"

Clone sample code and configure it

In your development environment (Business Application Studio or local VSCode in my case), clone sample code repository.

 

 

 

 

 

 

 

 

 

 

git clone https://github.com/kaztakata/sap-sample-fiori-elements-uploadset.git

 

 

 

 

 

 

 

 

 

 

In the cloned root directory, find ".cdsrc.json" file to change to your SDM repository ID.

 

 

 

 

 

 

 

 

 

 

{
  "requires": {
    "sap-cap-sdm-plugin": {
      "settings": {
        "destination": "SDM",
        "repositoryId": "your repository ID"
      }
    }
  }
}

 

 

 

 

 

 

 

 

 

 

Deploy to Cloud Foundry

In the cloned root directory, install NPM packages by:

 

 

 

 

 

 

 

 

 

 

npm i

 

 

 

 

 

 

 

 

 

 

then build multi-target application by:

 

 

 

 

 

 

 

 

 

 

mbt build

 

 

 

 

 

 

 

 

 

 

finally login to your Cloud Foundry and deploy sample program by:

 

 

 

 

 

 

 

 

 

 

cf deploy mta_archives/sap-sample-fiori-elements-uploadset_1.0.0.mtar

 

 

 

 

 

 

 

 

 

 

Test sample program

You can find deployed application in HTML5 Applications of deployed subaccount. You can directly open application or you can setup Work Zone to open it from Work Zone site.

In the application, you can create new Template Request with title, description and comment. Finally, you can upload any kind of files from your local machine. Uploaded files are displayed immediately then you can download it. 

Upload and donwload fileUpload and donwload file

 

After uploading file, you can check SDM repository and find folder name "TemplateRequests:{your request ID}" using SDM Application Option UI. In this folder your uploaded files are stored as expected.

SDM folderSDM folder

 

Conclusion

That's all for my sample program. I intended to minimize coding effort, hence not all events are implemented yet. If you have any feedback, please post reply and discuss with me.

I think I will write next blog about how I developed this program, step by step (Instruction of implement-test-deploy flow for SAPUI5 plus CAP integrated with another services). Keep in touch. 

1 Comment
Labels in this area