SAP BTP Cloud Foundry App mit SAP HANA Cloud Datenbank verbinden

SAP BTP Cloud Foundry App mit HANA Cloud Datenbank verbinden

In einem früheren Beitrag, Wie Sie eine App auf SAP BTP Cloud Foundry erstellen, habe ich Sie Schritt für Schritt durch die Erstellung einer eigenen Applikation geführt. In diesem Beitrag zeige ich Ihnen, wie Sie diese App mit einer SAP HANA Cloud Datenbank verknüpfen.

Operatives Reporting und strategische Planung in gewohnter Excel Umgebung. Mit der zweiten Auflage meines Praxishandbuchs lernen Sie, SAP Analysis for Microsoft Office einzurichten, aktuelle Daten aus SAP Systemen in Excel auszuwerten und professionelle Berichte zu erstellen.

Zunächst müssen Sie die Datenbank auf SAP BTP bereitstellen. Wählen Sie im BTP Cockpit Boosters aus dem Navigationsmenü aus.

Boosters

Geben Sie in der Suche „Set Up SAP HANA Cloud Administration Tools“ ein und klicken Sie anscließend auf Start.

Set Up SAP HANA Cloud Administration Tools

Nachdem der Booster erfolgreich eingerichtet wurde, navigieren Sie zu dem Subaccount.

Navigate to Subaccount

Wählen Sie unter Services (1) den Eintrag Instances and Subscription (2) aus. Selektieren Sie anschließend den Eintrag Go to Application (3) bei SAP HANA Cloud.

Go to SAP HANA Cloud Application

Sie werden nun zu HANA Cloud Central weitergeleitet. Klicken Sie auf Create Instance, um eine neue Instanz anzulegen.

SAP HANA Cloud Instanz anlegen

Wählen Sie SAP HANA Cloud, SAP HANA Database als Typ aus (1) und klicken Sie auf Next Step (2).

Typ auswählen

Vergeben Sie einen Namen für die Instanz (1) und definieren Sie einen Administrator Passwort (2).

Name und Admin Passwort festlegen

Beim nächsten Schritt können Sie die Standard Memory Einstellung übernehmen.

Memory festlegen

Den Schritt SAP HANA Database Availability Zone and Replicas können Sie auch überspringen.

Replicas

Im nächsten Schritt können Sie zusätzliche Einstellungen definieren. So können Sie bestimmen, ob die Datenbank nur für Cloud Foundry IPs, allen IP Adressen oder nur ausgewählten Adressen verfügbar ist (1). Wählen Sie Allow all IP addresses aus, wenn Sie auch lokal auf die Datenbank zugreifen wollen.

Darüber hinaus müssen Sie ein Mapping für Cloud Foundry festlegen. Klicken Sie dazu auf Add Mapping (2). Wählen Sie die als Environment Instance ID (3) die Org ID und als Environment Group (4) die Space ID aus.

SAP HANA Cloud Advanced Settings

Die Org ID und den Org Namen können Sie in dem Subaccount unter Cloud Foundry einsehen.

Org ID bestimmen

Die Space ID sehen Sie, wenn Sie im BTP Cockpit des Subaccounts unter Cloud Foundry den Eintrag Spaces auswählen und anschließend den Space selektieren. Sowohl die Org ID als auch die Space ID sind in der URL einsehbar. Zum Beispiel:

https://account.hanatrial.ondemand.com/trial/#/globalaccount/306a331f-b684-4ad4-92a4-f0634b3b1db0/subaccount/1096a328-524d-4d6d-9e9c-d8abfe0a2b28/org/123d3858-9a2a-4894-9505-6eac8323f6fc/space/fef3e096-2eab-43cd-8218-125809d23c60/applications

Wenn Sie bereits eine App auf Cloud Foundry bereitgestellt haben, sehen Sie die beiden IDs auch unter Environment Variables der App.

Umgebungsvariablen der App

Schließlich können Sie auch den Cloud Foundry CLI Client nutzen, um die IDs zu bestimmen. Verwenden Sie dazu die folgenden Befehle

cf org <your_org_name> --guid

cf space <your_space_name> --guid

Zum Beispiel:

cf org 55f175bbtrial --guid

cf space dev --guid
Org und Space ID herausfinden

Ok, zurück zu unserer HANA Cloud Instanz. Sie können den letzten Schritt, Data Lake, überspringen und mit Review and Create fortfahren.

Überprüfen Sie nochmals die Einstellungen und klicken Sie auf Create Instance.

Einstellungen überprüfen und Instanz anlegen

Das kann eine Weile dauern. Holen Sie sich in der Zwischenzeit einen Kaffee. Wenn der Status Running anzeigt, ist Ihre Datenbank bereit.

Instanz läuft

Je nach Präferenz können Sie SQL Console und Database Objects direkt nutzen oder SAP HANA Database Explorer verwenden.

Verschiedene Möglichkeiten

In unserem Beispiel wollen wir die Datenbank nutzen, um den Begrüßungstext mit dem Nachnahmen anzureichern. Dazu legen wir eine Tabelle an und tragen einen Wert ein.

CREATE TABLE person (
    name VARCHAR(20) PRIMARY KEY,
    nachname VARCHAR(20)
);

INSERT INTO person VALUES('Denis', 'Reis');
Werte in der Tabelle

Nun haben wir eine HANA Datenbank mit Werten, allerdings hat unsere App noch keinen Zugriff auf die Datenbank. Die Verknüpfung erfolgt mithilfe eines Cloud Foundry hana Dienstes, der auf BTP als „SAP HANA Schemas & HDI Containers“ bezeichnet wird (siehe SAP HANA Cloud, SAP HANA Database Developer Guide for Cloud Foundry Multitarget Applications (SAP Web IDE Full-Stack) Dokumenation für Details).

Um einen neuen Dienst (Service) anzulegen, verwenden wir den Befehl create-service:

cf create-service SERVICE_OFFERING PLAN SERVICE_INSTANCE

Wir legen eine hana Service Instanz mit dem Service Plan hdi-shared an. Als Namen der Instanz vergeben wir pyhana.

cf create-service hana hdi-shared pyhana
Instanz anlegen

Im BTP Cockpit des Subaccounts sehen Sie nun eine neue Instanz pyhana des Dienstes SAP HANA Schemas & HDI Containers.

Neue SAP HANA Schemas & HDI Containers Instanz

Nun müssen wir diesen Dienst an unsere App binden. Dazu können Sie im BTP Cockpit über Create Binding eine Bindung anlegen.

Bindung anlegen

Wählen Sie anschließend die gewünschte Applikation aus und klicken Sie auf Create.

App auswählen

Bei der Bindung erfolgt die Konfiguration der Service Instanz und Anmeldeinformationen werden generiert.

Sie können die Anmeldeinformationen im BTP Cockpit als Form oder JSON einsehen.

Darüber hinaus werden die Anmeldeinformationen auch in den Umgebungsvariablen der Applikation unter VCAP_SERVICES hinterlegt.

Umgebungsvariablen der App

In der HANA Datenbank werden auch entsprechende Schemata angelegt.

Sie können die Schemata auch über die SQL Console abrufen.

SELECT * FROM SYS.SCHEMAS;

Alternativ zu BTP Cockpit können sie auch den Befehl bind-service verwenden, um die Applikation an einen Dienst zu binden.

cf bind-service APP_NAME SERVICE_INSTANCE

Zum Beispiel:

cf bind-service fancy-hello-world-app pyhana

Um die Bindung wieder zu löschen, nutzen Sie den Befehl unbind-service.

Nun hat unsere App Zugriff auf die Datenbank. Aber der neue Benutzer hat keinen Zugriff auf die zentralle Tabelle person, die vom Benutzer DBADMIN angelegt wurde.

Fehlende Berechtigungen

Daher logen wir uns mit dem Benutzer DBADMIN ein und gewähren mit GRANT SELECT dem neuen Benutzer Zugriff auf die Tabelle.

GRANT SELECT ON <schema>.<table> TO <user>;

Zum Beispiel:

GRANT SELECT ON DBADMIN.PERSON TO "6CED33A3AB6A4DEE8659049B67B8638B_3H36L788I4HTOCR0R17RLMOWM_RT";

Anschließend kann der neue Benutzer die Tabelle lesen.

Tabelle erfolgreich gelesen

Als nächsten passen wir die ursprüngliche App an. So muss die Bindung auch in der manifest.yml Datei der App hinterlegt werden. Fügen Sie die folgenden Zeilen hinzu:

  services:
  - pyhana

Nun sieht die manifest.yml Datei wie folgt aus:

---
applications:
- name: fancy-hello-world-app
  random-route: false
  routes:
  - route: https://fancy-hello-world-app.cfapps.us10-001.hana.ondemand.com
  path: ./
  memory: 512M
  disk_quota: 1024M
  instances: 2
  buildpacks: 
  - python_buildpack
  command: python server.py
  services:
  - pyhana

Darüber hinaus brauchen wir zwei neue Python Module. Um die Datenbankanmeldeinformationen aus den Umgebungsvariablen der App zu lesen, verwenden wir das Modul cfenv. Für die Verbindung mit der HANA Datenbank nutzen wir das Modul hdbcli. Daher passen wir die Datei requirements.txt wie folgt an:

Flask==2.3.*
cfenv==0.5.3
hdbcli==2.24.*

Schließen passen wir den Code an. Wir lesen die Umgebungsvariablen aus, verbinden uns mit den ausgelesenen Anmeldeinformationen zu der Datenbank und lesen die Tabelle, um den zum Namen passenden Nachnamen zu finden.

import os
from flask import Flask
from fancy import get_fancy_html  
from cfenv import AppEnv
from hdbcli import dbapi

app = Flask(__name__)
port = int(os.environ.get('PORT', 3000))
# Read name from environment variable
name = os.environ.get('NAME')

# Connect to the database and read the last name
env = AppEnv()

hana_service = 'hana'
hana = env.get_service(label=hana_service)


conn = dbapi.connect(address=hana.credentials['host'],
                        port=int(hana.credentials['port']),
                        user=hana.credentials['user'],
                        password=hana.credentials['password'],
                        encrypt='true',
                        sslTrustStore=hana.credentials['certificate'])

cursor = conn.cursor()
sql_command = f"SELECT nachname FROM dbadmin.person WHERE name = '{name}'"
cursor.execute(sql_command)
row = cursor.fetchone()
cursor.close()
conn.close()

nachname = str(row["nachname"])

@app.route('/')
def home():
    return get_fancy_html(name=name, nachname=nachname)  

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=port)

Der Nachname wird an das HTML Modul fancy.py übergeben und dort verarbeitet.

# fancy.py
def get_fancy_html(name, nachname):
    html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Fancy Hello World</title>
    <style>
        body {{
            margin: 0;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            /* Animated gradient background */
            background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
            background-size: 400% 400%;
            animation: gradientBG 15s ease infinite;
            overflow: hidden; /* Hide scrollbars */
            font-family: Arial, sans-serif; 
        }}

        @keyframes gradientBG {{
            0% {{ background-position: 0% 50%; }}
            50% {{ background-position: 100% 50%; }}
            100% {{ background-position: 0% 50%; }}
        }}

        .hello-text {{
            font-size: 14em;
            color: white;
            text-shadow: 2px 2px 5px rgba(0,0,0,0.3);
            /* Text animation */
            animation: moveText 6s ease-in-out infinite alternate;
        }}

        @keyframes moveText {{
            0% {{ transform: translateY(0px) scale(1); }}
            50% {{ transform: translateY(-20px) scale(1.1); }}
            100% {{ transform: translateY(0px) scale(1); }}
        }}
    </style>
</head>
<body>
    <div class="hello-text">Hello {name} {nachname}!</div>
</body>
</html>
"""
    return html_content

Schließlich deployen wir die angepasste App:

cf push

Das Ergebnis lässt sich sehen, unsere App funktioniert.

Ich hoffe, dass dieser Beitrag Ihnen geholfen hat. Sie können die Beispieldateien hier herunterladen.

Ihre User beklagen sich über langsame Berichte?

  • In meinem Newsletter lernen Sie, wie Sie Abhilfe schaffen.
  • Entdecken Sie die Möglichkeiten der Performanceoptimierung.
  • Praktische Anleitungen ermöglichen Ihnen schnelle Erfolge bei der Optimierung von SAP Systemen.
  • Viele Tipps und Tricks zu SAP BI Themen.
  • Holen Sie die maximale Performance aus Ihrem SAP BI!
  • Bei der Anmeldung zu meinem Newsletter erhalten Sie das Buch „High Performance SAP BI“ als Willkommensgeschenk.
Fordere SAP Performance Tricks an

Jetzt anfordern!

* Pflichtfeld
 
Kein SPAM. Ich hasse Spam genau so wie du.

0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

This site uses Akismet to reduce spam. Learn how your comment data is processed.