ABAP & SAP Modularisatie & OO
Modularisatie & OO

Functiemodules, BAPI's & RFC

Code opdelen en hergebruiken: subroutines (legacy), functiemodules en function groups, BAPI's als officiële API's, RFC-varianten en het BAPIRET2-foutafhandelingspatroon.

Op deze pagina

01Subroutines: PERFORM & FORM (legacy)

Subroutines zijn de oudste vorm van modularisatie in ABAP. Nieuwe code hoort ze niet meer te gebruiken (schrijf methoden), maar je komt ze in vrijwel elk bestaand programma tegen — dus je moet ze kunnen lezen.

PERFORM bereken_totaal
  USING    lv_aantal lv_prijs
  CHANGING lv_totaal.

FORM bereken_totaal
  USING    iv_aantal TYPE i
           iv_prijs  TYPE p
  CHANGING cv_totaal TYPE p.
  cv_totaal = iv_aantal * iv_prijs.
ENDFORM.

02Functiemodules & function groups

Een functiemodule (FM) is een globaal aanroepbare procedure, beheerd in transactie SE37. FM's leven altijd in een function group (SE80/SE37), die de gedeelde globale data en includes bevat. Een function group wordt als geheel in het geheugen geladen zodra je één van zijn FM's aanroept — en blijft geladen voor de rest van de sessie (dus globale data blijft bewaard tussen aanroepen!).

CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
  EXPORTING
    input  = lv_matnr_ruw
  IMPORTING
    output = lv_matnr.

Parametersoorten

SoortRichting (vanuit de aanroeper)Opmerking
EXPORTINGJij geeft data aan de FMIn de FM-definitie heet dit IMPORTING — de richting is altijd vanuit het eigen perspectief.
IMPORTINGJij krijgt data terugOptioneel weg te laten als je het resultaat niet nodig hebt.
CHANGINGBeide richtingenIn/uitvoer.
TABLESInterne tabellen, beide richtingenVerouderd maar alomtegenwoordig (o.a. in BAPI's).
EXCEPTIONSFoutcodesKlassieke, niet-class-based fouten; zie hieronder.

Klassieke exceptions afhandelen

CALL FUNCTION 'ENQUEUE_EZMIJN_LOCK'
  EXPORTING
    matnr          = lv_matnr
  EXCEPTIONS
    foreign_lock   = 1
    system_failure = 2
    OTHERS         = 3.
CASE sy-subrc.
  WHEN 0.  " ok
  WHEN 1.  MESSAGE e001(zmm) WITH lv_matnr.  " al vergrendeld
  WHEN OTHERS. " onverwacht
ENDCASE.

Je koppelt elke exception aan een getal; na de aanroep staat dat getal in sy-subrc. Vergeet je de EXCEPTIONS-lijst en de FM gooit toch een exception, dan volgt een runtime-dump. Moderne code gebruikt class-based exceptions.

03BAPI's: de officiële API van SAP

Een BAPI (Business Application Programming Interface) is een door SAP vrijgegeven, stabiele, RFC-enabled functiemodule om businessobjecten te lezen of te muteren. Naamconventie: BAPI_<object>_<werkwoord>, bijvoorbeeld BAPI_SALESORDER_CREATEFROMDAT2, BAPI_MATERIAL_SAVEDATA, BAPI_USER_GET_DETAIL. Overzicht per module: zie Tabellen & BAPI's per module.

Het vaste patroon

DATA lt_return TYPE STANDARD TABLE OF bapiret2.

CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'
  EXPORTING
    order_header_in  = ls_header
    order_header_inx = ls_headerx      " X-structuur: welke velden tellen
  IMPORTING
    salesdocument    = lv_vbeln
  TABLES
    return           = lt_return
    order_items_in   = lt_items
    order_items_inx  = lt_itemsx
    order_partners   = lt_partners.

" Fouten checken vóór de commit
IF line_exists( lt_return[ type = 'E' ] )
OR line_exists( lt_return[ type = 'A' ] ).
  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
    EXPORTING wait = abap_true.   " wacht tot de update-task klaar is
ENDIF.
Drie ijzeren regels — ① Een BAPI doet zelf geen COMMIT: jij roept altijd expliciet BAPI_TRANSACTION_COMMIT (of ROLLBACK) aan. ② Controleer altijd de RETURN-tabel op type E (error) en A (abort) vóór je commit. ③ Gebruik wait = abap_true als je direct daarna de aangemaakte data wilt lezen — anders is de asynchrone update mogelijk nog niet klaar.

X-structuren (update-vlaggen)

Bij wijzigings-BAPI's (bijv. BAPI_SALESORDER_CHANGE) geef je náást de datastructuur een gelijknamige X-structuur mee. Elk veld daarin krijgt 'X' als het corresponderende dataveld daadwerkelijk gewijzigd moet worden — velden zonder X worden genegeerd. Zo kan de BAPI onderscheid maken tussen "leegmaken" en "niet aanraken".

ls_header-purch_no_c  = 'PO-4711'.
ls_headerx-purch_no_c = 'X'.
ls_headerx-updateflag = 'U'.   " U = update (bij CHANGE-BAPI's)

04BAPIRET2: de standaard-retourstructuur

Vrijwel elke BAPI retourneert meldingen in tabelvorm met regeltype BAPIRET2. Leer deze structuur uit je hoofd — je gebruikt hem dagelijks.

VeldBetekenis
TYPES succes, I info, W waarschuwing, E fout, A abort. Zie MESSAGE-types.
IDBerichtklasse (SE91), bijv. V1.
NUMBERBerichtnummer binnen de klasse, bijv. 045.
MESSAGEDe volledig samengestelde, vertaalde tekst.
MESSAGE_V1..V4De vier variabele delen (&-plaatshouders).
PARAMETER / ROW / FIELDOp welk invoerveld/regel de melding slaat.
LOOP AT lt_return ASSIGNING FIELD-SYMBOL(<ls_ret>)
     WHERE type CA 'EA'.
  MESSAGE ID <ls_ret>-id TYPE 'S' NUMBER <ls_ret>-number
    WITH <ls_ret>-message_v1 <ls_ret>-message_v2
         <ls_ret>-message_v3 <ls_ret>-message_v4
    DISPLAY LIKE 'E'.
ENDLOOP.

De truc TYPE 'S' ... DISPLAY LIKE 'E' toont de melding als fout (rood) zonder de programmastroom hard af te breken.

05RFC: aanroepen over systeemgrenzen

Remote Function Call is SAP's protocol om functiemodules in een ander systeem aan te roepen. Bestemmingen (destinations) beheer je in transactie SM59.

VariantSyntaxGedrag
Synchroon (sRFC)CALL FUNCTION 'Z_X' DESTINATION 'SYSB'Wacht op het antwoord. Standaard.
Asynchroon (aRFC)CALL FUNCTION ... STARTING NEW TASK 'T1'Loopt parallel; resultaat optioneel via RECEIVE RESULTS in een callback. Ook lokaal bruikbaar voor parallellisatie.
Transactioneel (tRFC)CALL FUNCTION ... IN BACKGROUND TASKGegarandeerd precies één keer uitgevoerd, bij de eerstvolgende COMMIT WORK. Monitoring: SM58.
Gequeued (qRFC)tRFC + queuenaamAls tRFC, maar met gegarandeerde volgorde binnen de queue. Monitoring: SMQ1/SMQ2.
CALL FUNCTION 'RFC_READ_TABLE' DESTINATION 'ERPCLNT100'
  EXPORTING  query_table = 'T001'
  TABLES     data        = lt_data
  EXCEPTIONS
    communication_failure = 1 MESSAGE lv_msg
    system_failure        = 2 MESSAGE lv_msg.