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.