Ir al contenido
Programación ABAP

ABAP RESTful Application Programming Model (RAP)

El modelo de SAP para crear aplicaciones Fiori y APIs OData con ABAP. Defines datos, comportamiento y servicio; el framework hace el resto.

Apartados
12
Revisado
Octubre de 2026
Fuentes
2 enlaces

Qué es RAP

RAP sustituye a los antiguos modelos de programación (BOPF, SEGW y Gateway clásico). Un objeto de negocio RAP se construye en capas, de la tabla a la aplicación:

ConsumoApp Fiori elementsOData V4 - UIWeb APIOData V4 - APIOtros programasEMLServicioService bindingprotocoloService definitionqué se exponeProyecciones C_CDS y BDEFObjeto de negocioVistas CDS R_modelo de datosBehavior definitionqué se puede hacerClase ZBP_lógica en ABAP
Las tres capas de RAP. Abajo, el objeto de negocio: datos y comportamiento. En medio, el servicio: qué se expone y con qué protocolo. Arriba, quién lo consume.

Tu primera app RAP en 5 minutos

ADT trae un generador que crea todas las capas a partir de una tabla. Es la forma más rápida de empezar y de ver cómo encajan las piezas. Funciona en Eclipse y en VS Code, con BTP ABAP environment, S/4HANA Cloud o S/4HANA 2022 y posteriores.

Tabla (ADT)
@EndUserText.label : 'Viajes'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zviaje {
  key client   : abap.clnt not null;
  key viaje_id : abap.numc(8) not null;
  cliente_id   : abap.char(10);
  fecha_inicio : abap.dats;
  @Semantics.amount.currencyCode : 'zviaje.moneda'
  importe      : abap.curr(15,2);
  moneda       : abap.cuky;
  estado       : abap.char(1);
  cambiado_en  : abp_lastchange_tstmpl;
}
  1. Crea un paquete (en BTP, dentro de ZLOCAL si es solo para practicar) y dentro la tabla ZVIAJE con el código de arriba. Actívala con Ctrl+F3.
  2. Pulsa con el botón derecho sobre la tabla y elige Generate ABAP Repository Objects…
  3. Selecciona el generador OData UI Service (en algunas versiones, ABAP RESTful Application Programming Model: UI Service).
  4. Revisa los nombres que propone: vistas ZR_ y ZC_, behavior definitions, clase ZBP_, service definition y binding. Pulsa Next y Finish.
  5. Abre el service binding generado, pulsa Publish, elige la entidad y pulsa Preview. Ya tienes una app Fiori elements con lista, detalle, creación y borrado.

El generador crea la app con borradores (draft) y numeración automática. Lee el código que genera: es el mejor ejemplo de cómo se escribe un RAP completo.

1. El modelo de datos

CDS
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Viaje'
define root view entity ZR_Viaje
  as select from zviaje
{
  key viaje_id     as ViajeId,
      cliente_id   as ClienteId,
      fecha_inicio as FechaInicio,
      @Semantics.amount.currencyCode: 'Moneda'
      importe      as Importe,
      moneda       as Moneda,
      estado       as Estado,
      @Semantics.systemDateTime.lastChangedAt: true
      cambiado_en  as CambiadoEn
}

2. El comportamiento

La behavior definition dice qué se puede hacer con el objeto: crear, modificar, borrar, acciones y validaciones. En el escenario managed, RAP guarda los datos por ti.

BDEF
managed implementation in class zbp_r_viaje unique;
strict ( 2 );

define behavior for ZR_Viaje alias Viaje
persistent table zviaje
lock master
authorization master ( instance )
etag master CambiadoEn
{
  create;
  update;
  delete;
  field ( readonly : update ) ViajeId;
  action aceptar result [1] $self;
  validation validarFechas on save { create; field FechaInicio; }

  mapping for zviaje
  {
    ViajeId     = viaje_id;
    ClienteId   = cliente_id;
    FechaInicio = fecha_inicio;
    Importe     = importe;
    Moneda      = moneda;
    Estado      = estado;
    CambiadoEn  = cambiado_en;
  }
}

La acción se programa en la clase de comportamiento con EML:

ABAP
METHOD aceptar.
  MODIFY ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje
    UPDATE FIELDS ( Estado )
    WITH VALUE #( FOR ls_key IN keys
                  ( %tky = ls_key-%tky Estado = 'A' ) ).

  READ ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje ALL FIELDS WITH CORRESPONDING #( keys )
    RESULT DATA(lt_viajes).

  result = VALUE #( FOR ls_v IN lt_viajes
                    ( %tky = ls_v-%tky %param = ls_v ) ).
ENDMETHOD.

3. El servicio

CDS (proyección)
@Metadata.allowExtensions: true
@EndUserText.label: 'Viaje (proyección)'
define root view entity ZC_Viaje
  provider contract transactional_query
  as projection on ZR_Viaje
{
  key ViajeId,
      ClienteId,
      FechaInicio,
      Importe,
      Moneda,
      Estado,
      CambiadoEn
}
Service definition
@EndUserText.label: 'Servicio de viajes'
define service ZUI_VIAJE {
  expose ZC_Viaje as Viaje;
}
  1. Crea también la proyección del comportamiento (projection; con use create; use update; use delete; use action aceptar;).
  2. Crea un service binding de tipo OData V4 - UI sobre ZUI_VIAJE.
  3. Pulsa Publish y después Preview: verás la app Fiori elements funcionando.

Usar el objeto desde ABAP con EML

EML (Entity Manipulation Language) lee y modifica objetos RAP desde cualquier programa respetando sus validaciones y bloqueos.

ABAP
READ ENTITIES OF zr_viaje
  ENTITY Viaje
  FIELDS ( Estado Importe ) WITH VALUE #( ( ViajeId = '00000001' ) )
  RESULT DATA(lt_viajes).

MODIFY ENTITIES OF zr_viaje
  ENTITY Viaje
  UPDATE FIELDS ( Estado )
  WITH VALUE #( ( ViajeId = '00000001' Estado = 'A' ) )
  FAILED DATA(ls_failed)
  REPORTED DATA(ls_reported).

COMMIT ENTITIES.

Managed, unmanaged y borradores

EscenarioQuién guarda los datosCuándo usarlo
ManagedRAPAplicaciones nuevas: la opción por defecto
Managed con guardado propioRAP, salvo el guardado finalCuando hay que grabar con una BAPI o API existente
UnmanagedTu códigoReutilizar lógica antigua que ya hace todo
Con borrador (draft)RAP guarda versiones intermediasFormularios largos que el usuario completa en varias veces

Qué pasa al guardar: interacción y guardado

Una transacción RAP tiene dos fases. En la fase de interacción el usuario o el programa modifica los datos en un búfer en memoria. Al hacer COMMIT ENTITIES empieza la secuencia de guardado: se completan y validan los datos y, si todo está bien, se graban en la base de datos.

Fase de interacciónMODIFY y READ ENTITIESAccionesDeterminaciones «on modify»Bloqueos y autorizacionesControl de funciones (features)COMMITENTITIESSecuencia de guardadofinalizedeterminaciones «on save»check_before_savevalidacionesadjust_numbersnumeración tardíasavegrabar en la base de datoscleanupvaciar el búfer
Si una validación falla en check_before_save, no se graba nada y los mensajes vuelven al usuario.

En la secuencia de guardado no se puede llamar a COMMIT WORK ni a ROLLBACK WORK: de eso se encarga RAP.

Determinaciones y validaciones

Una determinación rellena o calcula datos automáticamente. Una validación comprueba los datos antes de guardarlos y, si algo falla, devuelve un mensaje. Se declaran en la behavior definition:

BDEF
  determination fijarEstado on modify { create; }
  validation validarFechas on save { create; field FechaInicio; }

Esta determinación pone el estado «O» (abierto) a los viajes nuevos que no tienen estado:

ABAP
METHOD fijarEstado.
  READ ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje FIELDS ( Estado ) WITH CORRESPONDING #( keys )
    RESULT DATA(lt_viajes).

  DELETE lt_viajes WHERE Estado IS NOT INITIAL.
  CHECK lt_viajes IS NOT INITIAL.

  MODIFY ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje UPDATE FIELDS ( Estado )
    WITH VALUE #( FOR ls_v IN lt_viajes
                  ( %tky = ls_v-%tky Estado = 'O' ) ).
ENDMETHOD.

Y esta validación rechaza viajes con fecha de inicio pasada. failed indica qué registros fallan y reported lleva el mensaje, asociado al campo para que Fiori lo marque en rojo:

ABAP
METHOD validarFechas.
  READ ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje FIELDS ( FechaInicio ) WITH CORRESPONDING #( keys )
    RESULT DATA(lt_viajes).

  DATA(lv_hoy) = cl_abap_context_info=>get_system_date( ).

  LOOP AT lt_viajes INTO DATA(ls_viaje) WHERE FechaInicio < lv_hoy.
    APPEND VALUE #( %tky = ls_viaje-%tky ) TO failed-viaje.
    APPEND VALUE #( %tky = ls_viaje-%tky
                    %msg = new_message_with_text(
                             severity = if_abap_behv_message=>severity-error
                             text     = 'La fecha de inicio no puede ser pasada' )
                    %element-FechaInicio = if_abap_behv=>mk-on )
      TO reported-viaje.
  ENDLOOP.
ENDMETHOD.

Activar o desactivar acciones según los datos

Con el control de funciones (feature control) decides en cada registro qué botones y campos están disponibles. Por ejemplo, que no se pueda aceptar un viaje ya aceptado:

BDEF
  action ( features : instance ) aceptar result [1] $self;
ABAP
METHOD get_instance_features.
  READ ENTITIES OF zr_viaje IN LOCAL MODE
    ENTITY Viaje FIELDS ( Estado ) WITH CORRESPONDING #( keys )
    RESULT DATA(lt_viajes).

  result = VALUE #( FOR ls_v IN lt_viajes
    ( %tky            = ls_v-%tky
      %action-aceptar = COND #( WHEN ls_v-Estado = 'A'
                                THEN if_abap_behv=>fc-o-disabled
                                ELSE if_abap_behv=>fc-o-enabled ) ) ).
ENDMETHOD.

Fiori elements lee este resultado y desactiva el botón Aceptar en los viajes que ya lo están, sin tocar la interfaz.

Borradores (draft)

Con borradores, lo que el usuario va escribiendo se guarda en una tabla aparte. Puede cerrar el navegador y seguir más tarde, y otro usuario no puede editar el mismo registro a la vez. Basta con declararlo:

BDEF
managed implementation in class zbp_r_viaje unique;
strict ( 2 );
with draft;

define behavior for ZR_Viaje alias Viaje
persistent table zviaje
draft table zviaje_d
lock master total etag CambiadoEn
authorization master ( instance )
etag master CambiadoEn
{
  create;
  update;
  delete;

  draft action Edit;
  draft action Activate optimized;
  draft action Discard;
  draft action Resume;
  draft determine action Prepare { validation validarFechas; }
}
  • ADT crea la tabla de borradores ZVIAJE_D con un asistente rápido (Ctrl+1 sobre el nombre).
  • Prepare ejecuta las validaciones antes de activar, para avisar al usuario antes de guardar.
  • Fiori elements muestra solo los botones Editar, Guardar y Descartar borrador.

Eventos de negocio

Un objeto RAP puede publicar eventos para que otros sistemas reaccionen, por ejemplo una app en BTP que envía un correo cuando se acepta un viaje. El evento se declara en la behavior definition y se lanza durante el guardado.

BDEF
  event viajeAceptado;
ABAP
" En el método save_modified de la clase de guardado (managed with additional save)
RAISE ENTITY EVENT zr_viaje~viajeAceptado
  FROM VALUE #( FOR ls_v IN update-viaje WHERE ( Estado = 'A' )
                ( ViajeId = ls_v-ViajeId ) ).

Para que el evento salga del sistema hay que configurar un event binding y un canal hacia SAP Event Mesh o Advanced Event Mesh.

Fuentes