Develop Advanced Extensions with SAP Cloud SDK

Exercise: Building a CRUD extension using TypeScript

Objectives
After completing this lesson, you will be able to:

After completing this lesson, you will be able to:

  • Using the TypeScript language and the Nest framework, build an extension application executing CRUD operations on data in SAP S/4HANA Cloud

Building a CRUD Extension Application using TypeScript

Description

Create a simple version of the Address Manager application using TypeScript and the Nest framework. Run and debug it locally, connected to the SAP API Business Hub sandbox and to a local replica of the SAP S/4HANA Cloud system. Deploy the application to Cloud Foundry, run and debug it remotely. Create a Destination service and use it to connect the application to the back-end.

Prerequisites

For the complete execution of the current exercise, you must first execute the following exercises:

  • Create your Free Trial Account in SAP BTP
  • Activating the APIs in SAP S/4HANA Cloud: this exercise activates the required API in the S/4HANA Cloud tenant.

For the full execution of this exercise, you need to have the following software installed on your laptop:

SoftwareType
Node.jsapplication
Cloud Foundry CLIapplication
Visual Studio Codeapplication
Cloudfoundry Manifest YML SupportVisual Studio Code Extension
@sap-cloud-sdk/cliapplication

Some steps of this exercise depend on the https://api.sap.com website. As a consequence, they may not run properly if the website is not running 100% correctly. In this case, proceed with the exercise to reach the part that runs against the local SAP S/4HANA Cloud instance. That part will always run properly.

Information for execution

The exercise comes with an archive file:

ts-adman-solution.zip[download] contains the npm project in its final status after the correct execution of the exercise. This project can be used to clarify the correct solution or to copy and paste parts of the source code.

In the case you wish to run the solution application directly without going through the exercise steps, then complete the following actions (this is not a prerequisite to exercise execution):

  1. Extract the archive to a folder in your local system.
  2. Open the Windows Powershell and change directory to the project root folder.
  3. Execute the following sequence of commands (replace ">>>YOUR API KEY<<<" with your own API Key, for example, "FDqbnElM7mgmgqbIKBFHRpS1dvpt6sHD". To know your API Key, open https://api.sap.com/api/API_BUSINESS_PARTNER, then log on, and choose Show API Key).
    Code snippet
    $env:S4_APIKEY=">>>YOUR API KEY<<<"
    $env:S4_URL="https://sandbox.api.sap.com/s4hanacloud"
    npm install
    npm run build
    npm run start
    Copy code
  4. Wait till the following message appears: Nest application successfully started.
  5. Open the application at: http://localhost:3002.

To configure the application, the following environment variables can be set, such variables need to be properly set for the application to interact with the back-end service:

VariableContent
S4_DESTINATIONThe name of the destination defined within the Destination service of Cloud Foundry. Use it when running in Cloud Foundry, bound to a Destination and an Authorization services.
S4_URLThe URL of the back-end S/4HANA system. Use it when running locally.
S4_USERNAMEThe user name to access the back-end S/4HANA system. Use it when running locally.
S4_PASSWORDThe user name to access the back-end S/4HANA system. Use it when running locally.
S4_APIKEYYour API Key identifier, required to access the SAP API Business Hub. You can get your apikey at: https://api.sap.com.

Two authentication methods are possible. Based on the method, you will provide the corresponding environment variables:

  • Basic user and password authentication: used by the S/4HANA Cloud system.
  • NoAuthentication plus API key: used by the SAP API Business Hub sandbox system.

Task 1: Creating the Nest Development Project in Visual Studio Code

Steps

  1. In a local folder (folder D:\workspace if you are in the SAP Training System), use the SAP Cloud SDK CLI to generate a new extension application named: ts-adman.

    1. Open the Windows PowerShell, and execute the following commands:

      Code snippet
      cd D:\workspace
      sap-cloud-sdk init ts-adman
      Copy code
      Provide the following answers to the questions you are asked during the creation process:
      QuestionAnswer
      Should a new `nest.js` project be initialized in the target directory? (y|n)y
      Enter project name (for use in manifest.yml) [ts-adman]just press Enter
      Do you want to provide anonymous usage analytics to help us improve the SDK? (y|n)n
      The initial application is created. The process will last several minutes as all of the dependent node packages are downloaded from the internet. The final result is a Hello World application based on TypeScript and the Nest framework.

  2. Build and start the application from the command line. Open it in the browser, then stop the application.

    1. In the PowerShell, run the following commands:

      Code snippet
      cd ts-adman
      npm install
      npm run build
      npm start
      Copy code

      Wait till the following message appears: Nest application successfully started.

    2. Open the Web browser (for example, Google Chrome) at the following URL: http://localhost:3000

      The browser returns Hello World!.

    3. Back to the PowerShell, choose Ctrl+C, then choose Y to terminate the batch job.

  3. Open the application with Visual Studio Code.

    1. In the PowerShell, run the following command:

      Code snippet
      code .
      Copy code

      Visual Studio Code is opened, displaying the project folder content.

  4. Review the main project files.

    1. Review the following files:

      • The package.json file: containing project dependencies on external node packages.
      • All the files in the src folder: containing the TypeScript application, based on the Nest framework.
  5. In Visual Studio Code, build the application, then run it with debug and watch options.

    1. In Visual Studio Code, in the Explorer window, choose NPM SCRIPTSpackage.jsonbuildRun. The content of the dist folder is re-created. Once the build is executed, close the corresponding terminal window.

    2. Choose RunAdd Configuration ...Node.js. The launch.json file is opened.

    3. In the launch.json file, replace the existing configuration with the following one (that is, replace the whole content in the square brackets with the following):

      Code snippet
      {
                  "name": "Launch Application",
                  "type": "node-terminal",
                  "request": "launch",
                  "command": "npm run start:debug",
                  "cwd": "${workspaceFolder}"
              }
      Copy code
      As an alternative, you can copy the full ts_adman_01_launch_json.txt file [download], and replace the full content of the launch.json file.

    4. Choose F5 ( RunStart Debugging). Wait till the application starts and the following message appears in the terminal: Nest application successfully started.

  6. Open the src/app.controller.ts file and set a breakpoint at line 10. The open the application and verify that the execution stops at the breakpoint.

    1. In the VS Code Explorer tab, open the src/app.controller.ts file and click on the border of the editor window, on the left side of the line number 10. A red dot appears.

    2. Open the Web browser (for example, Google Chrome) at the following URL: http://localhost:3000

      The program execution stops at the breakpoint in Visual Studio Code.

    3. In Visual Studio Code, choose Continue (F5). The program execution continues and Hello World! appears in the browser.

    4. Click on the red dot beside line 10 and remove the breakpoint.

  7. Verify that the watch mode works properly. Open the src/app.service.ts file and change Hello World! to Hello SAP!. The change will be identified and the application re-runs automatically.

    1. Open the src/app.service.ts file.

    2. Replace Hello World! with Hello SAP!.

    3. Save (Ctrl+S). Observe in the terminal that the application is automatically re-started.

    4. Open the Web browser at the following URL: http://localhost:3000

      The browser returns Hello SAP!.

      Note
      During application development, the watch automatic mechanism can fail and the generated JavaScript code is not in sync anymore with the source TypeScript code. If you realize this is happening, stop the application, then build and run it again as per the previous exercise steps.

    5. Choose Stop to stop execution and close the terminal window.

  8. Deploy the application to Cloud Foundry.

    1. If required, in the Windows PowerShell, execute the following command:

      Code snippet
      cf login
      
      Copy code
      Enter your SAP BTP API endpoint, e-mail, and password.

    2. In Visual Studio Code, in the project root folder, delete the deployment sub-folder if required.

    3. In Visual Studio Code, in the Explorer window, choose NPM SCRIPTSpackage.jsondeployRun. The application is built (dist folder is re-created), then it is packaged (deployment folder is created), then it is deployed to the Cloud Foundry environment.

      At the end of the deployment process, you will get a text such as the following:

      Code snippet
           state     since                  cpu     memory         disk           details
      #0   running   2020-04-24T17:25:03Z   66.4%   167.5M of 1G   152.4M of 1G
      Copy code

  9. In the SAP BTP, navigate to the running application and open it.

    1. In Google Chrome, open the URL: https://account.hanatrial.ondemand.com. If required, enter your e-mail and password.

    2. In the SAP BTP Cockpit, choose Enter Your Trial account. Navigate to your trial Subaccount. Navigate to the dev space.

    3. Choose the ts-adman application name.

    4. Choose the Application Route. The application opens and Hello SAP! is returned in the browser page.

  10. In Visual Studio Code, create a debug configuration to attach the remote Nest application in Cloud Foundry.

    1. In Visual Studio Code, choose RunOpen Configurations. The launch.json file is opened.

    2. In the launch.json file, add the following debug configuration (for simplicity, you can copy the entire contents of the ts_adman_02_launch_json.txt file [download] ):

      Code snippet
      {
                  "name": "Attach Application",
                  "type": "node",
                  "request": "attach",
                  "port": 9229,
                  "localRoot": "${workspaceFolder}",
                  "remoteRoot": "/home/vcap/app"
              }
      Copy code
  11. Optional: Debug the application in Cloud Foundry using Visual Studio Code: Set a breakpoint and make an execution stop at line 10 of the src/app.controller.ts file.

    Note
    This step cannot be performed by multiple users simultaneously on the same system.
    1. In Visual Studio Code, open the manifest.yml file and observe the command to run the application in Cloud Foundry:

      Code snippet
      command: npm run start:prod
      Copy code
    2. Open the package.json file and search for the following line:

      Code snippet
      "start:prod": "node dist/main",
      Copy code
      To enable the application for debugging, add a --inspect option in the command, so that it becomes the following:
      Code snippet
      "start:prod": "node --inspect dist/main",
      Copy code

    3. In case it exists, in the project root folder, delete the deployment sub-folder.

    4. Deploy the previous change. In Visual Studio Code, in the Explorer window, choose NPM SCRIPTSpackage.jsondeployRun.

    5. In the PowerShell, ensure that the current directory is the project root folder: D:\workspace\ts-adman.

    6. To enable the application for debug, execute the following commands (you can find them in the ts_adman_enable_cf_debug.txt file [download] ):

      Code snippet
      cf enable-ssh ts-adman
      cf restage ts-adman
      cf ssh -N -T -L 9229:localhost:9229 ts-adman
      Copy code
    7. In Visual Studio Code, in the Run window, run the Attach Application configuration. The debugger attaches to the remote application.

    8. Open the src/app.controller.ts file and set a breakpoint (red dot aside the line number) at line 10:

      Code snippet
      return this.appService.getHello();
      Copy code
    9. Switch back to the application tab (containing Hello SAP!) and refresh the browser window.

      The program execution stops at the breakpoint. Switch the tab back to Visual Studio Code.

    10. In Visual Studio Code, choose Continue (F5). The execution is resumed.

    11. In Visual Studio Code, disconnect the debugger.

    12. In the PowerShell, choose Ctrl + C and terminate the cf ssh command.

Task 2: Creating the Nest Development Project in SAP Business Application Studio

Steps

  1. Open the SAP Business Application Studio, open the training development space.

    1. In your Web browser (for example, Google Chrome), open https://account.hanatrial.ondemand.com. If requested, enter your user and password.

    2. Choose SAP Business Application Studio.

    3. Enter the training development space.

  2. Open a terminal window and verify if the SAP Cloud SDK CLI is already installed (in the global NPM packages). If it is missing, install it.

    1. Choose FileOpen Workspace... (Ctrl+Alt+W), choose the projects folder and choose Open.

    2. Choose TerminalNew Terminal. A terminal window appears in the lower part of the screen.

    3. In the terminal, execute the following command:

      Code snippet
      npm list -g --depth=0
      Copy code
      A list of NPM global packages displays with their version.

    4. If the list does not contain package: @sap-cloud-sdk/cli, execute the following command:

      Code snippet
      npm install -g @sap-cloud-sdk/cli
      Copy code
    5. List the packages again; the list now contains the new package.

  3. In your local projects folder, use the SAP Cloud SDK CLI to generate a new extension application named ts-adman.

    1. In the terminal, execute the following command:

      Code snippet
      sap-cloud-sdk init ts-adman
      Copy code
      Provide the following answers to the questions you are asked during the creation process:
      QuestionAnswer
      Should a new `nest.js` project be initialized in the target directory? (y|n)y
      Enter project name (for use in manifest.yml) [ts-adman]just press Enter
      Do you want to provide anonymous usage analytics to help us improve the SDK? (y|n)n
      The initial application is created. The process will last several minutes as all the dependent node packages are downloaded from the internet. The final result is a Hello World application based on TypeScript and the Nest framework.

  4. Open the projects/ts-adman folder as a workspace.

    1. Choose FileOpen Workspace... (Ctrl+Alt+W), choose the projects/ts-adman folder and choose Open.

  5. Review the main project files.

    1. Review the following files:

      • The package.json file: containing project dependencies on external node packages.
      • All the files in the src folder: containing the TypeScript application, based on the Nest framework.
  6. By default, the application uses port 3000, this won't work in SAP Business Application Studio. Change the application port to 3002.

    1. In the src/main.ts file, replace the 3000 with 3002.

  7. Build and start the application from the command line. Open it in the browser, then stop the application.

    1. Choose TerminalNew Terminal. A terminal window appears in the lower part of the screen.

    2. In the terminal, run the following commands:

      Code snippet
      npm install
      npm run build
      npm start
      Copy code

      Wait till a pop-up window appears: A service is listening to port 3002. Choose Expose and Open then press enter. A new tab is opened in the browser, showing Hello World!.

    3. Back to the terminal, choose Ctrl+C, to terminate the batch job.

  8. In SAP Business Application Studio, build the application, then run it in debug mode.

    1. In the Explorer window, choose NPM SCRIPTSpackage.jsonbuildRun. The content of the dist folder is re-created. Once the build is executed, close the corresponding terminal window.

    2. Choose RunAdd Configuration ...Node.js. The launch.json file is opened.

    3. In the launch.json file, replace the existing configuration with the following code block (replace the entire content in the square brackets with the following):

      Code snippet
      {
            "name": "Launch Application",
            "type": "pwa-node",
            "request": "launch",
            "program": "${workspaceFolder}/dist/main",
            "skipFiles": [
                "<node_internals>/**"
            ]
          }
      Copy code
      As an alternative, you can copy the full ts_adman_01b_launch_json.txt file [download], and replace the full content of the launch.json file.

    4. Choose F5 (RunStart Debugging). Wait till a pop-up window appears: A service is listening to port 3002. Choose Open in New Tab. A new tab is opened in the browser, showing Hello World!.

  9. Open the src/app.controller.ts file and set a breakpoint at line 10. Refresh the application page and verify that the execution stops at the breakpoint.

    1. In the Explorertab, open the src/app.controller.ts file and click on the border of the editor window, on the left side of the line number 10. A red dot appears.

    2. Switch back to the application tab (containing Hello World!) and refresh the browser window.

      The program execution stops at the breakpoint. Switch the tab back to SAP Business Application Studio.

    3. In SAP Business Application Studio, choose Continue (F5). The program execution continues and Hello World! appears in the application tab.

    4. Return to the src/app.controller.ts file, click on the red dot aside line 10 and remove the breakpoint.

    5. Choose Stop to stop the application execution.

  10. Deploy the application to Cloud Foundry.

    1. Choose TerminalNew Terminal. A terminal window appears in the lower part of the screen.

    2. Make sure the Cloud Foundry CLI is logged in and targeting your dev space. In the Terminal, execute the following command:

      Code snippet
      cf login
      
      Copy code
      If required, enter your SAP BTP API endpoint, e-mail, and password.

    3. In the project root folder, delete the deployment sub-folder if required.

    4. In the Explorer window, choose NPM SCRIPTSpackage.jsondeployRun. The application is built (dist folder is re-created), then it is packaged (deployment folder is created), then it is deployed to the Cloud Foundry environment.

      At the end of the deployment process, you will get a text like the following:

      Code snippet
           state     since                  cpu     memory         disk           details
      #0   running   2020-04-24T17:25:03Z   66.4%   167.5M of 1G   152.4M of 1G
      Copy code

  11. Look for the running application in the SAP BTP Cockpit and open it.

    1. In Google Chrome, open the URL: https://account.hanatrial.ondemand.com. If required, enter your e-mail and password.

    2. In the SAP BTP Cockpit, choose Enter Your Trial account. Navigate to your trial Subaccount. Navigate to the dev space.

    3. Choose the ts-adman application name.

    4. Choose the Application Route. The application opens and Hello World! is returned in the browser page.

  12. In SAP Business Application Studio, create a debug configuration to attach the remote Nest application in Cloud Foundry.

    1. Choose RunOpen Configurations. The launch.json file is opened.

    2. In the launch.json file, add the following debug configuration (you can copy the entire content of the ts_adman_02b_launch_json.txt file [download] ):

      Code snippet
      {
                  "name": "Attach Application",
                  "type": "pwa-node",
                  "request": "attach",
                  "port": 9229,
                  "localRoot": "${workspaceFolder}",
                  "remoteRoot": "/home/vcap/app",
                  "skipFiles": [
                      "<node_internals>/**"
                  ]
              }
      Copy code
  13. Debug the remote application running in Cloud Foundry using the debugger in SAP Business Application Studio: set a breakpoint and make execution stop at line 10 of the src/app.controller.ts file.

    1. Open the manifest.yml file and observe the command to run the application in Cloud Foundry:

      Code snippet
      command: npm run start:prod
      Copy code
    2. Open the package.json file and search for the following line:

      Code snippet
      "start:prod": "node dist/main",
      Copy code
      To enable the application for debugging, add a --inspect option in the command, so that it becomes the following:
      Code snippet
      "start:prod": "node --inspect dist/main",
      Copy code

    3. Deploy the previous change: in the Explorer window, choose NPM SCRIPTSpackage.jsondeployRun.

    4. Choose TerminalNew Terminal. A terminal window appears in the lower part of the screen.

    5. To enable the application for debug, execute the following commands (you can find them in the ts_adman_enable_cf_debug.txt file [download] ):

      Code snippet
      cf enable-ssh ts-adman
      cf restage ts-adman
      cf ssh -N -T -L 9229:localhost:9229 ts-adman
      Copy code
      Ignore the proposal to "Expose and Open" the service listening to port 9229.

    6. In SAP Business Application Studio, in the Debug window, run the Attach Application configuration. The debugger attaches to the remote application.

    7. In the Run window, run the new configuration. The debugger attaches to the remote application.

    8. Open the src/app.controller.ts file and set a breakpoint (red dot aside the line number) at line 10:

      Code snippet
      return this.appService.getHello();
      Copy code
    9. Switch back to the application tab (containing Hello World!) and refresh the browser window.

      The program execution stops at the breakpoint. Switch the tab back to SAP Business Application Studio.

    10. In the SAP Business Application Studio, choose Continue (F5). The program execution continues and Hello World! appears in the application tab.

    11. In SAP Business Application Studio, stop the debugger.

    12. In the Terminal, choose Ctrl + C and terminate the cf ssh command.

Task 3: Creating the Address Manager Application

Steps

  1. Back to the application project in Visual Studio Code, add the following packages in the dependencies then install them so they are available for the application programs.

    PackageVersion
    @sap/cloud-sdk-vdm-business-partner-service^1.28.2
    1. Open the package.json file.

    2. In the file, look for the following text:

      Code snippet
          "@sap-cloud-sdk/core": "^1.54.0",
      Copy code
      After this text, insert the new dependency line:
      Code snippet
      "@sap/cloud-sdk-vdm-business-partner-service": "^1.28.2",
      Copy code
      The new text will look like the following:
      Code snippet
          "@sap-cloud-sdk/core": "^1.54.0",
          "@sap/cloud-sdk-vdm-business-partner-service": "^1.28.2",
      
      Copy code

    3. Choose TerminalNew Terminal. In the Terminal, run the following command:

      Code snippet
      npm install
      Copy code
      The new node package is downloaded to the node_modules folder. Once the action is complete, close the terminal window.

  2. On top of the initial application, create an Address Manager back-end application. The Address Manager is able to maintain the address information of SAP S/4HANA Cloud business partners. The application code for the back-end is provided in the ts_adman_backend.zip file [download] .

    1. Right-click on the ts-adman/src folder, choose Reveal in File Explorer, extract the content of the ts_adman_backend.zip archive [download] to the src folder.

    2. In Visual Studio Code, verify that the new src/adman folder is visible. The folder contains the following TypeScript source files:

      Content of backend-connector.ts

      Code snippet
      import { Destination, DestinationNameAndJwt } 
          from '@sap-cloud-sdk/core';
      
      export class BackendConnector {
          
          private static destination: Destination | DestinationNameAndJwt;
          private static apikey: string;
      
          public static getDestination()
              : Destination | DestinationNameAndJwt {
      
              if (this.destination == null) {
                  // Get the environment variables
                  const destinationName: string = process.env.S4_DESTINATION;
                  const url: string = process.env.S4_URL;
                  const username: string = process.env.S4_USERNAME;
                  const password: string = process.env.S4_PASSWORD;
                  
                  if (destinationName != null){
                      // Get the destination via the Destination service
                      // of Cloud Foundry, in the SCP.
                      this.destination = {
                          destinationName: destinationName
                      };
                  }
                  else {
                      // Create the destination at run time,
                      // using the URI and credentials
                      // provided in the environment variables.
                      if(username != null && password != null) {
      
                          // BasicAuthentication
                          this.destination = {
                              url: url,
                              username: username,
                              password: password
                          };
                      }
                      else {
                          // NoAuthentication
                          this.destination = {
                              url: url
                          }
                      }
                  }
              }
              return this.destination;
          }
      
          public static getApikey(): string {
              if (this.apikey == null) {
                  if (process.env.S4_APIKEY == null) 
                      this.apikey = "";
                  else
                      this.apikey = process.env.S4_APIKEY;
              }
              return this.apikey;
          }
      }
      Copy code
      Content of business-partner.service.ts
      Code snippet
      import { Injectable, Param } from '@nestjs/common';
      import { BusinessPartner, BusinessPartnerAddress } 
          from '@sap/cloud-sdk-vdm-business-partner-service';
      import { BackendConnector } from './backend-connector'
      import { asc } from '@sap-cloud-sdk/core';
      
      @Injectable()
      export class BusinessPartnerService {
      
          static findAll(): Promise<BusinessPartner[]> {
              return BusinessPartner.requestBuilder()
                  .getAll()
                  .select(
                      BusinessPartner.BUSINESS_PARTNER,
                      BusinessPartner.LAST_NAME,
                      BusinessPartner.FIRST_NAME
                  )
                  .filter(
                      BusinessPartner.BUSINESS_PARTNER_CATEGORY
                          .equals("1")
                  )
                  .orderBy(asc(BusinessPartner.LAST_NAME))
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                  })
                  .execute( BackendConnector.getDestination() );
          }
      
          static findById(id: string): Promise<BusinessPartner> {
              return BusinessPartner.requestBuilder()
              .getByKey(id)
              .select(BusinessPartner.BUSINESS_PARTNER,
                  BusinessPartner.LAST_NAME,
                  BusinessPartner.FIRST_NAME,
                  BusinessPartner.IS_MALE,
                  BusinessPartner.IS_FEMALE,
                  BusinessPartner.CREATION_DATE,
                  BusinessPartner.TO_BUSINESS_PARTNER_ADDRESS
                          .select(
                      BusinessPartnerAddress.BUSINESS_PARTNER,
                      BusinessPartnerAddress.ADDRESS_ID,
                      BusinessPartnerAddress.COUNTRY,
                      BusinessPartnerAddress.POSTAL_CODE,
                      BusinessPartnerAddress.CITY_NAME,
                      BusinessPartnerAddress.STREET_NAME,
                      BusinessPartnerAddress.HOUSE_NUMBER))
              .addCustomHeaders({
                  APIKey: BackendConnector.getApikey()
              })
              .execute( BackendConnector.getDestination() );
          }
      
      }
      Copy code
      Content of business-partner.controller.ts
      Code snippet
      import { Controller, Get, Query } from '@nestjs/common';
      import { BusinessPartnerService } from './business-partner.service';
      import { BusinessPartner } 
          from '@sap/cloud-sdk-vdm-business-partner-service';
      
      @Controller('api/business-partners')
      export class BusinessPartnerController {
      
        @Get()
        async getBusinessPartners(@Query('id') id: string)
          : Promise<BusinessPartner[] | BusinessPartner> {
          if (id == null) {
            return BusinessPartnerService.findAll()
              .catch(error => {
                console.log(
                  `Failed to get business partners - ${error.message}`);
                return null;
              });
          }
          else {
            return BusinessPartnerService.findById(id)
            .catch(error => {
              console.log(
                `Failed to get business partner ${id} - ${error.message}`);
              return null;
            });
          }
        }
      }
      Copy code
      Content of business-partner-address.service.ts
      Code snippet
      import { Injectable} from '@nestjs/common';
      import { BusinessPartnerAddress } 
          from '@sap/cloud-sdk-vdm-business-partner-service';
      import { BackendConnector } from './backend-connector'
      
      @Injectable()
      export class BusinessPartnerAddressService {
      
          public static async create(address: BusinessPartnerAddress) 
              : Promise<BusinessPartnerAddress> {
              return BusinessPartnerAddress.requestBuilder()
                  .create(address)
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      
          public static update(address: BusinessPartnerAddress) 
              : Promise<BusinessPartnerAddress> {
              return BusinessPartnerAddress.requestBuilder()
                  .update(address)
                  .ignoreVersionIdentifier()
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      
          public static delete(businessPartner: string, addressId: string) 
              : Promise<void> {
              return BusinessPartnerAddress.requestBuilder()
                  .delete(businessPartner, addressId)
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      }
      Copy code
      Content of business-partner-address.controller.ts
      Code snippet
      import { Controller, Post, Body, Patch, Delete, Query } 
          from '@nestjs/common';
      import { BusinessPartnerAddressService } 
          from './business-partner-address.service';
      import { BusinessPartnerAddress } 
          from '@sap/cloud-sdk-vdm-business-partner-service';
      
      @Controller('api/addresses')
      export class BusinessPartnerAddressController {
      
        @Post()
        async postBusinessPartnerAddress( 
          @Body() body: BusinessPartnerAddress ) 
          : Promise<void> {
      
          const bpa = BusinessPartnerAddress.builder().fromJson(body);
          await BusinessPartnerAddressService.create(bpa)
            .catch(error => {
              console.log(
                `Failed to create business` 
                + `partner address - ${error.message}`);
            });
        }
      
        @Patch()
        async patchBusinessPartnerAddress( 
          @Body() body: BusinessPartnerAddress ) 
          : Promise<void> {
      
            const bpa = BusinessPartnerAddress.builder().fromJson(body);
            await BusinessPartnerAddressService.update(bpa)
              .catch(error => {
                console.log(`Failed to update business partner address `
                    + `${bpa.addressId} of business partner `
                    + `${bpa.businessPartner} ` 
                    + ` - ${error.message}`);
              });
          }
      
          @Delete()
          async deleteBusinessPartnerAddress(
            @Query('businessPartnerId') businessPartnerId: string,
            @Query('addressId') addressId: string)
            : Promise<void> {
            
              await BusinessPartnerAddressService
                .delete(businessPartnerId, addressId)
                .catch(error => {
                  console.log(`Failed to update business partner address ` 
                      + `${addressId} of business partner ` 
                      + `${businessPartnerId} `
                      + ` - ${error.message}`);
            });
          }
      }
      Copy code

    3. Open the src/app.module.ts file and add the controllers and providers of the new application (with corresponding import statements). You can pick (from the provided exercise files) the content of the ts_adman_03_app_module_ts.txt file [download] , and copy it in the project of the src/app.module.ts file.

      Code snippet
      import { Module } from '@nestjs/common';
      import { AppController } from './app.controller';
      import { AppService } from './app.service';
      import { BusinessPartnerController } 
        from './adman/business-partner.controller';
      import { BusinessPartnerService } 
        from './adman/business-partner.service';
      import { BusinessPartnerAddressController } 
        from './adman/business-partner-address.controller';
      import { BusinessPartnerAddressService } 
        from './adman/business-partner-address.service';
      
      @Module({
        imports: [],
        controllers: [
          AppController, 
          BusinessPartnerController, 
          BusinessPartnerAddressController],
        providers: [
          AppService, 
          BusinessPartnerService, 
          BusinessPartnerAddressService],
      })
      export class AppModule {}
      Copy code
    4. In the Explorer window, choose NPM SCRIPTSpackage.jsonbuildRun. The content of the dist folder is re-created. Once the build is executed, close the corresponding terminal window.

  3. Run the application against the SAP API Business Hub sandbox.

    1. Start the application with the following environment variables set (replace >>>YOUR API KEY<<< with your own API Key, for example, FDqbnElM7mgmgqbIKBFHRpS1dvpt6sHD. To get your API Key, open https://api.sap.com/api/API_BUSINESS_PARTNER, then log on, and choose Show API Key):

      NameValue
      S4_URLhttps://sandbox.api.sap.com/s4hanacloud
      S4_APIKEY>>>YOUR API KEY<<<
    2. Open the .vscode/launch.json file.

    3. In the Launch Application configuration, add the values of environment variables (replace >>>YOUR API KEY<<< with your own API Key, for example, FDqbnElM7mgmgqbIKBFHRpS1dvpt6sHD).

      Code snippet
      {
                  "name": "Launch Application",
                  "type": "pwa-node",
                  "request": "launch",
                  "program": "${workspaceFolder}/dist/main",
                  "skipFiles": [
                      "<node_internals>/**"
                  ],
                  "env": {
                      "S4_APIKEY": ">>>YOUR API KEY<<<",
                      "S4_URL": "https://sandbox.api.sap.com/s4hanacloud"
                    
      Copy code
      As an alternative, you can copy the entire ts_adman_04_launch_json.txt file [download] , and replace the full content of the launch.json file (replace >>>YOUR API KEY<<< with your own API Key).

    4. In Visual Studio Code, in the Run and Debug tab, run the Launch Application configuration.

    5. Open the browser at http://localhost:3000, the page shows Hello World!.

    6. In the browser, in the application page, edit the URL and add the following suffix:

      Code snippet
      /api/business-partners
      Copy code
      The service you defined in the business-partner.service.ts file is executed and the business partner information is extracted in JSON format.

    7. In Visual Studio Code, choose Stop (Shift+F5). The application execution is stopped.

  4. Re-map the Hello World service to the /hello path, to avoid impacting the next step.

    1. In the /src/app.controller.ts file, replace the @Get() statement with @Get('hello').

  5. Enable the application to serve static HTML content, using the Nest's @nestjs/serve-static module. The HTML content will be stored in the project within a folder named client.

    1. Open the package.json file.

    2. In the file, look for the following text:

      Code snippet
          "@nestjs/platform-express": "^8.0.0",
      Copy code
      Just after this text, insert the new dependency line:
      Code snippet
      "@nestjs/serve-static": "^2.2.2",
      Copy code
      The new text will look like the following:
      Code snippet
          "@nestjs/platform-express": "^8.0.0"
          "@nestjs/serve-static": "^2.2.2",
      Copy code

    3. Choose TerminalNew Terminal. In the Terminal, run the following command:

      Code snippet
      npm install
      Copy code
      The new node package is downloaded to the node_modules folder. Once the action is complete, close the terminal window.

    4. Open the tsconfig.json file (main configuration file for TypeScript).

    5. In the file, look for the following code:

      Code snippet
          "noFallthroughCasesInSwitch": false,
          "allowJs": true
        }
      Copy code
      Just before the last curly bracket, add the following code:
      Code snippet
      ,
        "include": ["src/**/*"]
      Copy code
      The final result will look like the following:
      Code snippet
          "noFallthroughCasesInSwitch": false,
          "allowJs": true
        },
        "include": ["src/**/*"]
      }
      Copy code

    6. In the project root folder, create a sub-folder called client.

    7. In the client folder, create a index.html containing the following HTML code:

      Code snippet
      <!DOCTYPE html>
      <html>
      <body>
          <a href="address-manager">Address Manager</a>
      </body>
      </html>
      Copy code
      Copy the content of the ts_adman_05_index_html.txt file [download] , to the project client/index.html file.

    8. Open the app.module.ts file.

    9. Add the following import statements at the beginning of the file:

      Code snippet
      import { ServeStaticModule } from '@nestjs/serve-static';
      import { join } from 'path';
      Copy code
      Look for the following statement:
      Code snippet
      @Module({
        imports: [],
      Copy code
      Modify it in this way:
      Code snippet
      @Module({
        imports: [
          ServeStaticModule.forRoot({
            rootPath: join(__dirname, '..', 'client'),
          }),
        ],
      Copy code
      You can pick (from the provided exercise files) the content of the ts_adman_05_app_module_ts.txt file [download], and copy it to the project src/app.module.ts file.

  6. Create the Address Manager front-end application, then build and open it. The application code for the front-end is provided in the ts_adman_frontend.zip file [download] .

    1. Right-click on the ts-adman/client folder, choose Upload Files..., upload the ts_adman_frontend.zip archive [download].

    2. Right-click on the ts-adman/client folder, choose Open in Terminal

    3. In the terminal execute the following commands:

      Code snippet
      unzip *.zip
      rm *.zip
      Copy code
    4. In the Explorer window, choose NPM SCRIPTSpackage.jsonbuildRun. The content of the dist folder is re-created. Once the build is executed, close the corresponding terminal window.

    5. in the Run and Debug tab, run the Launch Application configuration.

    6. Open the browser at http://localhost:3000, the page shows the Address Manager link..

    7. Click on Address Manager.

      The Address Manager application is opened. You can browse business partners and addresses, but you cannot modify addresses as the SAP API Business Hub sandbox is read-only.

    8. Close the application page.

    9. In Visual Studio Code, choose Stop (Shift+F5) twice. The application execution is stopped.

  7. Log on to your SAP S/4HANA Cloud tenant.

    1. In the Web browser (for example, Google Chrome), on your SAP S/4HANA Cloud tenant, access the SAP Fiori Launchpad at [S/4HANA tenant url]/ui, for example (https://my000000.s4hana.ondemand.com/ui). If requested, enter your user and password.

  8. In SAP S/4HANA Cloud, if it is not yet assigned, assign role: BR_BUPA_MASTER_SPECIALIST to your user.

    1. In the Home page, choose Search and search for the Maintain Business Users app.

    2. In the app, search for your user and display the details by selecting the line of the list.

    3. In the user detail screen, scroll down and check the Assigned Business Roles section.

    4. If the BR_BUPA_MASTER_SPECIALIST is missing from the list, choose Add.

    5. Search for the BR_BUPA_MASTER_SPECIALIST role, select the box beside it and choose OK. Choose Save.

    6. Select the SAP logo to navigate back to the Home page.

    7. Refresh the Web browser page to see the additional apps provided with the new role.

  9. In SAP S/4HANA Cloud, in the Manage Business Partner Master Data app, create a new business partner based on the following information (replace ### with your user number) if it doesn't already exist:

    FieldValue
    BP CategoryPerson
    GroupingInternal numbering for standard use
    BP RoleCRM000 Sold-to-party
    First NameJohn
    Last NameDoe ###
    CityNew York
    CountryUS
    LanguageEN
    1. In the home page, search and open the Manage Business Partner Master Data app.

    2. Choose CreatePerson.

    3. In the Create Person dialog, enter the information provided in the table.

    4. Choose OK

    5. Choose Save.

    6. Select the SAP logo to navigate back to the Home page.

  10. Run the application against your SAP S/4HANA Cloud tenant. Use the following environment variables to configure the connection information (replace ### with your user number):

    NameValue
    S4_URLYour S/4HANA Client tenant URL, for example https://my000000.s4hana.ondemand.com
    S4_USERNAMEADDRESS_MANAGER_###
    S4_PASSWORDWelcomeToTheClouds1!
    Note
    As a prerequisite, for this API to be accessible in the S/4HANA Cloud tenant, you need to execute the previous exercise: Activating the APIs in SAP S/4HANA Cloud.
    1. Open the .vscode/launch.json file.

    2. In the Launch Application configuration, replace the values of the environment variables:

      Code snippet
      {
                  "name": "Launch Application",
                  "type": "pwa-node",
                  "request": "launch",
                  "program": "${workspaceFolder}/dist/main",
                  "skipFiles": [
                      "<node_internals>/**"
                  ],
                  "env": {
                      "S4_URL": "https://my000000.s4hana.ondemand.com",
                      "S4_USERNAME": "ADDRESS_MANAGER_###",
                      "S4_PASSWORD": "WelcomeToTheClouds1!"
                  }
              }
      Copy code
      As an alternative, copy the full ts_adman_06_launch_json.txt file [download] , and replace the full content of the launch.json file.

    3. Choose F5 (RunStart Debugging).

    4. Open the browser at http://localhost:3000, the page shows the Address Manager link..

    5. Click Address Manager.. The Address Manager application is opened. Search your John Doe ### business partner and add a new address to it.

    6. Close the application page.

    7. In Visual Studio Code, choose Stop (Shift+F5) twice. The application execution is stopped.

  11. In the package.json file, modify the deploy script to include the client folder in application deployment.

    1. Open the package.json file.

    2. In the file, look for the following text, in the scripts section:

      Code snippet
      "deploy": "npm run build && sap-cloud-sdk package && cf push",
      Copy code

      The script chains three statements to build, package, and deploy to Cloud Foundry. In the second package, add the list of files to be packaged. Replace the whole line with the following coe block:

      Code snippet
      "deploy": "npm run build && sap-cloud-sdk package -i \"package.json,package-lock.json,dist/**/*,client/**/*\"  && cf push",
      Copy code
      In exercise files, you can pick the ts_adman_07_deploy.txt file [download] and copy the same text displayed.

  12. Deploy the application to Cloud Foundry.

    1. Choose TerminalNew Terminal. A terminal window appears in the lower part of the screen.

    2. Make sure the Cloud Foundry CLI is logged in and targeting your dev space. In the Terminal, execute the following command:

      Code snippet
      cf login
      
      Copy code
      If required, enter your SAP BTP API endpoint, e-mail, and password.

    3. In the project root folder, delete the deployment sub-folder if required.

    4. In the Explorer window, choose NPM SCRIPTSpackage.jsondeployRun. The application is built (dist folder is re-created), then it is packaged (deployment folder is created), then it is deployed to the Cloud Foundry environment.

      At the end of the deployment process, you will get a text such as the following:

      Code snippet
           state     since                  cpu     memory         disk           details
      #0   running   2020-04-24T17:25:03Z   66.4%   167.5M of 1G   152.4M of 1G
      Copy code

  13. Navigate to the running application in the SAP BTP Cockpit. Configure the environment variables for it to run against the SAP API Business Hub sandbox, then open it.

    1. In Google Chrome, open the URL: https://account.hanatrial.ondemand.com. If required, enter your e-mail and password.

    2. In the SAP BTP Cockpit, choose Enter Your Trial account. Navigate to your trial sub-account. Navigate to the dev space.

    3. Choose the ts-adman application name.

    4. In the Application: ts-adman - Overview page, go to the User-Provided Variables tab. Add the following variables (replace >>>YOUR API KEY<<< with your own API Key, for example, FDqbnElM7mgmgqbIKBFHRpS1dvpt6sHD. To get your API Key, open https://api.sap.com/api/API_BUSINESS_PARTNER, then log on, and choose Show API Key):

      KeyValue
      S4_URLhttps://sandbox.api.sap.com/s4hanacloud
      S4_APIKEY>>>YOUR API KEY<<<
    5. Go to the Overview tab and restart the application.

    6. Choose the Application Route. The application is opened.

    7. Click on Address Manager. The Address Manager application is opened, reading the data from the SAP API Business Hub sandbox system.

  14. In Cloud Foundry, create an instance of the Authorization & Trust Management service with name my-xsuaa.

    1. In Visual Studio Code, in the project root folder, create a new file named xs-security.json with the following content:

      Code snippet
      {
          "xsappname": "ts-adman",
          "tenant-mode": "shared"
      }
      Copy code
      You can pick (from the provided exercise files) the content of the ts_adman_08_xs_security_json.txt file [download] , and copy it in the project to the xs-security.json file.

    2. In the SAP BTP Cockpit, navigate to the trial sub-account, then to the dev space.

    3. In the dev space, navigate to ServicesService Marketplace tab. Choose the Authorization & Trust Management tile.

    4. In the Authorization & Trust Management screen, choose Create. Create a new instance based on the following information:

      FieldValue
      ServiceAuthorization & Trust Management
      Planapplication
      Instance Namemy-xsuaa
      Specify Parameters in JSON format{ "xsappname": "ts-adman", "tenant-mode": "shared" }
  15. Connect the my-xsuaa service to the ts-adman application.

    1. In the SAP BTP Cockpit, navigate to the dev space, then to the ts-adman application.

    2. In the Application: ts-adman - Overview page, go to the Service Bindings page.

    3. Choose Bind Service.

    4. Select Service from the catalog. Choose Next.

    5. Choose the Authorization & Trust Management service. Choose Next.

    6. Choose the Re-use existing instance. Select the my-xsuaa Instance. Choose Next.

    7. Choose Finish.

  16. In Cloud Foundry, in the case it does not exist yet, create an instance of the Destination service named my-destinations.

    1. In the SAP BTP Cockpit, navigate to the trial sub-account, then navigate to the dev space.

    2. In the dev space, navigate to the ServicesService Instances tab.

    3. In the Service Instances screen, choose Create Instance. Create a new instance based on the following information:

      FieldValue
      ServiceDestination
      Service Planlite
      Instance Namemy-destinations
  17. Bind the my-destinations service to the ts-adman application.

    1. In the SAP BTP Cockpit, navigate to the dev space, then to the ts-adman application.

    2. In the Application: ts-adman - Overview page, go to the Service Bindings page.

    3. Choose Bind Service.

    4. Select Service from the catalog. Choose Next.

    5. Choose the Destination service. Choose Next.

    6. Choose the Re-use existing instance. Select the my-destinations Instance. Choose Next.

    7. Choose Finish.

  18. In the my-destinations service, in the case it does not exist yet, create a destination named sandbox, referring to the SAP API Business Hub sandbox.

    1. In the SAP BTP Cockpit, navigate to the dev space, then to the ServicesService Instances tab.

    2. In the Service Instances screen, choose the my-destinations instance.

    3. In the my-destinations pane, choose More information is available for this instance. See here

    4. Choose the Destinations tab.

    5. Chose New Destination create a destination based on the following information:

      FieldValue
      Namesandbox
      TypeHTTP
      DescriptionSAP API Business Hub sandbox system
      URLhttps://sandbox.api.sap.com/s4hanacloud
      Proxy TypeInternet
      AuthenticationNoAuthentication
      Use default JDK truststorechecked
      Once you have saved the destination, choose Check Connection to verify that the destination can be reached.

  19. Adapt the environment variables of your application so that it reads the system information from the destination service. Then restart and open the application again.

    1. Navigate to the dev space, then to the ts-adman application, then to the User-Provided Variables tab.

    2. Delete the S4_URL variable.

    3. Enter a new variable with the name: S4_DESTINATION and value sandbox.

    4. Go to the Overview tab and restart the application.

    5. Choose the Application Route. The application opens in the Address Manager link page.

    6. Click Address Manager. The Address Manager application is opened, reading the data from the SAP API Business Hub sandbox system, configured via the sandbox destination in the my-destinations service.

  20. In the my-destinations service, create a destination named s4cloud, referring to your SAP S/4HANA Cloud tenant if required.

    1. Return to the main page of the dev space, navigate to ServicesService Instances page. Choose the my-destinations instance. Click on More information is available for this instance. See here

    2. Choose the Destinations page.

    3. Chose New Destination create a destination based on the following information (replace ### with your user number, replace the URL value with your own SAP S/4HANA Cloud tenant URL):

      FieldValue
      Names4cloud
      TypeHTTP
      DescriptionSAP S/4HANA Cloud tenant
      URLYour S/4HANA Client tenant URL, for example https://my000000.s4hana.ondemand.com
      Proxy TypeInternet
      AuthenticationBasicAuthentication
      UserADDRESS_MANAGER_###
      PasswordWelcomeToTheClouds1!
  21. Adapt the environment variables of your application so that it reads the s4cloud system information from the destination service. Restart and open the application again.

    1. Navigate to the dev space, then to your application, then to the User-Provided Variables tab.

    2. Change the value of the S4_DESTINATION variable to s4cloud.

    3. Optionally, delete the S4_APIKEY variable.

    4. Go to the Overview tab.

    5. Restart the application.

    6. Choose the Application Route. The application opens on the Address Manager link page.

    7. Click Address manager. The Address Manager application is opened, reading the data from your SAP S/4HANA Cloud tenant, configured via the s4cloud destination in the my-destinations service. Search your John Doe ### business partner and add a new address to it.

Save progress to your learning plan by logging in or creating an account