ABAP Channels: Mensajes Push y Comunicación en Tiempo Real

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

ABAP Channels permiten la comunicación en tiempo real entre aplicaciones ABAP y clientes web. Con ABAP Messaging Channels (AMC) y ABAP Push Channels (APC) se pueden implementar mensajes push y conexiones WebSocket.

Tipos de Channels

TipoDescripción
AMCABAP Messaging Channel - Servidor a servidor
APCABAP Push Channel - Servidor a cliente (WebSocket)

ABAP Messaging Channels (AMC)

Definir canal AMC (SAMC)

Transacción SAMC:
1. ID de canal: /ZORDER/UPDATES
2. Tipo de mensaje: TEXT o BINARY
3. Extension-ID (opcional): Para sub-canales
4. Activar y transportar

Enviar mensaje

" Enviar mensaje de texto simple
TRY.
DATA(lo_producer) = cl_amc_channel_manager=>create_message_producer(
i_application_id = 'ZORDER_APP'
i_channel_id = '/zorder/updates' ).
" Mensaje de texto
lo_producer->send( i_message = 'Pedido 1000000001 actualizado' ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Mensaje con Extension-ID

" Mensaje a sub-canal específico
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 }| ). " Por pedido
lo_producer->send( i_message = lv_json_message ).
CATCH cx_amc_error INTO DATA(lx_error).
MESSAGE lx_error->get_text( ) TYPE 'E'.
ENDTRY.

Enviar mensaje binario

" Enviar datos XString
DATA: lv_binary TYPE xstring.
" Serializar datos
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 (Receptor)

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.
" Recibir mensaje
DATA(lv_message) = i_message.
" Procesamiento
CASE lv_message.
WHEN 'REFRESH'.
" Actualizar UI...
WHEN OTHERS.
" Parsear JSON...
ENDCASE.
ENDMETHOD.
ENDCLASS.

AMC en Job de Fondo

" Enviar mensaje desde proceso de fondo
REPORT zr_send_amc_notification.
DATA: lv_order_id TYPE zorder_id.
SELECT-OPTIONS: s_order FOR lv_order_id.
START-OF-SELECTION.
" Procesar pedidos
SELECT * FROM zorders INTO TABLE @DATA(lt_orders)
WHERE order_id IN @s_order.
LOOP AT lt_orders INTO DATA(ls_order).
" Procesamiento...
" Enviar notificación
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( |Pedido { ls_order-order_id } procesado| ).
CATCH cx_amc_error.
" Logging...
ENDTRY.
ENDLOOP.

ABAP Push Channels (APC)

Definir aplicación APC (SAPC)

Transacción SAPC:
1. Aplicación APC: ZORDER_PUSH
2. Tipo de conexión: WebSocket
3. Clase Handler: ZCL_ORDER_APC_HANDLER
4. Ruta: /sap/bc/apc/zorder
5. Activar y transportar

Clase 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.
" Conexión WebSocket abierta
mv_context_id = i_context->get_context_id( ).
" Iniciar AMC-Consumer para este cliente
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.
" Manejo de errores
ENDTRY.
ENDMETHOD.
METHOD if_apc_wsp_extension~on_message.
" Mensaje recibido del cliente
DATA(lv_text) = i_message->get_text( ).
" Parsear JSON
DATA: ls_request TYPE ty_request.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_text
CHANGING data = ls_request ).
" Procesar request
CASE ls_request-action.
WHEN 'SUBSCRIBE'.
" Cliente suscribe a actualizaciones específicas
handle_subscribe( ls_request-order_id ).
WHEN 'UNSUBSCRIBE'.
handle_unsubscribe( ls_request-order_id ).
ENDCASE.
" Enviar respuesta
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.
" Conexión WebSocket cerrada
" Limpieza...
ENDMETHOD.
METHOD if_apc_wsp_extension~on_error.
" Manejar error
DATA(lv_error) = i_error->get_text( ).
ENDMETHOD.
ENDCLASS.

Bridge AMC a APC

" Reenvía mensajes AMC al cliente 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.
" Reenviar mensaje AMC al cliente 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.
" Cliente posiblemente desconectado
ENDTRY.
ENDMETHOD.
ENDCLASS.

Cliente WebSocket JavaScript

// Cliente WebSocket del lado del navegador
const socket = new WebSocket('wss://server:port/sap/bc/apc/zorder');
// Conexión abierta
socket.onopen = function(event) {
console.log('WebSocket conectado');
// Suscribirse a pedido
socket.send(JSON.stringify({
action: 'SUBSCRIBE',
order_id: '1000000001'
}));
};
// Mensaje recibido
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Actualización recibida:', data);
// Actualizar UI
updateOrderDisplay(data);
};
// Conexión cerrada
socket.onclose = function(event) {
console.log('WebSocket desconectado');
// Lógica de reconexión...
};
// Error
socket.onerror = function(error) {
console.error('Error WebSocket:', error);
};

Broadcast a todos los clientes

" Mensaje a todos los clientes conectados
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.
" Enviar mensaje AMC (alcanza todos los clientes 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.
" Manejo de errores
ENDTRY.
ENDMETHOD.
ENDCLASS.

Mensaje a cliente específico

" Mensaje a cliente WebSocket específico
METHOD send_to_client.
DATA: lv_context_id TYPE apc_context_id.
" Obtener Context-ID del registro/tabla
lv_context_id = get_client_context( iv_user_id ).
TRY.
" Canal AMC directo con 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.
" Cliente ya no conectado
ENDTRY.
ENDMETHOD.

Implementar Heartbeat

" Mensajes Ping periódicos
METHOD if_apc_wsp_extension~on_message.
DATA(lv_text) = i_message->get_text( ).
IF lv_text = 'PING'.
" Enviar Pong
i_message_manager->send(
cl_apc_wsp_message=>create_text( 'PONG' ) ).
RETURN.
ENDIF.
" Procesamiento normal de mensajes...
ENDMETHOD.
" Del lado del cliente (JavaScript)
// Heartbeat cada 30 segundos
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send('PING');
}
}, 30000);

Gestión de sesiones

" Rastrear clientes conectados
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.

Conexión WebSocket segura

" APC con autenticación
METHOD if_apc_wsp_extension~on_start.
" Verificar usuario
DATA(lv_user) = i_context->get_user( ).
" Verificación de autorización
AUTHORITY-CHECK OBJECT 'Z_APC_AUTH'
ID 'ACTVT' FIELD '03'.
IF sy-subrc <> 0.
" Rechazar conexión
i_context->get_message_manager( )->send(
cl_apc_wsp_message=>create_text( '{"error": "Unauthorized"}' ) ).
i_context->close( ).
RETURN.
ENDIF.
" Procesamiento normal...
ENDMETHOD.

Casos de uso típicos

AplicaciónDescripción
Actualizaciones en vivoEstado de pedidos en tiempo real
NotificacionesNotificaciones push
ChatComunicación en tiempo real
DashboardsMétricas en vivo
ColaboraciónEdición colaborativa

Arquitectura

┌─────────────────┐ ┌─────────────────┐
│ Cliente Web │ │ Cliente Web │
│ (JavaScript) │ │ (JavaScript) │
└────────┬────────┘ └────────┬────────┘
│ WebSocket │ WebSocket
│ │
▼ ▼
┌─────────────────────────────────────────┐
│ ABAP Push Channel │
│ (APC Handler) │
└────────────────────┬────────────────────┘
┌─────────────────────────────────────────┐
│ ABAP Messaging Channel │
│ (AMC Broker) │
└────────────────────┬────────────────────┘
┌─────────────────────────────────────────┐
│ Lógica Backend ABAP │
│ (Jobs de fondo, BAPIs, etc.) │
└─────────────────────────────────────────┘

Mejores prácticas

  1. Manejo de errores: Manejo robusto de desconexiones
  2. Heartbeat: Mantener conexión activa
  3. Reconexión: Reconexión del lado del cliente
  4. Seguridad: Autenticación y autorización
  5. Escalabilidad: Extension-IDs para mensajes dirigidos
  6. Logging: Registrar conexiones y mensajes

Transacciones importantes

TransacciónDescripción
SAMCGestionar canales AMC
SAPCGestionar aplicaciones APC
SMICMMonitor ICM (WebSocket)

Temas relacionados