ABAP Channels : Messages Push et communication en temps reel

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les ABAP Channels permettent la communication en temps reel entre les applications ABAP et les clients web. Avec les ABAP Messaging Channels (AMC) et les ABAP Push Channels (APC), vous pouvez implementer des messages push et des connexions WebSocket.

Types de canaux

TypeDescription
AMCABAP Messaging Channel - Serveur a serveur
APCABAP Push Channel - Serveur a client (WebSocket)

ABAP Messaging Channels (AMC)

Definir un canal AMC (SAMC)

Transaction SAMC :
1. ID du canal : /ZORDER/UPDATES
2. Type de message : TEXT ou BINARY
3. Extension-ID (optionnel) : Pour les sous-canaux
4. Activer et transporter

Envoyer un message

" Envoyer un simple message texte
TRY.
DATA(lo_producer) = cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP"
i_channel_id = '/zorder/updates' ).
" Message texte
lo_producer->send( i_message = 'Commande 1000000001 a ete mise a jour' ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Message avec Extension-ID

" Message vers un sous-canal specifique
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 }| ). " Par commande
lo_producer->send( i_message = lv_json_message ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Envoyer un message binaire

" Envoyer des donnees XString
DATA: lv_binary TYPE xstring.
" Serialiser les donnees
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 (Recepteur)

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.
" Recevoir le message
DATA(lv_message) = i_message.
" Traitement
CASE lv_message.
WHEN 'REFRESH'.
" Actualiser l'interface...
WHEN OTHERS.
" Parser le JSON...
ENDCASE.
ENDMETHOD.
ENDCLASS.

AMC dans un job en arriere-plan

" Envoyer un message depuis un processus d'arriere-plan
REPORT zr_send_amc_notification.
DATA: lv_order_id TYPE zorder_id.
SELECT-OPTIONS: s_order FOR lv_order_id.
START-OF-SELECTION.
" Traiter les commandes
SELECT * FROM zorders INTO TABLE @DATA(lt_orders)
WHERE order_id IN @s_order.
LOOP AT lt_orders INTO DATA(ls_order).
" Traitement...
" Envoyer la notification
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( |Commande { ls_order-order_id } traitee| ).
CATCH cx_amc_error.
" Journalisation...
ENDTRY.
ENDLOOP.

ABAP Push Channels (APC)

Definir une application APC (SAPC)

Transaction SAPC :
1. Application APC : ZORDER_PUSH
2. Type de connexion : WebSocket
3. Classe Handler : ZCL_ORDER_APC_HANDLER
4. Chemin : /sap/bc/apc/zorder
5. Activer et transporter

Classe Handler APC

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.
" Connexion WebSocket ouverte
mv_context_id = i_context->get_context_id( ).
" Demarrer le consumer AMC pour ce client
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.
" Gestion des erreurs
ENDTRY.
ENDMETHOD.
METHOD if_apc_wsp_extension~on_message.
" Message recu du client
DATA(lv_text) = i_message->get_text( ).
" Parser le JSON
DATA: ls_request TYPE ty_request.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_text
CHANGING data = ls_request ).
" Traiter la requete
CASE ls_request-action.
WHEN 'SUBSCRIBE'.
" Le client s'abonne a certaines mises a jour
handle_subscribe( ls_request-order_id ).
WHEN 'UNSUBSCRIBE'.
handle_unsubscribe( ls_request-order_id ).
ENDCASE.
" Envoyer la reponse
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.
" Connexion WebSocket fermee
" Nettoyage...
ENDMETHOD.
METHOD if_apc_wsp_extension~on_error.
" Gerer l'erreur
DATA(lv_error) = i_error->get_text( ).
ENDMETHOD.
ENDCLASS.

Pont AMC vers APC

" Transmet les messages AMC au client WebSocket
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.
" Transmettre le message AMC au client WebSocket
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 peut-etre deconnecte
ENDTRY.
ENDMETHOD.
ENDCLASS.

Client JavaScript WebSocket

// Client WebSocket cote navigateur
const socket = new WebSocket('wss://server:port/sap/bc/apc/zorder');
// Connexion ouverte
socket.onopen = function(event) {
console.log('WebSocket connecte');
// S'abonner a une commande
socket.send(JSON.stringify({
action: 'SUBSCRIBE',
order_id: '1000000001"
}));
};
// Message recu
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Mise a jour recue:', data);
// Mettre a jour l'interface
updateOrderDisplay(data);
};
// Connexion fermee
socket.onclose = function(event) {
console.log('WebSocket deconnecte');
// Logique de reconnexion...
};
// Erreur
socket.onerror = function(error) {
console.error('Erreur WebSocket:', error);
};

Diffusion a tous les clients

" Message a tous les clients connectes
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.
" Envoyer un message AMC (atteint tous les clients APC)
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP"
i_channel_id = '/zorder/broadcast"
)->send( iv_message ).
CATCH cx_amc_error.
" Gestion des erreurs
ENDTRY.
ENDMETHOD.
ENDCLASS.

Message a un client specifique

" Message a un client WebSocket specifique
METHOD send_to_client.
DATA: lv_context_id TYPE apc_context_id.
" Obtenir l'ID de contexte depuis le registre/table
lv_context_id = get_client_context( iv_user_id ).
TRY.
" Canal AMC direct avec 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 plus connecte
ENDTRY.
ENDMETHOD.

Implementer un Heartbeat

" Messages Ping periodiques
METHOD if_apc_wsp_extension~on_message.
DATA(lv_text) = i_message->get_text( ).
IF lv_text = 'PING'.
" Renvoyer Pong
i_message_manager->send(
cl_apc_wsp_message=>create_text( 'PONG' ) ).
RETURN.
ENDIF.
" Traitement normal des messages...
ENDMETHOD.
" Cote client (JavaScript)
// Heartbeat toutes les 30 secondes
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send('PING');
}
}, 30000);

Gestion des sessions

" Suivre les clients connectes
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.

Connexion WebSocket securisee

" APC avec authentification
METHOD if_apc_wsp_extension~on_start.
" Verifier l'utilisateur
DATA(lv_user) = i_context->get_user( ).
" Verification d'autorisation
AUTHORITY-CHECK OBJECT 'Z_APC_AUTH"
ID 'ACTVT' FIELD '03'.
IF sy-subrc <> 0.
" Rejeter la connexion
i_context->get_message_manager( )->send(
cl_apc_wsp_message=>create_text( '{"error": "Unauthorized"}' ) ).
i_context->close( ).
RETURN.
ENDIF.
" Traitement normal...
ENDMETHOD.

Cas d’utilisation typiques

ApplicationDescription
Mises a jour en directStatut des commandes en temps reel
NotificationsNotifications push
ChatCommunication en temps reel
Tableaux de bordMetriques en direct
CollaborationEdition collaborative

Architecture

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

Bonnes pratiques

  1. Gestion des erreurs : Gestion robuste des erreurs pour les deconnexions
  2. Heartbeat : Maintenir la connexion active
  3. Reconnexion : Reconnexion cote client
  4. Securite : Authentification et autorisation
  5. Mise a l’echelle : Extension-IDs pour les messages cibles
  6. Journalisation : Journaliser les connexions et les messages

Transactions importantes

TransactionDescription
SAMCGerer les canaux AMC
SAPCGerer les applications APC
SMICMMoniteur ICM (WebSocket)

Sujets connexes