Salesforce und SAP BW: Wie eine Anbindung mit ABAP gelingt

Sebastian Uhlig

Geschrieben von: Sebastian Uhlig - 03 Januar 2020
(Aktualisiert am: 14 Februar 2023)

Gerade im Cloudzeitalter wird eine flexible Konnektivität immer wichtiger. So sollen Cloud-Systeme stärker mit On-Premise-Systemen verzahnt werden. Dazu bietet die Mehrzahl der Cloudanbieter ausgereifte Schnittstellen an, die meist als sogenannte REST APIs realisiert sind.

In diesem Artikel zeige ich Ihnen, wie Sie ein Salesforce System an SAP BW anbinden und beleuchte die Integrationsmöglichkeiten. Für das Lesen und Schreiben von großen Datenmengen stellt Salesforce die Schnittstelle Bulk API 2.0 zur Verfügung.

Wann ist eine direkte Anbindung an ein Cloudsystem sinnvoll?

Eine direkte Anbindung an Salesforce ist sinnvoll, wenn Sie vom SAP-System aus das Datenladen steuern und anpassen möchten. Ein anderer Anwendungsfall ergibt sich, wenn Sie eine starke Integration zwischen dem SAP-System und Salesforce wünschen. Außerdem sind Sie auf eine direkte Anbindung angewiesen, wenn keine Middleware existiert, über die die Kommunikation erfolgen könnte.

Ist eine solche Verbindung sicher?

In einem solchen Szenario tritt der SAP BW Server als HTTP Client auf und baut eine Verbindung zu Salesforce auf. Hierbei müssen Sie die Firewall entsprechend konfigurieren, um eine ausgehende Verbindung auf die IP-Adressen von Salesforce zu erlauben. Dabei sind eingehende Verbindungen zum SAP BW Server nicht möglich, was das Risiko minimiert.

Einbindung in SAP BW

Die Verbindung zu Salesforce lässt sich mithilfe von Prozessketten in bestehende Ladevorgänge integrieren. Nachfolgend sehen Sie Szenarien für einen Lese- und einen Schreibzugriff.

Lesezugriff:

Prozesskette zum Lesen von Daten aus Salesforce

Schritt 1

Programm ausführen, welches Daten aus Salesforce liest und Request basiert in ein ADSO schreibt. Etwaige beim Lesen auftretende Fehler können ins Prozessketten-Log geschrieben werden

Schritt 2

ADSO aktivieren

 

Schreibzugriff:

Prozesskette zum Schreiben von Daten in Salesforce

Schritt 1

ADSO mit Daten beladen, die zu Salesforce übertragen werden sollen

Schritt 2

Programm ausführen, welches Daten an Salesforce sendet. Etwaige beim Senden auftretende Fehler können ins Prozessketten-Log geschrieben werden

 

Salesforce Schnittstelle Bulk API 2.0 im Detail

Sehen wir uns als Nächstes die Salesforce Schnittstelle Bulk API 2.0 im Detail an. Diese ist speziell für große Datenmengen ausgelegt und ermöglicht Lese- und Schreibzugriffe. So können Sie Abfragen aller Art auf Objekte in Salesforce stellen oder auch über INSERT/UPDATE/DELETE-Befehle Daten in Salesforce flexibel ändern. Die Details und aktuelle Dokumentation können Sie auf der Salesforce Seite einsehen.


SAP BW, HANA Native und SAP Datawarehouse Cloud - Laden Sie sich den Vergleich herunter

New call-to-action


Gekapselte Logik zur einfachen Anbindung

Zwecks einfacher Anbindung von neuen Tabellen bietet es sich an, die Salesforce API spezifische Logik auf der SAP-Seite zu kapseln. So wird bei neuen Anbindungen kein spezifisches Know-how über die Funktionsweise der Schnittstelle benötigt.

Ein Aufruf des Lesezugriffs könnte in einer ABAP Klasse wie folgt umgesetzt werden:

* Schritt 1: Login und wichtige Parameter für die zu nutzende BULK API 2.0
DATA lo_sf TYPE REF TO zcl_sf_bulk_api_2_0.
lo_sf = zcl_sf_bulk_api_2_0=>login_by_url(
i_host_login = 'test.salesforce.com'
i_path_login = '/services/oauth2/token'
i_bulk_api_2_0_vers = 'v47.0'
i_https = 'X'
i_port = '443'
i_clientid = 'XXX'
i_secret = 'XXX'
i_user = 'XXX'
i_pw = 'XXX'
).

* Schritt 2: Lesezugriff in Richtung Salesforce
CALL METHOD lo_sf->query_data
EXPORTING
i_sql = | SELECT Id, Name FROM Account LIMIT 100|
IMPORTING
e_result = DATA(result)
e_job_state = DATA(l_job_state)
.
* In E_Result erhalten Sie die Tabelle von Salesforce zur weiteren Verarbeitung zurück

Logik für einen lesenden Zugriff aus ABAP Schritt für Schritt erklärt

SAP Server als HTTP Client nutzen

Um die Verbindung von der SAP-Seite auszuführen, muss der SAP Server als HTTP Client die Salesforce-Schnittstelle aufrufen. Dafür stellt SAP die Klasse cl_http_client zur Verfügung. Die detaillierte Dokumentation dieser Klasse finden Sie hier.

oAuth 2.0 Login

Um sich bei Salesforce einzuloggen, müssen im Header bzw. in den Formularfeldern gewisse Informationen übergeben werden. Details und Hintergründe zum Login können Sie auf der Seite von Salesforce nachlesen.

Um den Login Prozess mit der ABAP Klasse umzusetzen, wird er wie folgt angepasst: 

    i_client->request->set_header_field(
EXPORTING
name = 'Content-Type' " Name des Header-Feldes
value = 'application/x-www-form-urlencoded' " Wert des Header-Feldes
).
i_client->request->set_form_field(
EXPORTING
name = 'grant_type' " Name des Form-Feldes
value = 'password' " Wert des Form-Feldes
).
i_client->request->set_form_field(
EXPORTING
name = 'client_id' " Name des Form-Feldes
value = i_clientid " Wert des Form-Feldes
).
i_client->request->set_form_field(
EXPORTING
name = 'client_secret' " Name des Form-Feldes
value = i_secret " Wert des Form-Feldes
).
i_client->request->set_form_field(
EXPORTING
name = 'username' " Name des Form-Feldes
value = i_user " Wert des Form-Feldes
).
i_client->request->set_form_field(
EXPORTING
name = 'password' " Name des Form-Feldes
value = i_pw " Wert des Form-Feldes
).
i_client->request->set_method(
method = 'POST'
).

Aus der Antwort des Servers kann der Access Token entnommen werden, welcher bei allen weiteren Zugriffen auf die Salesforce API im Header mitgeführt werden muss. Zudem erhalten Sie die Instanz als Antwort, auf welche der angemeldete Benutzer Zugriff hat. Diese Instanz wird bei allen weiteren Anfragen verwendet.

Job ID und Abfrage senden

Nachdem Sie das Access Token und die Instanz erhalten haben, können Sie diese bei allen weiteren Abfragen verwenden. Hierbei müssen Sie den Body und Header wie folgt anpassen:

* zum Beispiel DATA(sql) = | SELECT Id, Name FROM Account LIMIT 100|.
l_body_job =
|\{| &&
|"operation" : "query",| &&
|"query": "{ sql }"| &&
|\}|.

*get JobID and send query
DATA(l_uri_job) = |/services/data/{ mv_bulk_api_2_0_vers }/jobs/query/|.
* set request uri (/<path>[?<querystring>])
cl_http_utility=>set_request_uri( request = lo_client->request
uri =l_uri ).
IF i_method IS NOT INITIAL.
lo_client->request->set_method(
method = ‘POST’
).
ENDIF.
lo_client->request->set_header_field(
EXPORTING
name = 'Accept' " Name des Header-Feldes
value = 'application/json' " Wert des Header-Feldes
).
lo_client->request->set_header_field(
EXPORTING
name = 'Authorization' " Name des Header-Feldes
value = |Bearer { mv_sessionid }| " Access Token
).
IF i_body IS NOT INITIAL.
* convert body to xstring as this is better consumed by salesforce avoiding errors in Update requests.
DATA lx_body TYPE xstring.
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = i_body " variable type string
IMPORTING
buffer = lx_body. " variable type xstring
lo_client->request->set_data( lx_body ).
ENDIF.

Status der Abfrage überprüfen

Im letzten Schritt haben wir eine Abfrage an das Salesforce-System gestartet. Je nach Datenmenge kann es wenige Sekunden bis Minuten dauern, bis die Abfrage abgearbeitet ist und das Resultat zum Download bereitsteht.

Um den aktuellen Status der Abfrage zu überprüfen, können Sie eine Statusabfrage an Salesforce senden. Als Antwort erhalten Sie den jeweils aktuellen Zustand zurück. Sie sollten in regelmäßigen Abständen prüfen, ob der Job korrekt und vollständig abgearbeitet wurde. Dabei entspricht der Zustand JobComplete einer erfolgreich abgeschlossenen Abfrage. Wie die Statusabfrage genau aussehen muss ist hier beschrieben.

Ergebnisse abrufen

Nachdem Sie JobComplete als Zustand zurückbekommen haben, können Sie im letzten Schritt die Ergebnisse über einen GET-Request abrufen. Hierfür wird eine neue Abfrage mit dem folgenden Pfad und Header an Salesforce gesendet.

DATA(l_uri_queryresults) = |/services/data/{ mv_bulk_api_2_0_vers }/jobs/query/{ mv_job_id }/results/|.
IF i_method IS NOT INITIAL.
lo_client->request->set_method(
method = i_method
).
ENDIF.
lo_client->request->set_header_field(
EXPORTING
name = 'Accept' " Name des Header-Feldes
value = 'application/json' " Wert des Header-Feldes
).
lo_client->request->set_content_type( content_type = ‘GET’).
lo_client->request->set_header_field(
EXPORTING
name = 'Authorization' " Name des Header-Feldes
value = |Bearer { mv_sessionid }| " Wert des Header-Feldes
).

Zusammenfassung

Es ist möglich, ein Cloudsystem mit einem überschaubaren Aufwand an das SAP BW anzubinden. Das Schöne daran ist, dass es unzählige Möglichkeiten der Integration gibt, die sich mit diesem oder einem ähnlichen Ansatz erschließen lassen.

Wenn Sie solche oder ähnliche Integration mit einem anderen Cloud-Anbieter oder einer anderen Schnittstelle anstreben, sehen Sie sich bitte unser Angebot zur Web-Konnektivität an:

Angebot ansehen

Themen: SAP BW/4HANA, SAP Connector

Beitrag teilen

Sie haben eine Frage zum Blog?
Fragen Sie Sebastian Uhlig