24 Working with APEXlang#
APEXlang is a practical text representation of your application that works both inside App Builder and with external tools. Its declarative definitions let you move through your development flow with confidence. APEX skills for popular AI coding agents enable rich, new ways of collaborating with AI coding agents for app development.
With App Builder, you create Oracle APEX apps right in your browser. You configure smart data components on your pages by choosing a table, view, or query and adjusting declarative options. Then you add business logic only you could write.
APEXlang gives you another way to work with the same application definition in external tools. You can review, edit, validate, version control, export, and import an application's APEXlang definitions using external tools like SQLcl, the SQL Developer extension for Visual Studio Code, and other development tools.
SQLcl, ORDS, and SQL Developer share a common APEXlang compiler driven by the rules that Page Designer has used for years. This makes external editing feel natural and safe, with strict validation, code completion, and integrated import and export support.
- Why APEXlang Matters
APEXlang lets you decide when to work in the browser with App Builder and when to use external tools. - Using APEXlang with AI Coding Agents
Use APEXlang skills, SQLcl validation, and blueprints to collaborate with AI coding agents. - Exporting APEXlang from App Builder
When you export an application from App Builder, you can choose the APEXlang format. - Importing APEXlang in App Builder
To import an APEXlang application, use the Import wizard. - Reading APEXlang Syntax
APEXlang's clean, modern syntax makes it easy for developers and AI coding assistants to read and write. - Using App Builder and External Tools Together
Export your application to APEXlang to work on it externally and import it to reflect the changes in App Builder. Teams using working copies to isolate a developer's changes for a feature or fix can also embrace external tools. - Editing APEXlang in Visual Studio Code
Using the SQL Developer extension for Visual Studio Code, you can export, validate, import, and edit APEXlang applications with context-sensitive assistance and proactive highlighting of errors. - Using SQLcl with APEXlang
Use the SQLcl command line tool to export, import, and validate APEXlang applications. - APEXlang Inside App Builder
View any page in APEXlang from Page Designer, and efficiently review working copy diffs interactively.
Official source: Working with APEXlang
24.1 Why APEXlang Matters#
APEXlang lets you decide when to work in the browser with App Builder and when to use external tools.
Before APEXlang, external editing of APEX applications was not supported. SQL exports worked well for source control, but application settings were represented as internal API calls and numerical IDs. Readable YAML simplified reviews and diffs, but it was not an editable import format.
APEXlang provides the best of both worlds. You can continue to use App Builder for visual and declarative development, and use external tools when they fit the task. SQLcl can export, import, and validate applications from the command line or in scripts. In Visual Studio Code, the SQL Developer extension can help you export, edit, validate, and import applications while showing validation problems proactively.
Tip:
For more information, see the.APEXlang Language Reference and the APEXlang Atlas interactive learning tool.
Parent topic: Working with APEXlang
Official source: Why APEXlang Matters
24.2 Using APEXlang with AI Coding Agents#
Use APEXlang skills, SQLcl validation, and blueprints to collaborate with AI coding agents.
APEXlang is well-structured and easy to understand, so you can also work
productively with AI coding agents like Claude, Codex, and others. With Oracle's APEXlang
skills from GitHub, you can describe what you need and let an
AI collaborator help review an application, suggest improvements, generate
pages and components, make incremental changes, and find and fix problems
using SQLcl's apex validate command.
This workflow is most useful when you treat validation as part of the editing loop: change the APEXlang files, validate the application, review the results, and import only after the source validates cleanly.
Tip:
To install or update the APEXlang skills, use the skills sync command in SQLcl.
If you work with stakeholders to capture and agree on specifications before starting a project, APEX blueprints help teams refine requirements before costly surprises appear. Starting from a draft functional spec and data model description, an AI coding agent uses Oracle's detailed blueprint generation prompt to produce a structured Markdown plan for pages, navigation, reports, forms, charts, filters, actions, and initial behavior. App Builder imports this blueprint and deterministically generates a scaffolded app from tested APEXlang building blocks, letting stakeholders try real pages and give early feedback. You can revise the specification and regenerate until everyone agrees on the app’s shape. After sign-off, the final scaffold becomes the foundation you and your team evolve to add the details real systems require using a combination of App Builder and conversational development with AI coding agents using APEXlang skills.
Parent topic: Working with APEXlang
Official source: Using APEXlang with AI Coding Agents
24.3 Exporting APEXlang from App Builder#
When you export an application from App Builder, you can choose the APEXlang format.
Creating an Example Application to Study
To see what APEXlang looks like, start with a simple APEX application built by the Create App Wizard. The example application has an Interactive Report page and a modal Form page on the familiar EMP table.
Exporting the Application in APEXlang
To export the app in APEXlang, just choose that format on the Export Application page as shown below.
This downloads an employees.zip file. As shown below, it contains a file for each page and component. The application.apx file has app-level settings. The .apx files contain APEXlang.
Contents of an APEXlang Application Export
The deployments, pages,
shared-components subdirectories organize app components at
the root level of the zip. Notice filenames for pages use both number and alias for
additional clarity, and the compiler enforces the page alias matches the page number
and alias in the file name. Static Application Files are included as-is along with a
list of their names and metadata in static-files.apx.
employees.zip
├── application.apx
├── page-groups.apx
├── deployments
│ └── default.json
├── pages
│ ├── p00000-global-page.apx
│ ├── p00001-home.apx
│ ├── p00002-employees.apx
│ ├── p00003-employee.apx
│ └── p09999-login.apx
├── shared-components
│ ├── static-files
│ │ └── icons
│ │ ├── app-icon-144-rounded.png
│ │ ├── app-icon-192.png
│ │ ├── app-icon-256-rounded.png
│ │ ├── app-icon-32.png
│ │ └── app-icon-512.png
│ ├── themes
│ │ └── universal-theme
│ │ └── theme.apx
│ ├── authentications.apx
│ ├── authorizations.apx
│ ├── breadcrumbs.apx
│ ├── build-options.apx
│ ├── component-settings.apx
│ ├── lists.apx
│ ├── lovs.apx
│ └── static-files.apx
└── .apex
└── apexlang.json
Application IDs and Deployment Settings
In APEXlang, the app id is stored in the defaults.json file in the deployments subdirectory. This lets the downloaded file employees.zip use a descriptive name based on the employees app alias. This separation also gives you the option to personalize each deployment environment with an appropriate set of environment-specific settings.
{
"app" : {
"id" : 104,
"runtime" : {
"debugging" : true
}
}
}
Parent topic: Working with APEXlang
Official source: Exporting APEXlang from App Builder
24.4 Importing APEXlang in App Builder#
To import an APEXlang application, use the Import wizard.
App Builder can import an application in APEXlang format. Just drag or select its zip file on the Import page and continue through the wizard.
The Import wizard confirms the Type is APEXlang and lets you choose the application ID. Just click (Import Application) to proceed. App Builder validates and compiles the APEXlang source. If no errors are raised, the application imports successfully.
App Builder uses a dedicated ORDS endpoint with Builder authentication to compile APEXlang artifacts. So, the first time you import an APEXlang format app in a workspace, you may be prompted to enable your workspace’s parsing schema for ORDS REST services. Just click the REST Enable Schema button and the wizard proceeds to the next step to continue the import.
Parent topic: Working with APEXlang
Official source: Importing APEXlang in App Builder
24.5 Reading APEXlang Syntax#
APEXlang's clean, modern syntax makes it easy for developers and AI coding assistants to read and write.
Studying APEXlang Syntax of a Page
When you open an app folder with APEXlang files in your favorite editor, you can browse, search, and edit them like any project. For example, page 3 is an Employee form page with alias employee. Its filename incorporates both the page number and the alias. Opening p00003‑employee.apx, you see the wizard created a modalDialog page using the drawer template.
page 3 (
name: Employee
alias: EMPLOYEE
title: Employee
appearance {
pageMode: modalDialog
dialogTemplate: @/drawer
templateOptions: [
#DEFAULT#
js-dialog-class-t-Drawer--pullOutEnd
]
}
dialog {
chained: false
}
⋮
)
In the example above, it’s easy to see this page component’s
pageMode property – in the appearance group – has the
value modalDialog. For brevity, you can say
appearance.pageMode is modalDialog.
APEXlang avoids unnecessary delimiters. Every component (e.g. page) contains its properties, grouped by function, as name : value pairs. Properties like name, alias, and title in the identification group can optionally appear with no group as shown below. Required properties must have a value, but files stay concise since any property with its default value can be omitted. Leave optional properties out until you need to assign them a value.
Values don’t require quotes in most cases, and a new line separates properties and array elements. For example, the value of appearance.templateOptions is an array with two entries. In this case, they are CSS class names the template defines with the special #DEFAULT# placeholder for “any default classes” the template specifies.
page 3 (
name: Employee
⋮
appearance {
⋮
templateOptions: [
#DEFAULT#
js-dialog-class-t-Drawer--pullOutEnd
]
}
⋮
)>
Component Identifiers and References
Each component type’s metadata nominates an identifier property. Most of the time, staticId plays this role, but sometimes it’s the name or alias. All components have a mandatory human-readable static ID so APEXlang files never need to reference internal ID numbers. APEX automatically assigns sensible static IDs to any components missing one on import or upgrade.
- an app can have only one page
3 - page
2and3can both have aregionwith identifieremployees - page
3can haveemployeesanddepartmentsregions each with aDEPTNOcolumn - the
departmentsregion on page3cannot have twoDEPTNOcolumns.
A component’s identifier value follows its type, just before the opening parenthesis of its property list. In the example below, 3 is the page component’s identifier, and employee identifies the region.
page 3 (
⋮
region employee (
⋮
)
⋮
)
Component References in APEXlang
Each @-prefixed value is a reference to the identifier property value of another component. Later in p00003‑employee.apx you find the page contains a Form region named Employee identified by employee. Notice its appearance.template property references the blank-with-attributes template.
page 3 (
⋮
region employee (
name: Employee
type: form
source {
location: localDatabase
tableName: EMP
}
layout {
sequence: 10
slot: contentBody
}
appearance {
template: @/blank-with-attributes
templateOptions: #DEFAULT#
}
edit {
enabled: true
allowedOperations: [
add
update
delete
]
}
)
⋮
)
Each page item appears in the page’s .apx file as well. Notice the
hidden, primary key P3_EMPNO item based on the EMPNO
column. It references the employee region as the value of both its
layout.region and source.formRegion properties.
When a pageItem references an employee region on the same
page, it uses @employee.
page 3 (
⋮
pageItem P3_EMPNO (
type: hidden
layout {
sequence: 10
region: @employee
slot: regionBody
}
source {
formRegion: @employee
column: EMPNO
dataType: number
queryOnly: true
primaryKey: true
}
security {
sessionStateProtection: checksumRequiredSessionLevel
}
)
⋮
)
Similarly, when a pageItem references a shared component like an LOV in the same app, it
uses @. Notice the P3_DEPTNO item below is a
selectList referencing the sharedComponent LOV using
@dept-dname.
page 3 (
⋮
pageItem P3_DEPTNO (
type: selectList
label {
label: Deptno
alignment: left
}
lov {
type: sharedComponent
lov: @dept-dname
}
layout {
sequence: 80
region: @employee
slot: regionBody
alignment: left
}
appearance {
template: @/optional-floating
templateOptions: #DEFAULT#
}
source {
formRegion: @employee
column: DEPTNO
dataType: number
}
)
⋮
)
@-prefix rule use an @/-prefix instead. They are the components that are either:
- on the global page, or
- part of the standard Universal Theme.
For example, in a regular page, reference the my-global-page-header region
from the global page using @/my-global-page-header.
When a template comes from the standard Universal Theme set, use references like
@/drawer or @/blank‑with‑attributes or
@/optional‑floating. In contrast, when a theme template is defined
locally within the app, use @my‑slideshow.
Adding Additional Features to Example App in App Builder
- switch the Interactive Report region to be a Content Row
- change it to be based on a SQL query,
- update the page help text with some HTML markup,
- define an inline CSS rule to increase the font size by 20%
- add a Raise Salary action button to run PL/SQL business logic, and
- use JavaScript on the Page Load event to welcome the user back to your app.
The figure below shows your page after these modifications. You could export the modified application again from App Builder to study how these new features look in the .apx files. However, since you haven’t made changes yet in VS Code, you can simply export the app to APEXlang directly in VS Code to reflect the latest App Builder changes in the project files.
SQL, PL/SQL, JavaScript, HTML, and CSS in APEXlang
APEXlang represents multi-line code using fenced code blocks with a language indicator. The following example shows a SQL query in the source of the Employees region.
page 2 (
name: Employees
⋮
region employees (
name: Employees
type: themeTemplateComponent/contentRow
source {
location: localDatabase
type: sqlQuery
sqlQuery:
```sql
select EMPNO,
ENAME,
DNAME
from EMP_DEPT_V
```
}
⋮
)
⋮
)
PL/SQL in the application appears in a block with the plsql language
indicator. In this example, the logic is a single update statement that
returns the adjusted salary into a hidden page item.
page 2 (
name: Employees
⋮
region employees (
name: Employees
⋮
action raise-salary (
position: primaryActions
template: button
label: Raise Salary
layout {
sequence: 10
}
behavior {
type: triggerAction
}
triggerAction increase-salary-by-100 (
name: Increase Salary by 100
action: executeServerSideCode
settings {
plsqlCode:
```plsql
update emp
set sal = nvl(sal,0) + 100
where empno = :EMPNO
returning sal into :P2_NEW_SALARY;
```
itemsToSubmit: EMPNO
itemsToReturn: P2_NEW_SALARY
}
execution {
sequence: 10
}
)
⋮
)
)
⋮
)
Page-load JavaScript runs in the browser, so it has a javascript-browser
language indicator. Any server-side JavaScript would use javascript-mle
instead.
page 2 (
name: Employees
⋮
dynamicAction on-page-load (
name: On Page Load
execution {
sequence: 20
}
when {
event: ready
}
action native-javascript-code (
action: executeJsCode
settings {
jsCode:
```javascript-browser
if ( !sessionStorage.getItem( "p2Welcomed" ) ) {
const username = apex.item( "P2_APP_USER" ).getValue();
apex.message.showPageSuccess( `Welcome back, ${username}!` );
sessionStorage.setItem( "p2Welcomed", "true" );
}
```
}
execution {
sequence: 10
}
)
)
⋮
)
HTML and CSS use the same fenced block pattern with html and
css language indicators.
page 2 (
name: Employees
⋮
css {
inline:
```css
body {
font-size: 1.2rem;
}
```
}
⋮
)
And page help HTML markup looks similar.
page 2 (
name: Employees
⋮
help {
helpText:
```html
<p>
Select an employee to edit it,
or click (Raise Salary) to increase
an employee's salary by 100.
</p>
```
}
⋮
)
Tip:
For more information, see the.APEXlang Language Reference and the APEXlang Atlas interactive learning tool.
Parent topic: Working with APEXlang
Official source: Reading APEXlang Syntax
24.6 Using App Builder and External Tools Together#
Export your application to APEXlang to work on it externally and import it to reflect the changes in App Builder. Teams using working copies to isolate a developer's changes for a feature or fix can also embrace external tools.
Application is the Unit of Export and Import
You can use App Builder as you normally would, but be mindful that the unit of APEXlang export is the application. If you have made changes to your app outside App Builder, importing its APEXlang replaces App Builder’s current version to reflect the latest external changes. Conversely, if you make changes in App Builder, external tools see them when you next export the app to APEXlang.
Using APEXlang for Source Control
Maintaining your app’s development history over time by source controlling its external artifacts in a system like Git continues to be a best practice. APEXlang files work great for this purpose, too.
Resolving Conflicts Using APEXlang
- Exporting the App Builder app version to APEXlang
- Unzipping it into a temporary folder
- Unifying versions, resolving any conflicts, with your favorite diff/merge tool
- Importing the unified APEXlang back into App Builder when appropriate.
The app only imports when it validates cleanly, so if it fails just review the errors, address them, and try again.
Using APEXlang with a Working Copy
If you create a working copy of your main application to isolate work on a feature or fix, you can export the working copy to APEXlang, use external tools to modify it, and import it again. APEX preserves the link between the working copy and its main application. When you are ready to merge your changes, the process works the same as if you had made them entirely in App Builder.
For more information, see Creating a Working Copy to Merge, Refresh, or Compare in Oracle APEX App Builder User’s Guide.
Parent topic: Working with APEXlang
Official source: Using App Builder and External Tools Together
24.7 Editing APEXlang in Visual Studio Code#
Using the SQL Developer extension for Visual Studio Code, you can export, validate, import, and edit APEXlang applications with context-sensitive assistance and proactive highlighting of errors.
Exporting APEXlang with SQL Developer
In VS Code, SQL Developer shows APEX apps in a connection’s APEX folder. As an alternative to exporting from App Builder, choose Export… on an app’s context menu under the connection. Then pick a parent folder for the app’s APEXlang artifacts and click Apply. If necessary, for our example here, SQL Developer creates the employees subdirectory in that parent folder and exports the app in APEXlang format into it.
If you’re curious, the SQL tab in the Export… panel shows the SQLcl command to do this APEXlang app export. The -dir parameter is optional in practice. If omitted, SQLcl exports the app into a folder named after the app alias to the current directory.
apex export -applicationid 104
-dir '/Users/smuench/Downloads'
-exptype APEXLANG
Editing APEXlang in Visual Studio Code
The SQL Developer extension adds APEXlang assistance for .apx files. For example, in the figure below when the cursor is in the value of the appearance.dialogTemplate property of page 3, pressing (Ctrl) + (Space) shows the valid templates available for this page whose pageMode is modalDialog. You can switch the page from a drawer template to a modal dialog one by choosing @/modal-dialog from this list.
Problems Panel Proactively Presents Errors
After changing the page to use the modal-dialog template, templateOptions gets a squiggly underline and the Problems panel shows “Invalid template option value…” This validation error indicates one of the existing values is no longer applicable to a modal dialog.
Importing APEXlang from VS Code into App Builder
After correcting the templateOptions value, optionally removing the square brackets for a one-element array, we’re ready to import the changed application into App Builder. As shown below, just click the “play” button in toolbar in the upper right of the editor. Since importing an APEX app requires a connection to your APEX workspace’s parsing schema, SQL Developer prompts you to choose one if needed.
As always, importing an app overwrites the current version in App Builder so ensure all App Builder changes are already reflected in the APEXlang you’re about to import.
If the app validates successfully, then the import succeeds and a confirmation appears.
Refreshing the application page in the browser, you see the Employee page has changed from a modal drawer to a modal dialog.
Parent topic: Working with APEXlang
Official source: Editing APEXlang in Visual Studio Code
24.8 Using SQLcl with APEXlang#
Use the SQLcl command line tool to export, import, and validate APEXlang applications.
Exporting and Importing APEXlang Apps with SQLcl
You can also export, import, and validate your APEX apps in APEXlang using the SQLcl command line.
To export an app in APEXlang format, connect to your workspace’s parsing schema, use the apex export command, and indicate the application id and export type of apexlang.
SQL> apex export -applicationid 104 -exptype apexlang
To import an APEXlang application with SQLcl, connect to your workspace’s parsing schema, use apex import, and indicate the input to load as a path to a directory or zip file:
SQL> apex import -input /Users/smuench/Downloads/employees
Importing an APEXlang app always validates it first, so any errors or warnings appear as with apex validate below. If no errors are detected, SQLcl proceeds. If the import is successful, you’ll see:
SQL> apex import -input /Users/smuench/Downloads/employees
Importing application ID: 104 into workspace: DIVEINTOAPEX
Import successful.
Validating an APEXlang Application with SQLcl
To validate an APEXlang application in SQLcl without importing it, connect to your workspace’s parsing schema, use apex validate, and indicate the input to verify as a path to a directory or zip file:
SQL> apex validate -input /Users/smuench/Downloads/employees
You’ll see Validation successful, otherwise any errors or warnings appear
in the SQLcl console.
For example, suppose you edit the pageItem P3_EMPNO section of the
p00003‑employee.apx page to introduce three typos as shown below and
save the file:
@employee->@employe(remove the trailinge)number->numbe(remove the trailingr)primaryKey->primaryKe(remove the trailingy)
page 3 (
⋮
pageItem P3_EMPNO (
type: hidden
layout {
sequence: 10
region: @employe <-- 1 --
slot: regionBody
}
source {
formRegion: @employee
column: EMPNO
dataType: numbe <-- 2 --
queryOnly: true
primaryKe: true <-- 3 --
}
security {
sessionStateProtection: checksumRequiredSessionLeve
}
)
⋮
)
The errors display immediately in the VS Code Problems panel, and apex validate shows them as follows in SQLcl:
SQL> apex validate -input /Users/smuench/Downloads/employees
APEXLang Compile Errors:
File: pages/p00003-employee.apx
Line: 123
Column: 12
Type: LOV_NOT_FOUND
Error: Invalid LOV required parameter: source - dataType (string)
Valid parameters are:
-bfile
-blob
-boolean
-clob
-date
-intervalDayToSecond
-intervalYearToMonth
-number
-rowid
-sdoGeometry
-timestamp
-timestampWithLocalTimeZone
-timestampWithTimeZone
-varchar2
File: pages/p00003-employee.apx
Line: 117
Column: 12
Type: REFERENCE_NOT_FOUND
Error: Reference not found: @employe
File: pages/p00003-employee.apx
Line: 125
Column: 12
Type: INVALID_PROPERTY
Error: Invalid property: primaryKe
To collect any errors or warnings for later reference, use the SQLcl spool command to capture the console output into a file.
SQL> spool employees_errors.log
SQL> apex validate -input /Users/smuench/Downloads/employees
APEXLang Compile Errors:
File: pages/p00003-employee.apx
Line: 123
Column: 12
Type: LOV_NOT_FOUND
Error: Invalid LOV required parameter: source - dataType (string)
⋮
SQL> spool off
Metadata-Driven Validation
The APEXlang compiler knows which APEX components are available as well as what properties and child components each one has. It validates property values, nested components, and constraints on when each applies. For example, one type of region component like an interactiveReport has nested column definitions, but a form type region doesn’t. Similarly, a chart type region has a zoomAndScroll property, but a classicReport does not.
Page Designer has always reacted dynamically to show and hide appropriate properties and child components. Now the APEXlang compiler leverages the same details to strictly validate your app components and pages.
This information about APEX's app metadata is called meta-metadata (MMD). Over time, it will grow to reflect new APEX features, so each app stores the current APEX meta-metadata version used to export it. This lets the APEXlang compiler validate app files correctly. It also ensures SQL Developer offers accurate code completion in VS Code.
Your app’s .apex/apexlang.json file records this MMD version. It’s important this version remain unchanged until a future APEX version might export your app with a new value. Do not modify it by hand.
{
"mmdVersion" : "26.1.0+3102"
}
Validating APEXlang Without a Connection
While importing an APEXlang application requires access to your workspace's parsing schema, you can validate an APEXlang application without a connection. For example, if you run SQLcl with the /nolog option to avoid a login, you can still run apex validate to compile your application and report errors and warning, if any. This can be useful to validate an application you have downloaded from an APEX instance without direct SQLNet connectivity, or useful for an AI coding agent to discover its own errors to fix them autonomously.
For example, if you are in the root directory of an APEXlang application you want to validate, you can do the following, using the dot (.) to represent the current directory as the input to validate.
$ sql /nolog
SQL> apex validate -input .
APEXLang Compile Errors:
File: pages/p10020-dashboard.apx
Line: 499
Column: 4
Type: DUPLICATED_COMPONENT
Error: Duplicated component within parent scope. For properties:
identification.buttonName: VIEW_ACTIVITY_BY_USER
File: pages/p10020-dashboard.apx
Line: 526
Column: 4
Type: DUPLICATED_COMPONENT
Error: Duplicated component within parent scope. For properties:
identification.buttonName: VIEW_ACTIVITY_BY_USER
Parent topic: Working with APEXlang
Official source: Using SQLcl with APEXlang
24.9 APEXlang Inside App Builder#
View any page in APEXlang from Page Designer, and efficiently review working copy diffs interactively.
Even if you continue doing all APEX development in App Builder, you still benefit from the readability of APEXlang: it replaces the readable YAML format when reviewing changes.
For example, while working on any page in Page Designer, see an APEXlang view of the page with the new APEXlang View menu option shown below.
This lets you review and search the page’s APEXlang whenever useful.
In addition, when reviewing changes between a working copy and the main application, you now see the diffs between APEXlang artifacts. For example, as shown below, it’s easy to see that the P3_MGR page item changed from a selectList to a textField, losing its related lov in the process.
Parent topic: Working with APEXlang