ABAP Channels: Push-Nachrichten und Echtzeit-Kommunikation

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

ABAP Channels ermöglichen Echtzeit-Kommunikation zwischen ABAP-Anwendungen und Web-Clients. Mit ABAP Messaging Channels (AMC) und ABAP Push Channels (APC) können Push-Nachrichten und WebSocket-Verbindungen implementiert werden.

Channel-Typen

TypBeschreibung
AMCABAP Messaging Channel - Server-zu-Server
APCABAP Push Channel - Server-zu-Client (WebSocket)

ABAP Messaging Channels (AMC)

AMC-Kanal definieren (SAMC)

Transaktion SAMC:
1. Kanal-ID: /ZORDER/UPDATES
2. Nachrichtentyp: TEXT oder BINARY
3. Extension-ID (optional): Für Sub-Channels
4. Aktivieren und transportieren

Nachricht senden

" Einfache Textnachricht senden
TRY.
DATA(lo_producer) = cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates' ).
" Text-Nachricht
lo_producer->send( i_message = 'Bestellung 1000000001 wurde aktualisiert' ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Nachricht mit Extension-ID

" Nachricht an spezifischen Sub-Channel
TRY.
DATA(lo_producer) = cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates'
i_extension_id = |ORDER_{ lv_order_id }| ). " Pro Bestellung
lo_producer->send( i_message = lv_json_message ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Binäre Nachricht senden

" XString-Daten senden
DATA: lv_binary TYPE xstring.
" Daten serialisieren
CALL TRANSFORMATION id
SOURCE data = ls_order_data
RESULT XML lv_binary.
TRY.
DATA(lo_producer) = cl_amc_channel_manager=>create_message_producer_bin(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/binary' ).
lo_producer->send( i_message = lv_binary ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

AMC-Consumer (Empfänger)

CLASS zcl_order_amc_consumer DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_amc_message_receiver.
METHODS start_listening.
ENDCLASS.
CLASS zcl_order_amc_consumer IMPLEMENTATION.
METHOD start_listening.
TRY.
cl_amc_channel_manager=>create_message_consumer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates'
)->start_message_delivery( i_receiver = me ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.
ENDMETHOD.
METHOD if_amc_message_receiver~receive.
" Nachricht empfangen
DATA(lv_message) = i_message.
" Verarbeitung
CASE lv_message.
WHEN 'REFRESH'.
" UI aktualisieren...
WHEN OTHERS.
" JSON parsen...
ENDCASE.
ENDMETHOD.
ENDCLASS.

AMC im Background Job

" Nachricht aus Hintergrundprozess senden
REPORT zr_send_amc_notification.
DATA: lv_order_id TYPE zorder_id.
SELECT-OPTIONS: s_order FOR lv_order_id.
START-OF-SELECTION.
" Bestellungen verarbeiten
SELECT * FROM zorders INTO TABLE @DATA(lt_orders)
WHERE order_id IN @s_order.
LOOP AT lt_orders INTO DATA(ls_order).
" Verarbeitung...
" Benachrichtigung senden
TRY.
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates'
i_extension_id = |ORDER_{ ls_order-order_id }|
)->send( |Bestellung { ls_order-order_id } verarbeitet| ).
CATCH cx_amc_error.
" Logging...
ENDTRY.
ENDLOOP.

ABAP Push Channels (APC)

APC-Anwendung definieren (SAPC)

Transaktion SAPC:
1. APC-Anwendung: ZORDER_PUSH
2. Verbindungsart: WebSocket
3. Handler-Klasse: ZCL_ORDER_APC_HANDLER
4. Pfad: /sap/bc/apc/zorder
5. Aktivieren und transportieren

APC Handler-Klasse

CLASS zcl_order_apc_handler DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_apc_wsp_extension.
PRIVATE SECTION.
DATA: mv_context_id TYPE apc_context_id.
ENDCLASS.
CLASS zcl_order_apc_handler IMPLEMENTATION.
METHOD if_apc_wsp_extension~on_start.
" WebSocket-Verbindung geöffnet
mv_context_id = i_context->get_context_id( ).
" AMC-Consumer für diesen Client starten
TRY.
cl_amc_channel_manager=>create_message_consumer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates'
)->start_message_delivery(
i_receiver = NEW zcl_apc_amc_bridge( i_context ) ).
CATCH cx_amc_error.
" Fehlerbehandlung
ENDTRY.
ENDMETHOD.
METHOD if_apc_wsp_extension~on_message.
" Nachricht vom Client empfangen
DATA(lv_text) = i_message->get_text( ).
" JSON parsen
DATA: ls_request TYPE ty_request.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_text
CHANGING data = ls_request ).
" Request verarbeiten
CASE ls_request-action.
WHEN 'SUBSCRIBE'.
" Client abonniert bestimmte Updates
handle_subscribe( ls_request-order_id ).
WHEN 'UNSUBSCRIBE'.
handle_unsubscribe( ls_request-order_id ).
ENDCASE.
" Antwort senden
DATA(lv_response) = /ui2/cl_json=>serialize(
data = VALUE ty_response( status = 'OK' ) ).
i_message_manager->send( i_message = cl_apc_wsp_message=>create_text( lv_response ) ).
ENDMETHOD.
METHOD if_apc_wsp_extension~on_close.
" WebSocket-Verbindung geschlossen
" Aufräumen...
ENDMETHOD.
METHOD if_apc_wsp_extension~on_error.
" Fehler behandeln
DATA(lv_error) = i_error->get_text( ).
ENDMETHOD.
ENDCLASS.

AMC-zu-APC Bridge

" Leitet AMC-Nachrichten an WebSocket-Client weiter
CLASS zcl_apc_amc_bridge DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_amc_message_receiver.
METHODS constructor
IMPORTING io_apc_context TYPE REF TO if_apc_wsp_context.
PRIVATE SECTION.
DATA: mo_context TYPE REF TO if_apc_wsp_context.
ENDCLASS.
CLASS zcl_apc_amc_bridge IMPLEMENTATION.
METHOD constructor.
mo_context = io_apc_context.
ENDMETHOD.
METHOD if_amc_message_receiver~receive.
" AMC-Nachricht an WebSocket-Client weiterleiten
TRY.
DATA(lo_message) = cl_apc_wsp_message=>create_text( i_message ).
mo_context->get_message_manager( )->send( lo_message ).
CATCH cx_apc_error.
" Client möglicherweise disconnected
ENDTRY.
ENDMETHOD.
ENDCLASS.

JavaScript WebSocket-Client

// Browser-seitiger WebSocket-Client
const socket = new WebSocket('wss://server:port/sap/bc/apc/zorder');
// Verbindung geöffnet
socket.onopen = function(event) {
console.log('WebSocket verbunden');
// Bestellung abonnieren
socket.send(JSON.stringify({
action: 'SUBSCRIBE',
order_id: '1000000001'
}));
};
// Nachricht empfangen
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Update erhalten:', data);
// UI aktualisieren
updateOrderDisplay(data);
};
// Verbindung geschlossen
socket.onclose = function(event) {
console.log('WebSocket getrennt');
// Reconnect-Logik...
};
// Fehler
socket.onerror = function(error) {
console.error('WebSocket Fehler:', error);
};

Broadcast an alle Clients

" Nachricht an alle verbundenen Clients
CLASS zcl_order_notifier DEFINITION.
PUBLIC SECTION.
CLASS-METHODS notify_all
IMPORTING iv_message TYPE string.
ENDCLASS.
CLASS zcl_order_notifier IMPLEMENTATION.
METHOD notify_all.
TRY.
" AMC-Nachricht senden (erreicht alle APC-Clients)
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/broadcast'
)->send( iv_message ).
CATCH cx_amc_error.
" Fehlerbehandlung
ENDTRY.
ENDMETHOD.
ENDCLASS.

Nachricht an spezifischen Client

" Nachricht an bestimmten WebSocket-Client
METHOD send_to_client.
DATA: lv_context_id TYPE apc_context_id.
" Context-ID aus Registry/Tabelle holen
lv_context_id = get_client_context( iv_user_id ).
TRY.
" Direkter AMC-Kanal mit Extension
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/direct'
i_extension_id = lv_context_id
)->send( iv_message ).
CATCH cx_amc_error.
" Client nicht mehr verbunden
ENDTRY.
ENDMETHOD.

Heartbeat implementieren

" Periodische Ping-Nachrichten
METHOD if_apc_wsp_extension~on_message.
DATA(lv_text) = i_message->get_text( ).
IF lv_text = 'PING'.
" Pong zurücksenden
i_message_manager->send(
cl_apc_wsp_message=>create_text( 'PONG' ) ).
RETURN.
ENDIF.
" Normale Nachrichtenverarbeitung...
ENDMETHOD.
" Client-seitig (JavaScript)
// Heartbeat alle 30 Sekunden
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send('PING');
}
}, 30000);

Session-Management

" Verbundene Clients tracken
CLASS zcl_apc_session_manager DEFINITION.
PUBLIC SECTION.
CLASS-DATA: gt_sessions TYPE TABLE OF ty_session.
CLASS-METHODS register
IMPORTING iv_context_id TYPE apc_context_id
iv_user_id TYPE sy-uname.
CLASS-METHODS unregister
IMPORTING iv_context_id TYPE apc_context_id.
CLASS-METHODS get_sessions_for_user
IMPORTING iv_user_id TYPE sy-uname
RETURNING VALUE(rt_sessions) TYPE ty_session_tab.
ENDCLASS.
CLASS zcl_apc_session_manager IMPLEMENTATION.
METHOD register.
APPEND VALUE #(
context_id = iv_context_id
user_id = iv_user_id
timestamp = sy-datum && sy-uzeit
) TO gt_sessions.
ENDMETHOD.
METHOD unregister.
DELETE gt_sessions WHERE context_id = iv_context_id.
ENDMETHOD.
METHOD get_sessions_for_user.
rt_sessions = VALUE #( FOR session IN gt_sessions
WHERE ( user_id = iv_user_id ) ( session ) ).
ENDMETHOD.
ENDCLASS.

Sichere WebSocket-Verbindung

" APC mit Authentifizierung
METHOD if_apc_wsp_extension~on_start.
" Benutzer prüfen
DATA(lv_user) = i_context->get_user( ).
" Berechtigungsprüfung
AUTHORITY-CHECK OBJECT 'Z_APC_AUTH'
ID 'ACTVT' FIELD '03'.
IF sy-subrc <> 0.
" Verbindung ablehnen
i_context->get_message_manager( )->send(
cl_apc_wsp_message=>create_text( '{"error": "Unauthorized"}' ) ).
i_context->close( ).
RETURN.
ENDIF.
" Normale Verarbeitung...
ENDMETHOD.

Typische Anwendungsfälle

AnwendungBeschreibung
Live-UpdatesBestellstatus in Echtzeit
BenachrichtigungenPush-Notifications
ChatEchtzeit-Kommunikation
DashboardsLive-Metriken
CollaborationGemeinsames Bearbeiten

Architektur

┌─────────────────┐ ┌─────────────────┐
│ Web-Client │ │ Web-Client │
│ (JavaScript) │ │ (JavaScript) │
└────────┬────────┘ └────────┬────────┘
│ WebSocket │ WebSocket
│ │
▼ ▼
┌─────────────────────────────────────────┐
│ ABAP Push Channel │
│ (APC Handler) │
└────────────────────┬────────────────────┘
┌─────────────────────────────────────────┐
│ ABAP Messaging Channel │
│ (AMC Broker) │
└────────────────────┬────────────────────┘
┌─────────────────────────────────────────┐
│ ABAP Backend Logic │
│ (Background Jobs, BAPIs, etc.) │
└─────────────────────────────────────────┘

Best Practices

  1. Error Handling: Robuste Fehlerbehandlung für Disconnects
  2. Heartbeat: Verbindung aktiv halten
  3. Reconnect: Client-seitige Wiederverbindung
  4. Security: Authentifizierung und Autorisierung
  5. Skalierung: Extension-IDs für gezielte Nachrichten
  6. Logging: Verbindungen und Nachrichten protokollieren

Wichtige Transaktionen

TransaktionBeschreibung
SAMCAMC-Kanäle pflegen
SAPCAPC-Anwendungen pflegen
SMICMICM-Monitor (WebSocket)

Verwandte Themen