PackagePackagetypeA library you install and call yourself.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

abap-point-gate

A configuration-driven framework that decouples custom ABAP enhancements from standard SAP objects, activating and sequencing them through a Fiori app instead of code changes.

Custom logic attached to standard SAP objects usually stays hard-coded and scattered across the codebase, which makes it hard to see what runs where. This defines Points as hook locations and attaches an ordered chain of Gate Handlers to each one, activated, deactivated, sequenced and parameterised through a Fiori app rather than by editing code. A failing handler is turned into an error message rather than aborting the host transaction, and dependency injection lets handlers, toggles and configurations be mocked for unit testing. It stops at the gate mechanism itself: the enhancement logic still has to be written as a handler class implementing ZIF_APG_HANDLER.

Facts

Last pushLicenceMIT

Where it sits

Lives in
Provides
ExtensibilityABAPExtensibilitycapabilityLetting a customer change delivered behaviour without modifying it — key-user fields and logic, developer extensions, and the released extension points that make either safe across an upgrade.
Flavors
Requires
abapGitabapGitartifactInstalls the framework into the ABAP system, and is where its ABAP Language Version is set to ABAP for Cloud Development; the README names it under both Prerequisites and Design Goals.

Who is behind it

George DrakosGeorge DrakosPersonMaintains this
In the atlas: maintains 4, contributes to 7
@greltel
maintainer

Before choosing this

Conditions

PracticalFunctional boundary

Anything below SAP S/4HANA 2023 FPS03 (ABAP 7.58), and any system not running the ABAP Cloud development model: those two are the prerequisites the README names, and it states that the framework targets ABAP Cloud exclusively.

What it declares

Every artifact

Type
Package
Origin
Independently maintained

As a package

Where it runs
Inside its host
Distributed through
abapGit

Connections2

README

quoted from greltel/abap-point-gate under MIT, read
greltel/abap-point-gate/README.mdOn GitHub

ABAP Point Gate

✅ Status: Production Ready (v3.0.0)

Open Source Contribution: This project is community-driven and Open Source! 🚀 If you spot a bug or have an idea for a cool enhancement, your contributions are more than welcome. Feel free to open an Issue or submit a Pull Request — see CONTRIBUTING.md.

abaplint Unit Tests Version ABAP Cloud License: MIT ABAP 7.58+ Code Statistics

Table of contents

  1. ABAP Point Gate
  2. Architecture
  3. Prerequisites
  4. License
  5. Contributing
  6. Contributors-Developers
  7. Motivation for Creating the Repository
  8. Key Technical Features
  9. Maintaining the Configuration
  10. Authorization
  11. Usage Examples
  12. Testing Your Handlers
  13. Design Goals-Features
  14. Changelog
  15. Roadmap

ABAP Point Gate

ABAP Point Gate is a configuration-driven framework designed to decouple custom enhancements from standard SAP objects, ensuring a clean and maintainable architecture. By leveraging Dependency Injection and Type-Safe Context management, it enables seamless unit testing and granular, hierarchical control over enhancement execution.

Define Points (hook locations in your code) and attach an ordered chain of Gate Handlers to each of them — activated, deactivated, sequenced, and parameterized through a Fiori app instead of code changes.

Architecture

Consumer code                       ABAP Point Gate                    Configuration
─────────────                       ───────────────                    ─────────────
build ZCL_APG_CONTEXT   ──────▶   ZCL_APG_EXECUTION (facade)
                                        │
                                        ▼
                                  ZCL_APG_FACTORY          ◀────────  ZAPG_POINT
                                        │  evaluates activation        ZAPG_GATE_HANDLE
                                        │  (point level, then gate)    (maintained via
                                        ▼                               Fiori app)
                                  ZCL_APG_INJECTOR
                                        │  resolves instances
                                        ▼
                                  ZIF_APG_HANDLER chain
                                  executed in SEQNO order
  1. The consumer fills a ZCL_APG_CONTEXT with named data references and calls ZCL_APG_EXECUTION=>EXECUTE_GATE for a point ID.
  2. The factory reads the configuration, evaluates the hierarchical activation model (point first, then each gate) and resolves the handler instances.
  3. The handlers run in sequence order. A failing handler is converted into an error message — it never aborts the host transaction or the remaining chain.
ObjectRole
ZIF_APG_HANDLERContract for a gate handler (Strategy)
ZIF_APG_ACTIVATION_TOGGLEContract for a custom activation decision
ZIF_APG_CONTEXT / ZCL_APG_CONTEXTNamed data-reference container shared along the chain
ZIF_APG_EXECUTION / ZCL_APG_EXECUTIONFacade — the only class consumers call
ZCL_APG_FACTORYResolves the active handlers of a point
ZCL_APG_INJECTORDI registry — dynamic instantiation and test-double injection
ZIF_APG_CLOCK / ZCL_APG_SYSTEM_CLOCKSystem date behind an interface — no SY-DATUM anywhere
ZIF_APG_CLASS_INSPECTORRTTI lookups behind an interface, doubled in tests
ZIF_APG_DOMAIN_VALUESDomain fixed values for the value-help custom entities
ZIF_APG_AUTHORIZATION / ZCL_APG_AUTHORIZATIONThe framework's only AUTHORITY-CHECK (object ZAPG_POINT)
ZCX_APG_ERRORT100 exception (message class ZAPG)
ZCM_APG_POINTRAP message class of the configuration business object
ZR_APG_Point / ZR_APG_GateHandle + BDEFRAP managed, draft-enabled configuration BO
ZC_APG_*, ZUI_APG_POINT_V4Projection layer and OData V4 UI service

Prerequisites

  • SAP S/4HANA 2023 FPS03 (ABAP 7.58) or higher, OR SAP BTP ABAP Environment.
  • Set the abapGit repository's ABAP Language Version to ABAP for Cloud Development. The framework targets ABAP Cloud exclusively.
  • The framework itself uses released APIs only. The two sample classes reference the released CDS view I_JournalEntry.
  • Statement Compatibility

License

This project is licensed under the MIT License.

Contributing

Pull requests are welcome. The ABAP source here is serialized by abapGit, so development happens in your own system and not against these files — the workflow, the quality bar and the naming rules are described in CONTRIBUTING.md.

Contributors-Developers

The repository was created by George Drakos.

Motivation for Creating the Repository

ABAP Point Gate provides a standardized "gate" around ABAP exit points/enhancements, so custom logic stays isolated from the SAP core instead of being scattered across standard objects. This helps keep the system clean, maintainable, and upgrade-friendly, while offering a consistent way to implement enhancements that aligns with Clean Core / ABAP Cloud readiness practices and encourages quality through automated checks (e.g. abaplint) and unit testing.

Key Technical Features

  • Hierarchical Activation: Control execution at both Point and Gate levels.
  • Type-Safe Context: Easily pass and retrieve data with built-in type-safe getters — missing or non-convertible values raise a typed ZCX_APG_ERROR instead of failing silently.
  • Handler Parameters: Two configuration parameters per gate (PARAM_1 / PARAM_2) are maintained in the Fiori app and delivered to every handler, enabling parameterized handler variants without new classes.
  • Dependency Injection: Built-in support for mocking handlers, toggles and configurations for Unit Testing. Every dependency on the outside world — the system date, RTTI lookups, domain values, authority checks — sits behind an interface that tests can replace.
  • T100 Error Handling: Every framework error carries a message from message class ZAPG with full diagnostics (failing class, context name, original exception in previous).
  • High Performance: Uses Hashed Tables (O(1)O(1) complexity) for context and configuration lookups; point-level custom toggles are evaluated exactly once per execution; the configuration read is table-buffer friendly.
  • Clean ABAP: Modern syntax, ABAP Doc on every public declaration, robust exception handling.
  • RAP Maintenance App: Managed, draft-enabled Fiori app with optimistic locking, authorization checks, side effects and full input validation.
⚙️ Hierarchical Activation Logic

ABAP Point Gate supports a sophisticated activation model (domain ZAPG_ACTIVE):

StatusMeaning
XGlobally Active
-Inactive
Unknown — treated as inactive
CCustom — a ZIF_APG_ACTIVATION_TOGGLE class decides at runtime
  • Parent-Child Rule: If the Point is inactive (or its custom toggle returns false), none of its assigned Gates will execute, regardless of their individual status.
  • A point-level custom toggle is evaluated exactly once per execution, not once per gate.

Maintaining the Configuration

The Fiori app (service binding ZUI_APG_POINT_V4_O4, OData V4) maintains points and their handler chains with draft handling and optimistic locking. The following rules are enforced on save, as state messages that stay visible while the draft is being edited:

  • The handler class must exist and implement ZIF_APG_HANDLER (messages 001/002/009).
  • An activation class is required when the status is Custom (006), forbidden otherwise (007), and must implement ZIF_APG_ACTIVATION_TOGGLE (001/002).
  • All value helps for statuses, point types, programs, includes and classes are served from domain fixed values or released repository views, so every valid value is selectable with its proper text.

Authorization

The configuration app is protected by authorization object ZAPG_POINT:

FieldMeaning
ZAPG_PIDPoint ID, or * for all points
ACTVT01 create, 02 change, 03 display, 06 delete

Checks happen in three places and nowhere else:

  • Global authorization — decides whether the user may create, change or delete at all.
  • Instance authorization — decides it again per point, so a user can be restricted to a subset of point IDs.
  • DCL roles ZR_APG_POINT, ZC_APG_POINT and ZI_APG_VALUE_HELPS — restrict what is readable.

ZCL_APG_AUTHORIZATION holds the framework's single AUTHORITY-CHECK statement. Everything above it is written against ZIF_APG_AUTHORIZATION, which is what makes the behavior handlers testable without a user master record.

Assign the authorization object to a role in PFCG before handing the app to end users. Without it, nobody can maintain the configuration.

Usage Examples

1. Prepare the Context

Prepare the data environment before triggering a gate.

DATA(context) = NEW zcl_apg_context( ).
context->set_data( name  = `SALES_ORDER`
                   value = REF #( sales_order ) ).
context->set_data( name  = `POSTING_DATE`
                   value = NEW d( cl_abap_context_info=>get_system_date( ) ) ).
context->set_data( name  = `RETRY_COUNT`
                   value = NEW i( 3 ) ).
2. Execute the Gate

Trigger the execution logic. The framework automatically identifies and runs all active handlers.

DATA messages TYPE zcl_apg_execution=>tt_messages.

TRY.
    " The Point ID 'SAMPLE_SAVE_BEFORE' must be configured in table ZAPG_POINT
    zcl_apg_execution=>execute_gate( EXPORTING point_id = 'SAMPLE_SAVE_BEFORE'
                                               context  = context
                                     CHANGING  messages = messages ).
  CATCH zcx_apg_error INTO DATA(configuration_error).
    " Configuration problems (unknown class, broken toggle) - surface them
    " through the host's own error channel, e.g. reported/failed in RAP
    INSERT VALUE #( type    = 'E'
                    message = configuration_error->get_text( ) ) INTO TABLE messages.
ENDTRY.

Handler exceptions are converted into E messages by the framework; only configuration errors raise ZCX_APG_ERROR to the consumer.

The static call above stays supported. Where the consumer itself is unit tested, inject the facade instead:

DATA(execution) = CAST zif_apg_execution( NEW zcl_apg_execution( ) ).
3. Handle Results

Retrieve modified data or typed values without manual casting.

" A. Check for validation messages returned by handlers
IF line_exists( messages[ type = 'E' ] ).
  " Handle errors (e.g. abort save, show log)
ENDIF.

" B. Retrieve potentially modified data
" If a handler modified the data, the updated reference is available again
DATA(changed_order) = context->get_data( `SALES_ORDER` ).

DATA(posting_date) = context->get_date( `POSTING_DATE` ).
DATA(retry_count)  = context->get_integer( `RETRY_COUNT` ).
4. Implement a Handler
CLASS zcl_my_enrichment DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES zif_apg_handler.
ENDCLASS.


CLASS zcl_my_enrichment IMPLEMENTATION.

  METHOD zif_apg_handler~execute.
    " Named data references shared along the handler chain
    DATA(order_ref) = context->get_data( `SALES_ORDER` ).

    " Gate configuration parameters (PARAM_1 / PARAM_2 from the Fiori app)
    IF parameters-param_1 = 'STRICT'.
      " variant-specific behavior without a new handler class
    ENDIF.

    " Findings go into the shared message container
    INSERT VALUE #( type    = 'W'
                    message = 'Order enriched with defaults' ) INTO TABLE messages.
  ENDMETHOD.

ENDCLASS.
5. Implement an Activation Toggle
CLASS zcl_weekday_toggle DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES zif_apg_activation_toggle.

    "! @parameter clock | Injected by tests, defaults to the system clock
    METHODS constructor
      IMPORTING clock TYPE REF TO zif_apg_clock OPTIONAL.

  PRIVATE SECTION.
    "! 1 January 2024 was a Monday - the anchor of the weekday calculation
    CONSTANTS reference_monday TYPE d VALUE '20240101'.

    DATA clock TYPE REF TO zif_apg_clock.
ENDCLASS.


CLASS zcl_weekday_toggle IMPLEMENTATION.

  METHOD constructor.
    me->clock = COND #( WHEN clock IS BOUND
                        THEN clock
                        ELSE NEW zcl_apg_system_clock( ) ).
  ENDMETHOD.

  METHOD zif_apg_activation_toggle~is_active.
    " 0 = Monday. Counted from a known Monday, so no system field is read here
    DATA(weekday) = ( clock->today( ) - reference_monday ) MOD 7.
    result = xsdbool( weekday < 5 ).
  ENDMETHOD.

ENDCLASS.

Assign the class to a point or gate with activation status C in the Fiori app. Because the clock is injected, the toggle can be tested for every day of the week without waiting for one.

Testing Your Handlers

ZCL_APG_INJECTOR doubles as the test seam — no database needed:

" Inject the configuration for a point
zcl_apg_injector=>inject_configurations(
    point_id       = 'SAMPLE_SAVE_BEFORE'
    configurations = VALUE #( ( point_id      = 'SAMPLE_SAVE_BEFORE'
                                point_active  = zcl_apg_factory=>activation_status-active
                                seqno         = '001'
                                handler_class = 'ZCL_MY_ENRICHMENT'
                                gate_active   = zcl_apg_factory=>activation_status-active ) ) ).

" Inject a test double for a class name
zcl_apg_injector=>inject_instance( classname = 'ZCL_MY_ENRICHMENT'
                                   instance  = my_test_double ).

" Always clean up in setup/teardown
zcl_apg_injector=>clear( ).

An injected configuration always wins, even when it is empty on purpose — a test asking for "no gates" never falls back to the database.

Design Goals-Features

  • Install via abapGit.
  • ABAP Cloud / Clean Core compatibility. Passed SCI check variants S4HANA_READINESS_2023 and ABAP_CLOUD_READINESS; ATC variant ABAP_CLOUD_DEVELOPMENT_DEFAULT with zero priority-1/2 findings.
  • 66 ABAP Unit tests across 11 test includes: core classes, the factory database path via CL_OSQL_TEST_ENVIRONMENT, the value-help query classes, the toggle error paths, and the RAP validations via CL_CDS_TEST_ENVIRONMENT. The only untested objects are the two boundary adapters ZCL_APG_AUTHORIZATION and ZCL_APG_SYSTEM_CLOCK, which exist so that everything else can be doubled.
  • abaplint runs in GitHub Actions on every push and pull request; the documented rule exceptions live in abaplint.json, each with a comment saying why it is there.
  • ABAP Doc on every public declaration; all messages are T100-based (message class ZAPG, 000-011) — no hardcoded texts.

Changelog

See CHANGELOG.md for the full history.

[3.0.0] - 2026-09-20

Hardening release: authorization layer (authorization object, DCL roles, RAP global and instance authorization), every external dependency moved behind an injectable interface, %state_area draft messages, typed RAP messages, side effects, and 66 unit tests. Fixes a context bug that silently discarded all stored values. Contains one breaking change — see the changelog.

[2.0.0] - 2026-08-09

Full production-hardening rewrite: ABAP Cloud readiness, T100-based error handling, handler parameters, hardened RAP layer (validations, optimistic locking, domain-based value helps), and complete unit-test coverage. Contains breaking API changes — see the changelog.

[1.0.0] - 2026-01-04

Initial Release.

Roadmap

  • Integrated Logging & Monitoring System (IF_BALI_LOG) for suppressed handler errors.
  • Parallel Processing for independent handlers.
  • Unit tests for the RAP authorization handlers once the typed request declarations are verified on the target release.
  • Additional typed context getters (get_boolean, structures, tables).
  • Rename the service definition to ZSD_APG_Point with a new service binding (breaking change, next major version).
MIT, read

History

Latest

v3.0.0

Features 11, Changed 3, Fixes 4

Notes

Hardening release. The framework keeps its shape; what changed is that every dependency on the outside world now sits behind an interface, the configuration business object has an authorization layer, and everything that is not a boundary adapter is covered by tests.

Added
  • Authorization layer. Authorization object ZAPG_POINT (ZAPG_PID / ACTVT), ZIF_APG_AUTHORIZATION with ZCL_APG_AUTHORIZATION — the single AUTHORITY-CHECK of the framework — and global/instance authorization handlers in the behavior pool.
  • DCL roles ZR_APG_POINT, ZC_APG_POINT and ZI_APG_VALUE_HELPS, so the @AccessControl.authorizationCheck: #CHECK annotations are actually backed by rules.
  • ZIF_APG_CLOCK / ZCL_APG_SYSTEM_CLOCK — system date behind an interface, so time-dependent toggles are testable and no consumer reads the system context directly.
  • ZIF_APG_CLASS_INSPECTOR / ZCL_APG_CLASS_INSPECTOR — RTTI lookups behind an interface, replacing the duplicated class checks in the injector and the behavior pool.
  • ZIF_APG_DOMAIN_VALUES / ZCL_APG_DOMAIN_VALUES — domain fixed values for the value-help custom entities.
  • ZIF_APG_EXECUTION — the facade is now instantiable and injectable; the static ZCL_APG_EXECUTION=>EXECUTE_GATE stays as a thin wrapper.
  • ZCM_APG_POINT — RAP message class, so validation messages are named constants the tests assert on instead of message numbers.
  • ZCL_APG_INJECTOR=>HAS_CONFIGURATIONS and INJECT_CLASS_INSPECTOR.
  • Message ZAPG 011 — "Context value &1 is stored but empty".
  • RAP layer: use etag in the projection, side effects on the activation fields, %state_area state messages in every draft validation, administrative-data facet on the Gate entity, and the five missing value helps exposed in the service definition.
  • 66 ABAP Unit tests across 11 test includes, including RAP validation tests through CL_CDS_TEST_ENVIRONMENT.
Fixed
  • ZCL_APG_CONTEXT=>SET_DATA deleted the entire context. DELETE entries WHERE name = name compared the table component with itself, which is always true, so every stored value was dropped on each call. Replaced with a keyed DELETE TABLE. The existing test passed only because it re-stored the same key.
  • ZCL_APG_FACTORY read the configuration through a join, which bypasses the table buffer. Split into two single-table reads ordered by primary key.
  • An injected but empty configuration is now honoured instead of silently falling back to the database — a test asking for "no gates" no longer reads the persistent tables.
  • ZCL_APG_CONTEXT reported a missing name and an unusable reference with the same message; the second case now has its own.
Changed
  • Breaking: ZCL_APG_EXECUTION is no longer a pure static utility. Existing calls to ZCL_APG_EXECUTION=>EXECUTE_GATE keep working unchanged.
  • The behavior pool no longer performs RTTI lookups or system-context reads of its own; both go through injectable adapters.
  • DDIC: PROGNAME replaced by SYREPID, blank domain fixed value removed.
  1. v2.0.0

    Notes

    Full production-hardening rewrite: ABAP Cloud readiness, T100-based error handling, handler parameters, hardened RAP layer (validations, optimistic locking, domain-based value helps) and unit-test coverage. Contains breaking API changes.

  2. v1.0.0

    Notes

    Initial release.

Extensibility
  1. ZABAP_SAP_ENHANCEMENTSReport listing user-exits, BAdIs and enhancement spots of a program

Details

Sources3
Added by handdiscovered herechecked
github.com/greltel/abap-point-gatetree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
discovered viaAdded by hand
first seen in the atlas
ecosystem and domainabap, operations-and-runtime
abaplint
issues under its own abaplint configuration0
lines3,215
statements1,949
objects66
files56
analysed, main
abaplint version2.120.84
Flavors1
ABAP Cloud
“ABAP Cloud / Clean Core compatibility. Passed SCI check variants S4HANA_READINESS_2023 and ABAP_CLOUD_READINESS; ATC variant `ABAP_CLOUD_DEVELOPMENT_DEFAULT` with zero priority-1/2 findings.” — greltel/abap-point-gate — README, Design Goals-Featureschecked
History in the atlas1
  1. First seen.
For your agent
Ref
artifact:greltel-abap-point-gate
JSON
/artifacts/greltel-abap-point-gate.json
MCP
Connecting an agent