Strongly typed annotations provide a structured way to attach metadata to object‑oriented ABL program elements and access that metadata at runtime. This feature enables developers to describe additional characteristics of classes and class members without embedding those details in executable logic.

Annotations are commonly used by frameworks, tools, and application infrastructure to influence behavior indirectly—for example, to describe services, declare configuration, or mark elements for special handling. With OpenEdge strongly typed annotations, this metadata is validated by the compiler, stored in r‑code, and retrieved programmatically using the object-oriented ABL reflection API.

What are annotations?

Annotations are metadata—data about a program rather than instructions executed by the program itself. An annotation is associated with a specific program element, such as a class, method, or property, and expresses information that can be inspected by other code at runtime.

Unlike comments, annotations are not intended for human readers only. They are designed to be read and interpreted by code, typically through reflection, to support patterns such as:

  • Declarative configuration
  • Framework‑driven behavior
  • Architectural or design‑time constraints
  • Integration with tooling and automation

In object-oriented ABL, strongly typed annotations are defined as a special kind of class and behave like read‑only objects when accessed at runtime.

Strongly typed annotations vs. comments and source-only annotations

Comments are ignored by the compiler and have no effect at runtime. They exist solely to aid human understanding of the source code and cannot be accessed programmatically.

Earlier versions of OpenEdge support source‑only annotations, which use an @ syntax and are validated syntactically by the compiler. However, these annotations are not strongly typed, are not stored in r‑code, cannot be accessed at runtime, and require source parsing or XREF analysis to interpret. As a result, source‑only annotations behave much like structured comments.

Strongly typed annotations, which are enclosed in square brackets ([ ]), address these limitations by introducing compiler‑validated annotation definitions, strongly typed annotation properties, storage of annotation metadata in r‑code, and runtime access through the reflection API. Strongly typed annotations coexist safely with source‑only annotations.

Note: In the Procedure Editor, source‑only annotations (@) and strongly typed annotations (enclosed in square brackets [ ]) are displayed using different colors to help distinguish them visually. Source‑only annotations appear in a lighter purple, while strongly typed annotations appear in a darker purple.

Overview of existing source-only ABL annotations

OpenEdge has long supported source-only annotations, which use an @‑based syntax to associate structured information with ABL source code. These annotations are commonly used to convey metadata for tooling, integration, or documentation purposes.

Source‑only annotations are limited to the ABL source code and must be interpreted by parsing source files or compiler XREF output. Although useful for describing intent or supplying information to external tools, source‑only annotations behave similarly to structured comments and do not participate in the object‑oriented runtime model.

Strongly typed annotations are designed to coexist with these existing annotations. The introduction of strongly typed annotations does not change the syntax or behavior of source‑only annotations, and existing applications that rely on them continue to function without modification.

Scope and limitations

Strongly typed annotations are designed specifically for object‑oriented ABL and are limited to elements that can be accessed through the object-oriented ABL reflection API.

Strongly typed annotations can be applied to classes, interfaces, enums, constructors, methods, property definitions, variables, and events. Strongly typed annotations are not supported on procedures, temp‑tables, ProDataSets, queries, buffers, or data sources.

Annotation metadata is read‑only at runtime. Once compiled, annotation values cannot be modified by application code.

Backward compatibility and mixed usage

Strongly typed annotations are fully backward compatible with existing source‑only annotations. Both forms can be used in the same source file, each following its own syntax and rules. Source‑only annotations continue to use the @ prefix. Strongly typed annotations are enclosed in square brackets ([ ]). Existing code does not need to be modified to adopt strongly typed annotations.

Migration from source‑only annotations to strongly typed annotations is a manual process, allowing developers to adopt the new feature incrementally.

The annotation class type

Strongly typed annotations are defined using a new annotation class type. An annotation class describes the structure of the metadata by declaring a set of strongly typed properties.

All annotation classes implicitly inherit from Progress.Lang.Annotation. This built‑in base class provides a common type that allows the reflection API to handle multiple annotation types uniformly.

Annotation classes cannot explicitly specify inheritance and cannot be instantiated directly.

Just like for classes, interfaces, or enums, only one annotation class may be defined per .cls file.

Annotation classes differ from regular object-oriented ABL classes in several important ways:

  • They can contain properties only.
  • Methods, constructors, and events are not allowed.
  • Properties are always public and read‑only.

These restrictions ensure that annotations remain lightweight, declarative metadata rather than executable logic.

Where and how annotations are applied

Strongly typed annotations are applied by enclosing the annotation usage in square brackets ([]) and should appear on a line by themselves immediately before the declaration they annotate.

The compiler associates an annotation with the next applicable declaration, skipping over comments and other annotations. Multiple annotations may be applied to the same element, provided each annotation type is used only once per element.

Marker annotations and property-based annotations

A marker annotation is an annotation class with no properties. Its presence alone conveys meaning. Marker annotations are commonly used to flag an element for special handling.

Property‑based annotations define one or more strongly typed properties. Property values may be specified when the annotation is applied, or default or INITIAL values may be used. Properties that are not explicitly assigned retain their default or INITIAL values.

Runtime metadata and reflection

Annotation metadata is compiled into r‑code and loaded on demand when accessed through the reflection API. This approach avoids runtime overhead unless annotation data is actually needed.

The reflection API provides methods to:

  • Determine whether a type is an annotation.
  • Retrieve a specific annotation by type.
  • Retrieve all annotations applied to an element.
  • Test for the presence of marker annotations.

Annotation instances returned by reflection behave like read‑only object-oriented ABL objects, allowing property access using standard object‑oriented syntax.

Summary

Strongly typed annotations extend object-oriented ABL with a modern, structured metadata capability that supports cleaner architecture, better tooling integration, and framework‑driven development. By combining compile‑time validation, r‑code storage, and reflection‑based access, strongly typed annotations provide a robust alternative to source‑only annotations while remaining fully backward compatible.

Next, in How to define, apply, and access strongly typed annotations, you learn how to define annotation classes, apply annotations to object-oriented ABL elements, and retrieve annotation data at runtime using the reflection API.