This is a test message to test the length of the message box.
Login
|
BTP On-Premise (OData)
Erstellt von Software-Heroes

BTP - Zugriffsmethoden On-Premise (OData)

537

In diesem Artikel schauen wir uns die anderen Zugriffmethoden auf einen OData Service über die Proxy Klassen an.

Werbung


Im letzten Artikel haben wir uns angeschaut, wie wir einen OData Service im ABAP Environment zur Verfügung stellen und zum ersten Mal auch aufrufen. Neben dem Holen von Daten gibt es aber auch andere Szenarien, mit der API im Backend zu arbeiten, diese wollen wir uns in diesem Artikel näher anschauen.

 

Einleitung

Wie bereits im letzten Artikel angesprochen, müssen wir vor dem Zugriff eine Proxy Klasse erzeugen, über die wir unser Proxy Objekt erzeugen können, um auf das Backend zugreifen zu können. Wir verwenden in diesem Fall wieder eine Destination aus dem Destination Service und erzeugen das Objekt in einer eigenen Methode GET_PROXY. Diese Methode verwenden wir in allen folgenden Beispielen:

DATA(lo_destination) = cl_http_destination_provider=>create_by_cloud_destination(
  i_name       = c_destination
  i_authn_mode = if_a4c_cp_service=>service_specific
).

DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

ro_result = cl_web_odata_client_factory=>create_v2_remote_proxy(
  EXPORTING
    iv_service_definition_name = 'ZBS_DEMO_RAP_ONPREM_ODATA'
    io_http_client             = lo_client
    iv_relative_service_root   = '/sap/opu/odata/sap/ZBS_API_COMPANY_NAMES_O2' ).

 

READ mit Filter

Beim letzten Zugriff hatten wir alle Daten der Schnittstelle gelesen, in diesem Beispiel wollen wir einmal einen Filter auf ein Feld anwenden, um nur eine Teilmenge der Daten zu lesen. Im ersten Schritt erstellen wir eine Range mit den entsprechenden Filtern und erzeugen dann ein Objekt zum Lesen. Im Anschluss erzeugen wir eine Filter-Factory und bauen einen Filter für den Zugriff auf.

DATA:
  lt_r_branch TYPE RANGE OF zbs_rap_companynames-Branch,
  lt_found    TYPE STANDARD TABLE OF zbs_rap_companynames.

lt_r_branch = VALUE #( sign = 'I' option = 'EQ'
  ( low = 'Software' )
  ( low = 'Food' )
).

DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_read( ).

" Create filter object 
DATA(lo_filter_factory) = lo_request->create_filter_factory( ).
DATA(lo_filter)  = lo_filter_factory->create_by_range( iv_property_path = 'BRANCH' it_range = lt_r_branch ).
lo_request->set_filter( lo_filter ).

DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING et_business_data = lt_found ).

 

Es werden nun aus dem Backend die gefundenen Einträge in LT_FOUND zurückgegeben, diese entsprechen unserem angewandten Filter:

 

CREATE

Im zweiten Beispiel wollen wir einen neuen Datensatz On-Premise erzeugen. Dazu definieren wir uns eine Struktur mit den neuen Werten, der Schlüssel der Entität muss aber mindestens gefüllt sein. Dann erzeugen wir uns  ein Objekt für die Anlage und übergeben die Daten. Am Ende führen wir die Anfrage per Execute aus.

DATA:
  ls_created TYPE zbs_rap_companynames.

DATA(ls_new_company) = VALUE zbs_rap_companynames(
  CompanyName = 'Gazprom'
  Branch = 'Gas'
).

DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_create( ).
lo_request->set_business_data( ls_new_company ).

DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_created ).

 

Wenn wir uns die Tabelle im Data-Preview anschauen, wurde der neue Datensatz angelegt. Mit einer weiteren Leseabfrage, könnten wir dann die Daten ermitteln:

 

UPDATE

Den zuvor angelegten Datensatz wollen wir in diesem Schritt nun aktualisieren und eine Beschreibung mitgeben. Dazu definieren wir uns zwei Strukturen, eine für den Schlüssel und eine mit den Daten. Bevor wir das Update-Objekt erzeugen können, müssen wir über den Schlüssel navigieren. Beim Update setzen wir die HTTP Methode auf PUT. Zum Abschluss übergeben wir wieder die neuen Daten und führen die Anfrage aus.

DATA:
  ls_updated TYPE zbs_rap_companynames.

DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).

DATA(ls_update_company) = VALUE zbs_rap_companynames(
  companyname         = 'Gazprom'
  branch              = 'Gas'
  companydescription  = `PJSC Gazprom is a Russian majority state-owned multinational energy corporation headquartered in the Lakhta Center in Saint Petersburg.`
).

DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
  )->navigate_with_key( ls_key
  )->create_request_for_update( /iwbep/if_cp_request_update=>gcs_update_semantic-put
).
lo_request->set_business_data( ls_update_company ).

DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_updated ).

 

In diesem Fall sind nun die Daten über den Data-Preview vollständig und wir sehen die befüllte Beschreibung im Backend System:

 

DELETE

Zum Abschluss wollen wir den Datensatz wieder aus dem System entfernen. In diesem Fall benötigen wir nur die Schlüssel-Struktur, navigieren über diese und erzeugen uns ein Objekt zum Löschen. Am Ende reicht das Ausführen der Abfrage und der Datensatz wird gelöscht.

DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).

DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
  )->navigate_with_key( ls_key
  )->create_request_for_delete(
).

lo_request->execute( ).

io_out->write( `Company deleted` ).

 

Vollständiges Beispiel

Hier noch einmal die vollständige Beispielklasse mit der Ausführung. Damit diese läuft, muss noch eine existierende Destination eingefügt werden und die API im Zielsystem laufen:

CLASS zcl_bs_demo_odata_actions DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
    CONSTANTS:
      c_destination TYPE string VALUE `<destination-service-id>`,
      c_entity      TYPE /iwbep/if_cp_runtime_types=>ty_entity_set_name VALUE 'COMPANYNAMES'.

    METHODS:
      get_proxy
        RETURNING VALUE(ro_result) TYPE REF TO /iwbep/if_cp_client_proxy,

      read_data_with_filter
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out
        RAISING
          /iwbep/cx_gateway,
      create_new_company
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out
        RAISING
          /iwbep/cx_gateway,
      update_company_description
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out
        RAISING
          /iwbep/cx_gateway,
      delete_company
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out
        RAISING
          /iwbep/cx_gateway.
ENDCLASS.


CLASS zcl_bs_demo_odata_actions IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    TRY.
        read_data_with_filter( out ).
        create_new_company( out ).
        update_company_description( out ).
        delete_company( out ).

      CATCH cx_root INTO DATA(lo_error).
        out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.


  METHOD get_proxy.
    TRY.
        DATA(lo_destination) = cl_http_destination_provider=>create_by_cloud_destination(
          i_name       = c_destination
          i_authn_mode = if_a4c_cp_service=>service_specific
        ).

        DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

        ro_result = cl_web_odata_client_factory=>create_v2_remote_proxy(
          EXPORTING
            iv_service_definition_name = 'ZBS_DEMO_RAP_ONPREM_ODATA'
            io_http_client             = lo_client
            iv_relative_service_root   = '/sap/opu/odata/sap/ZBS_API_COMPANY_NAMES_O2' ).

      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.


  METHOD read_data_with_filter.
    DATA:
      lt_r_branch TYPE RANGE OF zbs_rap_companynames-Branch,
      lt_found    TYPE STANDARD TABLE OF zbs_rap_companynames.

    lt_r_branch = VALUE #( sign = 'I' option = 'EQ'
      ( low = 'Software' )
      ( low = 'Food' )
    ).

    DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_read( ).

    DATA(lo_filter_factory) = lo_request->create_filter_factory( ).
    DATA(lo_filter)  = lo_filter_factory->create_by_range( iv_property_path = 'BRANCH' it_range = lt_r_branch ).
    lo_request->set_filter( lo_filter ).

    DATA(lo_response) = lo_request->execute( ).
    lo_response->get_business_data( IMPORTING et_business_data = lt_found ).

    io_out->write( `Read with filter active:` ).
    io_out->write( lt_found ).
  ENDMETHOD.


  METHOD create_new_company.
    DATA:
      ls_created TYPE zbs_rap_companynames.

    DATA(ls_new_company) = VALUE zbs_rap_companynames(
      CompanyName = 'Gazprom'
      Branch = 'Gas'
    ).

    DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_create( ).
    lo_request->set_business_data( ls_new_company ).

    DATA(lo_response) = lo_request->execute( ).
    lo_response->get_business_data( IMPORTING es_business_data = ls_created ).

    io_out->write( `Created new company:` ).
    io_out->write( ls_created ).
  ENDMETHOD.


  METHOD update_company_description.
    DATA:
      ls_updated TYPE zbs_rap_companynames.

    DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).

    DATA(ls_update_company) = VALUE zbs_rap_companynames(
      companyname         = 'Gazprom'
      branch              = 'Gas'
      companydescription  = `PJSC Gazprom is a Russian majority state-owned multinational energy corporation headquartered in the Lakhta Center in Saint Petersburg.`
    ).

    DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
      )->navigate_with_key( ls_key
      )->create_request_for_update( /iwbep/if_cp_request_update=>gcs_update_semantic-put
    ).
    lo_request->set_business_data( ls_update_company ).

    DATA(lo_response) = lo_request->execute( ).
    lo_response->get_business_data( IMPORTING es_business_data = ls_updated ).

    io_out->write( `Updated company:` ).
    io_out->write( ls_updated ).
  ENDMETHOD.


  METHOD delete_company.
    DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).

    DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
      )->navigate_with_key( ls_key
      )->create_request_for_delete(
    ).

    lo_request->execute( ).

    io_out->write( `Company deleted:` ).
  ENDMETHOD.
ENDCLASS.

 

Fazit

Die Arbeit mit den Daten im Backend ist relativ einfach und folgt immer dem gleichen Schema. Im angelegten Consumption Modell bekommst du immer einige rudimentäre Beispiele, wie du die Abfragen Richtung On-Premise durchführen kannst oder du nutzt einfach unseren Artikel dafür.


Enthaltene Themen:
BTPRAPABAP EnvironmentOn-PremiseOData
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Dienstag und Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


BTP - E-Mail Anbindung OAuth 2.0

Kategorie - ABAP

Die Mail-Anbindung per Basic Auth funktioniert nun nicht mehr. Welche Möglichkeiten bestehen alternativ für die Anbindung von Office365 an das ABAP Environment und wie kannst du sie einrichten?

13.10.2026

BTP - Pakete und SWC bereinigen

Kategorie - ABAP

Du möchtest ein Pakete im ABAP Environment löschen, doch es gibt noch Objekte die blockieren und vielleicht gar nicht mehr in Eclipse sichtbar sind? Schauen wir uns dazu einige Punkte zur Bereinigung an.

25.09.2026

RAP - Sales App Learnings

Kategorie - ABAP

Das Tutorial für die Sales App ist zu Ende und dieses Mal wurde eine große Bandbreite an Themen und Bereichen adressiert. In diesem Artikel schauen wir auf das Gelernte und wichtige Punkte.

08.09.2026

RAP - Navigation (App to App)

Kategorie - ABAP

Wie kannst du eigentlich innerhalb deiner Fiori Anwendung auf eine andere Anwendung navigieren, ohne das der User die App manuell wechseln muss? Schauen wir uns die Navigation zwischen Fiori Apps an.

01.09.2026

RAP - Singleton Pattern

Kategorie - ABAP

Das Singleton Pattern in RAP gibt es schon länger, doch wie genau funktioniert es und wie kannst du es auch für andere Use-Cases nutzen? Schauen wir uns dazu die Details in diesem Artikel an.

25.08.2026