Exercise: Building a BP Address Manager 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 a Business Partner address manager extension, able to maintain addresses in SAP S/4HANA Cloud

Building a BP address manager extension using TypeScript and the Nest framework

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:

  • Creating your Pay-As-You-Go Account in SAP BTP
  • Activating the APIs in SAP S/4HANA Cloud: this exercise activates the required API in the S/4HANA Cloud tenant.

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.

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 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 your SAP BTP Cockpit based on the link you received at subscription time (for example: https://cockpit.eu20.hana.ondemand.com). If requested, enter your user and password.

    2. Choose the training subaccount, that you created in a previous exercise.

    3. Choose ServicesInstances and Subscriptions.

    4. Choose SAP Business Application Studio.

    5. Eventually start the training development space.

    6. Once the space is running, click on training to enter the development space.

  2. Open a terminal window and verify if the Nest 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
      Expand
      A list of NPM global packages displays with their version.

    4. If the list does not contain package: @nestjs/cli, execute the following command:

      Code snippet
      npm install -g @nestjs/cli
      Expand
    5. List the packages again; the list now contains the new package.

  3. In your projects folder, use the Nest CLI to generate a new application named ts-adman.

    1. In the terminal, execute the following command:

      Code snippet
      nest new ts-adman
      Expand
      Provide the following answers to the questions you are asked during the creation process:
      QuestionAnswer
      Which package manager would you like to use?npm
      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.

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

    1. Choose FileOpen Folder..., 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
      Expand

      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 terminal, run:

      Code snippet
      npm run build
      Expand

      The TypeScript files are converted to JavaScript and stored in the dist folder.

    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>/**"
            ]
          }
      Expand
      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. Commit changes in Source Control.

    1. Choose the Source Control tab.

    2. In the Message field, enter any text (for example initial), choose Commit.. In case you are requested to stage all the changes, choose Yes.

    3. Switch back to the Explorer tab.

  11. Adapt the project for deployment to Cloud Foundry.

    1. Open the src/main.ts file.

      Find this line:

      Code snippet
      await app.listen(3002);
      Expand

      and replace it with the following line:

      Code snippet
      await app.listen( process.env.PORT || 3002 );
      Expand

      Then save the file.

    2. In the root project folder, create a new file with name manifest.yml, containing the following text.

      Code snippet
      applications:
        - name: ts-adman
          path: ./
          buildpacks:
            - nodejs_buildpack
          memory: 256M
          command: npm run start:prod
          random-route: true
      Expand

      This text can also be found in the provided ts_adman_02_manifest_yml.txt file [download].

    3. In the root project folder, create a new file with name .cfignore, containing the following text.

      Code snippet
      node_modules
      Expand
  12. Deploy the application to Cloud Foundry.

    1. In the Visual Studio Code, if a Terminal window is not opened yet, choose TerminalNew Terminal.

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

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

    3. In the terminal, run:

      Code snippet
      npm run build
      Expand

      The TypeScript files are converted to JavaScript and stored in the dist folder.

    4. In the terminal, run:

      Code snippet
      cf push
      Expand

      The application is uploaded to Cloud Foundry, installed and run.

      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
      Expand
  13. In the SAP BTP Cockpit, navigate to the running application and open it.

    1. In a web browser, open your SAP BTP Cockpit based on the url you received at subscription time (for example: https://cockpit.eu20.hana.ondemand.com. If required, enter your e-mail and password.

    2. In the SAP BTP Cockpit, navigate to the training 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.

  14. In SAP Business Application Studio, commit changes in Source Control.

    1. Choose the Source Control tab.

    2. In the Message field, enter any text (for example Deployed to Cloud Foundry), choose Commit.

    3. Switch back to the Explorer tab.

  15. 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_03b_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>/**"
                  ]
              }
      Expand
  16. 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
      Expand
    2. Open the package.json file and search for the following line:

      Code snippet
      "start:prod": "node dist/main",
      Expand
      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",
      Expand

    3. Deploy the previous change. In Visual Studio Code. In the terminal window, run:

      Code snippet
      cf push
      Expand
    4. 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
      Expand
      Ignore the proposal to "Open in a New Tab" the service listening to port 9229.

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

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

    7. 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();
      Expand
    8. 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 SAP Business Application Studio.

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

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

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

  17. In SAP Business Application Studio, commit changes in Source Control.

    1. Choose the Source Control tab.

    2. In the Message field, enter any text (for example Ready for remote debugging), choose Commit.

    3. Switch back to the Explorer tab.

Task 2: 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/connectivity^2.11.0
    @sap-cloud-sdk/odata-v2^2.11.0
    @sap/cloud-sdk-vdm-business-partner-service^2.1.0
    1. Open the package.json file.

    2. In the file, at the end of the dependencies section, add the following text:

      Code snippet
      ,
          "@sap-cloud-sdk/connectivity": "^2.11.0",
          "@sap-cloud-sdk/odata-v2": "^2.11.0",
          "@sap/cloud-sdk-vdm-business-partner-service": "^2.1.0"
      Expand
    3. Choose TerminalNew Terminal. In the Terminal, run the following command:

      Code snippet
      npm install
      Expand
      The dependent node modules are downloaded to the node_modules folder.

  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:

      Note
      To better analyze the following source code, we recommend you review the following sections in the standard SAP Cloud SDK documentation:
      Content of backend-connector.ts
      Code snippet
      import { DestinationOrFetchOptions } from '@sap-cloud-sdk/connectivity';
      
      export class BackendConnector {
          
          private static destination: DestinationOrFetchOptions;
          private static apikey: string;
      
          public static getDestination(): DestinationOrFetchOptions {
      
              if (this.destination == null) {
                  // Get the environment variables
                  let destinationName: string = process.env.S4_DESTINATION;
                  let url: string = process.env.S4_URL;
                  let username: string = process.env.S4_USERNAME;
                  let 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;
          }
      }
      Expand
      Content of business-partner.service.ts
      Code snippet
      import { Injectable } from '@nestjs/common';
      import { BusinessPartner, businessPartnerService } from '@sap/cloud-sdk-vdm-business-partner-service';
      import { BackendConnector } from './backend-connector'
      import { asc } from '@sap-cloud-sdk/odata-v2';
      
      const { businessPartnerApi, businessPartnerAddressApi } = businessPartnerService();
      
      @Injectable()
      export class BusinessPartnerService {
      
          static findAll(): Promise<BusinessPartner[]> {
              return businessPartnerApi.requestBuilder()
                  .getAll()
                  .select(
                      businessPartnerApi.schema.BUSINESS_PARTNER,
                      businessPartnerApi.schema.LAST_NAME,
                      businessPartnerApi.schema.FIRST_NAME
                  )
                  .filter(
                      businessPartnerApi.schema.BUSINESS_PARTNER_CATEGORY
                          .equals("1")
                  )
                  .orderBy(asc(businessPartnerApi.schema.LAST_NAME))
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                  })
                  .execute( BackendConnector.getDestination() );
          }
      
          static findById(id: string): Promise<BusinessPartner> {
              return businessPartnerApi.requestBuilder()
              .getByKey(id)
              .select(businessPartnerApi.schema.BUSINESS_PARTNER,
                  businessPartnerApi.schema.LAST_NAME,
                  businessPartnerApi.schema.FIRST_NAME,
                  businessPartnerApi.schema.IS_MALE,
                  businessPartnerApi.schema.IS_FEMALE,
                  businessPartnerApi.schema.CREATION_DATE,
                  businessPartnerApi.schema.TO_BUSINESS_PARTNER_ADDRESS
                          .select(
                      businessPartnerAddressApi.schema.BUSINESS_PARTNER,
                      businessPartnerAddressApi.schema.ADDRESS_ID,
                      businessPartnerAddressApi.schema.COUNTRY,
                      businessPartnerAddressApi.schema.POSTAL_CODE,
                      businessPartnerAddressApi.schema.CITY_NAME,
                      businessPartnerAddressApi.schema.STREET_NAME,
                      businessPartnerAddressApi.schema.HOUSE_NUMBER))
              .addCustomHeaders({
                  APIKey: BackendConnector.getApikey()
              })
              .execute( BackendConnector.getDestination() );
          }
      
      }
      Expand
      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;
            });
          }
        }
      }
      Expand
      Content of business-partner-address.service.ts
      Code snippet
      import { Injectable } from '@nestjs/common';
      import { BusinessPartnerAddress, businessPartnerService } from '@sap/cloud-sdk-vdm-business-partner-service';
      import { BackendConnector } from './backend-connector'
      
      const { businessPartnerAddressApi } = businessPartnerService();
      
      @Injectable()
      export class BusinessPartnerAddressService {
      
          public static async create(address: BusinessPartnerAddress) : Promise<BusinessPartnerAddress> {
              return businessPartnerAddressApi.requestBuilder()
                  .create(address)
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      
          public static update(address: BusinessPartnerAddress) : Promise<BusinessPartnerAddress> {
              return businessPartnerAddressApi.requestBuilder()
                  .update(address)
                  .ignoreVersionIdentifier()
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      
          public static delete(businessPartner: string, addressId: string) 
              : Promise<void> {
              return businessPartnerAddressApi.requestBuilder()
                  .delete(businessPartner, addressId)
                  .addCustomHeaders({
                      APIKey: BackendConnector.getApikey()
                      })
                  .execute( BackendConnector.getDestination() );
          }
      
      }
      Expand
      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 { businessPartnerService } from '@sap/cloud-sdk-vdm-business-partner-service';
      
      const { businessPartnerAddressApi } = businessPartnerService();
      
      @Controller('api/addresses')
      export class BusinessPartnerAddressController {
      
        @Post()
        async postBusinessPartnerAddress( @Body() body ) {
          let bpa = businessPartnerAddressApi.entityBuilder().fromJson(body); //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 ) {
          let bpa = businessPartnerAddressApi.entityBuilder().fromJson(body); //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) {
            
              await BusinessPartnerAddressService.delete(businessPartnerId, addressId)
                .catch(error => {
                  console.log(`Failed to update business partner address ` 
                      + `${addressId} of business partner ${businessPartnerId} ` 
                      + ` - ${error.message}`);
            });
      
          }
      
      }
      Expand

    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_04_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 {}
      Expand
    4. In the terminal, run:

      Code snippet
      npm run build
      Expand

      The TypeScript files are converted to JavaScript and stored in the dist folder.

  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"
                    
                  }
      }
      Expand
      As an alternative, you can copy the entire ts_adman_05_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
      Expand
      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. In Visual Studio Code, commit changes in Source Control.

    1. Choose the Source Control tab.

    2. In the Message field, enter any text (for example Back-end service is working.), choose Commit.

    3. Switch back to the Explorer tab.

  5. 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').

  6. 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": "^9.0.0",
      Expand
      Just after this text, insert the new dependency line:
      Code snippet
      "@nestjs/serve-static": "^3.0.0",
      Expand
      The new text will look like the following:
      Code snippet
          "@nestjs/platform-express": "^9.0.0",
          "@nestjs/serve-static": "^3.0.0",
      Expand

    3. In the Terminal, run the following command:

      Code snippet
      npm install
      Expand
      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
        }
      Expand
      Just before the last curly bracket, add the following code:
      Code snippet
      ,
        "include": ["src/**/*"]
      Expand
      The final result will look like the following:
      Code snippet
          "noFallthroughCasesInSwitch": false
        },
        "include": ["src/**/*"]
      }
      Expand

    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>
      Expand
      Copy the content of the ts_adman_06_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';
      Expand
      Look for the following statement:
      Code snippet
      @Module({
        imports: [],
      Expand
      Modify it in this way:
      Code snippet
      @Module({
        imports: [
          ServeStaticModule.forRoot({
            rootPath: join(__dirname, '..', 'client'),
          }),
        ],
      Expand
      You can pick (from the provided exercise files) the content of the ts_adman_06_app_module_ts.txt file [download], and copy it to the project src/app.module.ts file.

  7. 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 Reveal in File Explorer,

    2. Extract the content of the ts_adman_frontend.zip archive [download]to the client folder. The archive contains an address-manager sub folder.

    3. In the terminal, run:

      Code snippet
      npm run build
      Expand

      The TypeScript files are converted to JavaScript and stored in the dist folder.

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

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

    6. 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.

    7. Close the application page.

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

  8. In Visual Studio Code, commit changes in Source Control.

    1. Choose the Source Control tab.

    2. In the Message field, enter any text (for example User interface is working.), choose Commit.

    3. Switch back to the Explorer tab.

  9. 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.

  10. 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.

  11. 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.

  12. 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!"
                  }
              }
      Expand
      As an alternative, copy the full ts_adman_07_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.

  13. Deploy the application to Cloud Foundry.

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

    2. In the Terminal, execute the following command:

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

    3. In the Terminal, execute the following command:

      Code snippet
      npm run build
      cf push
      
      Expand
      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
      Expand

  14. 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 a web browser, open your SAP BTP Cockpit based on the url you received at subscription time (for example: https://cockpit.eu20.hana.ondemand.com. If required, enter your e-mail and password.

    2. In the SAP BTP Cockpit, navigate to the training Subaccount. 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.

  15. 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"
      }
      Expand
      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" }
  16. 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.

  17. 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
  18. 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.

  19. 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.

  20. 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.

  21. 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!
  22. 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.

Log in to track your progress & complete quizzes