Integrare una API esterna in un microservizio SAP CAP

Scenario

In questo tutorial vedremo come integrare un’API esterna all’interno di un applicativo CAP, attraverso la consumazione di una destination. Verrà spiegato come dialogare con un altro servizio sia durante lo sviluppo, quindi eseguendo l’applicazione in locale tramite comando “cds watch”, sia in produzione sfruttando l’Approuter e il Destination Service messi a disposizione dal BTP.

La base dati è così definita:

				
					namespace my.namespace;

entity Employee {
  key ID      : UUID;
      name    : String;
      surname : String;
      region  : String;
}

				
			

Le proprietà ID, name e surname sono valorizzate all’interno del db, mentre region verrà determinato in base ai dati recuperati dal servizio esterno. Come API verrà usata Northwind, un servizio di test messo a disposizione da OData.

Step 1 - Definire la destination nel package.json

Definiamo la destination all’interno della sezione cds/requires nel file package.json

				
					"cds": {
    "requires": {
      "externalServiceNorthwind": {
        "kind": "odata",
        "credentials": {
          "destination": "externalServiceNorthwind"
        }
      }
    }
  }

				
			

Per semplicità useremo lo stesso nome sia nel codice che per definire la destination su BTP (o in locale sul default-env.json). In generale, la sintassi di questa sezione del package.json è la seguente:

  • Il primo “externalServiceNorthwind” sotto “requires” indica il nome che associamo alla destination all’interno del progetto cap. Può essere un nome qualsiasi.
  • Il secondo “destination: externalServiceNorthwind” indica il nome assegnato alla destination su BTP, deve necessariamente chiamarsi nello stesso modo.

Step 2 - Implementare un handler per il mashup dei dati

Questa parte dipende molto dalla logica di business del progetto. Nell’esempio il campo region verrà valorizzato senza nessuna logica specifica. La parte importante di questo step è capire come consumare la destination: utilizziamo la funzione cds.connect.to(“nome-destination”) per collegarci alla destination e la send() per lanciare la chiamata verso il servizio puntato dalla destination. await next() ci permette di recuperare i dati provenienti dal database del progetto CAP.

				
					const cds = require("@sap/cds");

module.exports = cds.service.impl(async (srv) => {

    srv.on("READ", "Employee", async (req, next) => {
        
        const externalService = await cds.connect.to("externalServiceNorthwind")
        
        try {
            var responseExt = await externalService.send({
                query: 'GET /v4/northwind/northwind.svc/Regions',
                headers: {
                    'content-type': 'application/json'
                }
            })
            var responseDB = await next();
            responseDB.forEach((x,i) => {
                x.region = responseExt[i].RegionDescription
            });
            console.log(responseDB)
            return responseDB
        } catch (error) {
            req.error(500, error.message)
        }

    })
});

				
			

Step 3 - Test in locale

Step 3.1 - Definire la destination nel default-env.json

Per testare in locale la comunicazione con il servizio esterno abbiamo bisogno di definire la destination nel file default-env.json posizionato nella root del progetto CAP

				
					{"VCAP_SERVICES":[],"destinations":[{"name":"externalServiceNorthwind","url":"https:\/\/services.odata.org"}]}
				
			

Le informazioni da inserire sono name e url della destination. Notare che la parte dell’URI per accedere alla risorsa viene inserito direttamente nel codice definito nello step 2.

Step 3.2 - cds watch

Utilizziamo il comando cds watch per far partire l’applicazione in locale. Verrà creato un database temporaneo secondo la configurazione all’interno del package.json e verrà lanciato un server in ascolto sulla porta 4004, nel nostro caso, della nostra macchina che ospiterà l’applicativo. 

Dai log del terminale possiamo vedere che, quando si tenta di accedere a /my_service/Employee, il servizio si connette all’API esterna tramite la destination definita nello step 3.1

Nel browser possiamo vedere I dati di Employee con il campo region valorizzato

Step 4 - Test sul servizio deployato

Step 4.1 - Definire la destination sul btp

Definiamo la destination per raggiungere il servizio Northwind all’interno della sezione Destinations del subaccount su SAP BTP.

Step 4.1 – Aggiungere l’Approuter

In questo step utilizzeremo L’approuter, che è un servizio messo a disposizione da BTP per la gestione delle rotte e dei token per autenticazione e autorizzazione (non trattati in questo tutorial).

Tramite terminale, digitiamo il comando “cds add approuter”

Il framework aggiunge nell’mta.yaml un modulo di tipo approuter.nodejs

				
					  - name: MyProject
    type: approuter.nodejs
    path: app/ 
    parameters:
      keep-existing-routes: true
      disk-quota: 256M
      memory: 256M
    requires:
      - name: srv-api
        group: destinations
        properties:
          name: srv-api 
          url: ~{srv-url}
          forwardAuthToken: true

				
			

Nella cartella /app vengono creati alcuni file di configurazione. Quello di nostro interesse è l’xs-app.json dove andremo ad indicare come verranno gestite le chiamate.

				
					{"authenticationMethod":"none","routes":[{"source":"^\/v4\/northwind\/northwind.svc\/(.*)$","target":"\/v4\/northwind\/northwind.svc\/$1","destination":"externalServiceNorthwind"},{"source":"^\/my_service\/(.*)$","target":"\/my_service\/$1","destination":"srv-api"}]}
				
			

La prima rotta ci permette di indirizzare le chiamate a Northwind verso la destination che abbiamo definito su BTP, mentre la seconda per quelle che vanno verso il microservizio CAP.

Step 4.2 – Aggiungere il Destination Server

Per permettere all’approuter di recuperare le informazioni sulle destination definite nel BTP, dobbiamo aggiungere all’mta.yaml il Destination Service

				
					- name: btp_destination
    type: org.cloudfoundry.managed-service
    parameters:
      service: destination
      service-plan: lite

				
			

Aggiungiamo – name: btp_destination ai requires dell’approuter e del microservizio node.

Di seguito il file mta.yaml completo

				
					_schema-version: '3.1'
ID: MyProject
version: 1.0.0
description: "A simple CAP project."
parameters:
  enable-parallel-deployments: true
build-parameters:
  before-all:
    - builder: custom
      commands:
        - npx -p @sap/cds-dk cds build --production
modules:
  - name: MyProject-srv
    type: nodejs
    path: gen/srv
    parameters:
      buildpack: nodejs_buildpack
    build-parameters:
      builder: npm-ci
    provides:
      - name: srv-api # required by consumers of CAP services (e.g. approuter)
        properties:
          srv-url: ${default-url}
    requires:
      - name: MyProject-db
      - name: btp_destination
      - name: MyProject-auth

  - name: MyProject-db-deployer
    type: hdb
    path: gen/db
    parameters:
      buildpack: nodejs_buildpack
    requires:
      - name: MyProject-db
      - name: MyProject-auth

  - name: MyProject
    type: approuter.nodejs
    path: app/ 
    parameters:
      keep-existing-routes: true
      disk-quota: 256M
      memory: 256M
    requires:
      - name: srv-api
        group: destinations
        properties:
          name: srv-api 
          url: ~{srv-url}
          forwardAuthToken: true
      - name: MyProject-auth
      - name: btp_destination

resources:
  - name: MyProject-db
    type: com.sap.xs.hdi-container
    parameters:
      service: hana
      service-plan: hdi-shared
  - name: btp_destination
    type: org.cloudfoundry.managed-service
    parameters:
      service: destination
      service-plan: lite
  - name: MyProject-auth
    type: org.cloudfoundry.managed-service
    parameters:
      service: xsuaa
      service-plan: application
      path: ./xs-security.json
      config:
        xsappname: MyProject-${org}-${space}
        tenant-mode: dedicated

				
			

Step 4.3 – Deploy su CF

Compiliamo il progetto facendo tasto destro sull’mta.yaml > Build MTA Project. Il compilatore crea un archivio di tipo .mtar sotto la cartella /mta_archives. Pubblichiamo il progetto su CF cliccando col tasto destro sull’archivio mtar > Deploy MTA Archive

Nella sezione subaccount/space/overview nel BTP troveremo i microservizi definiti all’interno dell’mta.yaml che abbiamo appena deployato. Per testare apriamo l’approuter (nel nostro esempio “MyProject”, come definito nello step 4.1), effettuiamo il login e accediamo alla risorsa Employee. Il servizio mostrerà i risultati con il campo region popolato

Vuoi maggiori informazioni?

Vuoi approfondire l’argomento e ottenere maggiori informazioni o supporto da parte dei nostri developer?

Compila i campi qui sotto, ti ricontatteremo quanto prima.