ABAP Openapi
A source-verified project description is not available yet. Open the detail page or wait for a manual refresh.
Source facts need a manual refresh
The source repository does not currently provide a readable project description. See the README below for project goals and usage guidance.
The source repository does not currently provide a readable project description. See the README below for project goals and usage guidance.
Translations:
ABAP Concurrency APIABAP Concurrency API is's a Java-inspired library for parallel task execution in ABAP using the SPTA Framework.
💡 Note: The name references Java’s concurrency model, but under the hood, tasks run in parallel (not just concurrently) via RFC.
Don't forget to click ⭐ if you like the project!
A set of high-level ABAP utility classes that simplify parallel task execution using SAP’s SPTA Framework, without requiring manual RFC module creation.
Parallel processing in ABAP traditionally follows a tedious pattern:
In practice, only steps 2 and 4 matter - the rest is repetitive plumbing that’s error-prone and hard to maintain.
While SAP’s SPTA Framework eliminates the need for custom RFC modules, its low-level API still forces developers to manage serialization, task lifecycle, and error handling manually - often leading to global variables and fragile code.
The ABAP Concurrency API abstracts all that away. You define what to run (your logic) and what to return (your result), and the framework handles how it runs in parallel - cleanly and safely.
Install the package via abapGit.
To illustrate the core concepts, consider a minimal example:
Compute the squares of the integers from 1 to 10 in parallel.
Each number is processed independently in its own parallel task.
While this example is intentionally simple, it demonstrates the essential workflow of the API-defining a task, executing it in parallel, and collecting results-without domain-specific complexity.
First, define three classes: Context, Task, and Result. These can be implemented as either local or global classes, depending on whether you need to reuse them across programs.
CLASS lcl_context DEFINITION FINAL.
PUBLIC SECTION.
INTERFACES if_serializable_object.
TYPES:
BEGIN OF ty_params,
param TYPE i,
END OF ty_params.
METHODS:
constructor IMPORTING is_params TYPE ty_params,
get RETURNING VALUE(rs_params) TYPE ty_params.
PRIVATE SECTION.
DATA ms_params TYPE ty_params.
ENDCLASS.
CLASS lcl_context IMPLEMENTATION.
METHOD constructor.
ms_params = is_params.
ENDMETHOD.
METHOD get.
rs_params = ms_params.
ENDMETHOD.
ENDCLASS.
CLASS lcl_task DEFINITION INHERITING FROM zcl_capi_abstract_task FINAL.
PUBLIC SECTION.
METHODS:
constructor IMPORTING io_context TYPE REF TO lcl_context,
zif_capi_callable~call REDEFINITION.
PRIVATE SECTION.
DATA mo_context TYPE REF TO lcl_context.
DATA mv_res TYPE i.
ENDCLASS.
CLASS lcl_task IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mo_context = io_context.
ENDMETHOD.
METHOD zif_capi_callable~call.
DATA(ls_params) = mo_context->get( ).
mv_res = ls_params-param ** 2.
ro_result = new lcl_result( iv_param = ls_params-param
iv_result = mv_res ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_result DEFINITION FINAL.
PUBLIC SECTION.
INTERFACES if_serializable_object.
METHODS:
constructor IMPORTING iv_param TYPE i
iv_result TYPE i,
get RETURNING VALUE(rv_result) TYPE string.
PRIVATE SECTION.
DATA mv_param TYPE i.
DATA mv_result TYPE i.
ENDCLASS.
CLASS lcl_result IMPLEMENTATION.
METHOD constructor.
mv_param = iv_param.
mv_result = iv_result.
ENDMETHOD.
METHOD get.
rv_result = |{ mv_param } -> { mv_result }|.
ENDMETHOD.
ENDCLASS.
⚠️ Important: Avoid static attributes All Context, Task, and Result objects are serialized and transferred between dialog work processes.
Static attributes are not serialized - they belong to the class metadata, not to the instance. Any data stored in them will not be transferred to the target process and may lead to inconsistent or incorrect behavior.
Always use instance attributes to hold task-specific state.
With the three core classes defined, let’s walk through a complete usage example.
CONSTANTS lc_server_group TYPE rfcgr VALUE 'parallel_generators'.
DATA lo_result TYPE REF TO lcl_result.
" Create collection of tasks
DATA(lo_tasks) = NEW zcl_capi_collection( ).
DO 10 TIMES.
DATA(lo_context) = NEW lcl_context( VALUE lcl_context=>ty_params( param = sy-index ) ).
DATA(lo_task) = NEW lcl_task( lo_context ).
lo_tasks->zif_capi_collection~add( lo_task ).
ENDDO.
DATA(lo_message_handler) = NEW zcl_capi_message_handler( ).
DATA(lv_max_no_of_tasks) = zcl_capi_thread_pool_executor=>max_no_of_tasks( lc_server_group ).
DATA(lo_executor) = zcl_capi_executors=>new_fixed_thread_pool( iv_server_group = lc_server_group
iv_n_threads = lv_max_no_of_tasks
io_capi_message_handler = lo_message_handler ).
TRY.
DATA(lo_results) = lo_executor->zif_capi_executor_service~invoke_all( lo_tasks ).
IF lo_message_handler->zif_capi_message_handler~has_messages( ) = abap_false.
DATA(lo_results_iterator) = lo_results->get_iterator( ).
WHILE lo_results_iterator->has_next( ).
lo_result ?= lo_results_iterator->next( ).
WRITE: / lo_result->get( ).
ENDWHILE.
ENDIF.
CATCH zcx_capi_tasks_invocation INTO DATA(lo_capi_tasks_invocation).
WRITE lo_capi_tasks_invocation->get_text( ).
ENDTRY.
In the example, we use the static method zcl_capi_executors=>new_fixed_thread_pool, which returns an executor configured to use a fixed number of parallel tasks. This method takes four parameters:
| Parameter name | Optional | Description |
|---|---|---|
| iv_server_group | server group (tcode: RZ12) | |
| iv_max_no_of_tasks | maximum number of parallel tasks | |
| iv_no_resubmission_on_error | flag "true" - don't restart the task in case of an error | |
| io_capi_message_handler | Yes | an object that will contain error messages (if they occurred) |
The lo_executor object exposes a single interface method: zif_capi_executor_service~invoke_all(). This method accepts a collection of tasks and returns a collection of results lo_results, following the design pattern used in Java’s java.util.concurrent package*.
Result of execution:

A complete working example is available in the report ZCONCURRENCY_API_EXAMPLE.
To simplify parallel processing in the HCM module, the ZCAPI_FACADE_HCM package provides a Facade implementation (based on the Facade design pattern).
This facade abstracts away common boilerplate tasks-such as splitting personnel numbers (pernr) into batches, creating task instances, and collecting results-so you can focus on your core business logic.
Let’s consider a simple use case: Retrieve the full names of employees by their personnel numbers.
As with the general API, you’ll need to define three classes: Context, Task, and Result-but now tailored to the HCM facade’s expectations.
CLASS lcl_context DEFINITION INHERITING FROM zcl_capi_facade_hcm_abstr_cntx FINAL.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_params,
begda TYPE d,
endda TYPE d,
END OF ty_params.
METHODS:
constructor IMPORTING is_params TYPE ty_params,
get_params RETURNING VALUE(rs_params) TYPE ty_params.
PRIVATE SECTION.
DATA: ms_params TYPE ty_params.
ENDCLASS.
CLASS lcl_context IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
ms_params = is_params.
ENDMETHOD.
METHOD get_params.
rs_params = ms_params.
ENDMETHOD.
ENDCLASS.
CLASS lcl_task DEFINITION INHERITING FROM zcl_capi_facade_hcm_abstr_task FINAL.
PUBLIC SECTION.
METHODS:
constructor IMPORTING io_context TYPE REF TO zcl_capi_facade_hcm_abstr_cntx,
zif_capi_callable~call REDEFINITION.
PRIVATE SECTION.
DATA ms_params TYPE lcl_context=>ty_params.
ENDCLASS.
CLASS lcl_task IMPLEMENTATION.
METHOD constructor.
DATA lo_context TYPE REF TO lcl_context.
" Set Pernrs numbers to mt_pernrs of Task
super->constructor( io_context ).
" Set Context parameters
lo_context ?= io_context.
ms_params = lo_context->get_params( ).
ENDMETHOD.
METHOD zif_capi_callable~call.
DATA lt_employees TYPE lcl_result=>ty_t_employees.
DATA ls_employees LIKE LINE OF lt_employees.
" Simulates retrieving employee full names by personnel number.
" The `ms_params` attribute (e.g., validity dates) is available here.
" It’s not used in this example, but you can leverage it in your implementation.
LOOP AT mt_pernrs ASSIGNING FIELD-SYMBOL(<ls_pernr>).
ls_employees-pernr = <ls_pernr>-low.
CASE <ls_pernr>-low.
WHEN 00000001.
ls_employees-ename = 'John Doe 1'.
WHEN 00000002.
ls_employees-ename = 'John Doe 2'.
WHEN 00000003.
ls_employees-ename = 'John Doe 3'.
WHEN 00000004.
ls_employees-ename = 'John Doe 4'.
WHEN 00000005.
ls_employees-ename = 'John Doe 5'.
WHEN 00000006.
ls_employees-ename = 'John Doe 6'.
WHEN 00000007.
To keep this page readable, only the first part of the README is shown. Open the original README for the full document.