DEV Community

Cover image for The anatomy of an APEX 26.1 APEXlang file
Usman Khan
Usman Khan

Posted on

The anatomy of an APEX 26.1 APEXlang file

Introduction
If you have spent any time reviewing traditional APEX export SQL, you know the problem. The application is there, but it is buried inside hundreds of calls to internal APIs. You can version it, search it, and deploy it, but reading it fluently is hard work.

To be fair, this is not the first time APEX has given us something better than one huge SQL export. Older versions of APEX could export an application using the Split into Multiple Files option, and APEX has also had a human-readable YAML export format. Those were useful, especially for review and source control, but the YAML format was read-only, and the split SQL export was fundamentally SQL export syntax.

APEXlang makes that structure easier to work with. It mirrors the APEX Builder mental model in a source format that is intended to be read as APEX metadata: applications contain pages, pages contain regions and components, shared components live together, and SQL, PL/SQL, JavaScript, CSS, and HTML still appear where you would expect them.

In this post, I will walk through the anatomy of an APEXlang .apx file and show how to build a mental model of an app quickly.

The Folder Structure
An APEXlang export is not one giant SQL file. It is exported as a zip file that expands into a folder structure.

For the customers sample app, the tree looks like this:

customers/
|-- application.apx
|-- page-groups.apx
|-- pages/
| -- p00001-dashboard.apx
|
-- p00050-customer.apx
|-- shared-components/
| |-- app-computations.apx
| |-- app-items.apx
| |-- app-processes.apx
| |-- authentications.apx
| |-- authorizations.apx
| |-- breadcrumbs.apx
| |-- build-options.apx
| |-- classic-navigation-bar-entries.apx
| |-- component-settings.apx
| |-- legacy-data-load-definitions.apx
| |-- lists.apx
| |-- lovs.apx
| |-- messages.apx
| |-- plugins/region/APEXLANG-14855697926908483213/{custom-attributes.apx,plugin.apx}
| |-- shortcuts.apx
| |-- static-files.apx
| |-- report-layouts/report-layouts.apx
| |-- report-layouts/CUSTOMER-REPORT.rtf
| |-- static-files/icons/app-icon-32.png
| -- themes/universal-theme/{template-option-groups.apx,theme.apx}
|-- supporting-objects/
| |-- deinstall-script.sql
| |-- install-scripts.apx
| |-- install-scripts/activities.sql
| |-- supporting-objects.apx
| |-- substitutions.apx
| |-- upgrade-scripts.apx
|
-- upgrade-scripts/upgrade-eba-cust-spec-and-body.sql
|-- deployments/default.json
|-- .apex/apexlang.json
`-- workspace-components/app-groups/APEX-184853421316436653.apx
application.apx is the application-level definition. This is where you find the application name, version, authentication, authorization, navigation, theme, globalization, security settings, substitutions, JavaScript, CSS, and other global configuration.

pages contains one file per page. The filenames are practical: p00001-home.apx, p00003-event-details-p3-event-name.apx, p00050-customer.apx, and so on. You can usually tell the page number and purpose before opening the file.

shared-components contains the things you would expect from APEX Builder: LOVs, lists, breadcrumbs, authentications, authorizations, app items, app processes, themes, plugins, messages, build options, static files, and report layouts.

supporting-objects contains installation, upgrade, substitution, and deinstallation metadata. The actual SQL scripts can live under folders such as supporting-objects/install-scripts and supporting-objects/upgrade-scripts.

deployments contains deployment configuration. In the examples, default.json maps the app to an application ID.

.apex contains APEXlang metadata. In the examples, .apex/apexlang.json identifies the APEXlang metadata version.

This structure matters because it lets you navigate an app the same way you think about an app. That idea existed before APEXlang, but APEXlang makes the files easier to read. You can edit, validate, and import them back into APEX.

What Lives in application.apx
Open application.apx first.

It starts with an app block:

app TEAM-CALENDAR (
name: Team Calendar
version: 24.2.1
authentication {
publicUser: APEX_PUBLIC_USER
authenticationScheme: @apex$8947201266001685638
}
navigation {
homeUrl: f?p=&APP_ID.:1:&SESSION.
}
)
That reads much closer to a configuration file than an export script. You can scan it and answer basic questions quickly:

What is this application called?

What authentication scheme does it use?

Is authorization configured globally?

What is the home page?

Which theme is current?

Are there global substitutions?

Is custom CSS or JavaScript included?

You will also see the same APEX ideas you already know: session management, security, globalization, navigation, Progressive Web App settings, and substitutions.

Read application.apx like the App Definition screen in APEX Builder. Do not try to understand every reference yet. Get the global shape first.

How Pages Are Modeled
Page files are where APEXlang becomes especially useful.

A page starts with a page block:

page 1 (
name: Home
alias: HOME
title: &APPLICATION_TITLE. - Home
appearance {
pageTemplate: @/standard
}
)
After that, the file is organized around page components. In the examples, pages contain:

region

item

button

dynamicAction

validation

computation

process

branch

Again, this follows the APEX Builder mental model. To understand a page, scan the top-level component blocks first.

Regions often contain their own nested configuration. A report region may include a source block, layout settings, template choices, columns, actions, conditions, and attributes.

region APEX$1553489748373581675 (
name: Events Calendar
type: calendar
source {
location: localDatabase
type: sqlQuery
sqlQuery:
sql
select e.event_id
, e.event_name
from eba_ca_events e

}
)
That is the key pattern: the declarative APEX component is modeled structurally, and the executable code remains embedded in a fenced block.

For form or dialog pages, I would scan in this order:

Page name, alias, template, and security.

Regions, especially the main form region.

Items and their source/default/session state behavior.

Buttons and button positions.

Processes and branches.

Validations and dynamic actions.

You can usually tell whether a page is display-only, a report, a modal form, or a complex transactional page in a couple of minutes.

Shared Components Become Readable
Shared components are split into focused files. That is one of the biggest readability wins.

For example, shared-components/lovs.apx contains lov blocks. A static LOV contains nested entry blocks. A SQL-based LOV contains a source block with the SQL query.

lov APEX$14836072312031628364 (
name: USERNAME_FORMAT
source {
location: staticValues
}

entry APEX$14836072618328628365 (
    sequence: 1
    display: Email Address
    return: EMAIL
)
Enter fullscreen mode Exit fullscreen mode

)
Lists work the same way. shared-components/lists.apx contains list blocks, and each list contains entry blocks with labels, icons, links, current-page logic, and parent-child relationships.

App processes live in shared-components/app-processes.apx. Authentication schemes live in shared-components/authentications.apx. Plugins live under shared-components/plugins, separated by plugin type and id. Themes live under shared-components/themes.

This is much easier to review than a traditional SQL export because the file boundaries match the APEX Builder navigation, and the file contents are not wrapped in API calls.

Understanding References
APEXlang uses references heavily, and learning the reference style is what makes the files click.

You will see @apex(... references in exported files. These are references to APEX components by generated identifier. For example, an application may point to an authentication scheme or navigation list using an @apex)... value.

You will also see more readable references based on static ids and names:

authentication {
scheme: @oracle-apex-accounts
}
userInterface {
currentTheme: @universal-theme
}
navigationMenu {
list: @navigation-menu
}
That matters because APEX 26.1 adds static ids across APEX components, and APEXlang uses those ids to make references more stable and readable.

You will also see @/... references, especially for templates:

pageTemplate: @/standard
listTemplate: @/side-navigation-menu
buttonTemplate: @/text-with-icon
These are easier to read because the component is referenced by a friendly path-like name.

Page item references still look like APEX page item references. SQL and PL/SQL blocks use bind variables such as :P50_ID, :APP_ID, and :APP_USER. URL targets still use familiar APEX substitution syntax, such as f?p=&APP_ID.:1:&SESSION..

Named component references also appear naturally in places such as authorization checks, build option logic, template references, and links.

Top comments (0)