Skip to main content

Command Palette

Search for a command to run...

Mastering Modularity

PL/SQL Packages, REST Data Sources, and Shared Components

Updated
5 min read
Mastering Modularity

🇪🇸 Leer en Español

Introduction: Modularity — The Secret to Scalable Code

In Oracle APEX development, most projects start fast… and get complicated just as fast. As applications grow, pages multiply, processes duplicate, and every change feels riskier.

We've already covered Best Practices, Security, UX, and Performance. Now it's time to talk about architecture.

That’s where modularity comes in — the art of building Oracle APEX apps as a collection of reusable, independent, and maintainable components.
A modular app reduces errors, speeds up maintenance, and scales naturally with your team.

If you work across multiple Oracle APEX applications or collaborate in teams, mastering modularity can transform how you build, deploy, and evolve your systems.

In this APEX Insights edition, we’ll build a modular architecture from the ground up using three key pillars:

  1. PL/SQL Packages to encapsulate business logic.
  2. REST Data Sources to share data and services between applications.
  3. Oracle APEX Shared Components to ensure visual and functional consistency.

Our example: a centralized authentication and logging module reusable across multiple Oracle APEX apps within the same workspace.


1. Core Concepts: What Modularity Means in Oracle APEX

Before writing a single line of code, let’s define what modularity really means:

  • Separation of responsibilities: each module has a clear purpose (e.g., authentication, notifications, configuration).
  • Reusability: logic and UI components can be used across multiple applications.
  • Maintainability: changes in one module don’t break others.
  • Decoupling: modules interact through interfaces (packages, APIs) — never by tightly coupled dependencies.

These principles are the foundation of sustainable architecture, regardless of project size or complexity.


Before coding, define a clear project structure.
It might seem minor at first, but it will save you countless hours of maintenance later.

Suggested base structure:

/apex-insights/
│
├── db/
│   ├── packages/
│   │   ├── auth_core.pks
│   │   ├── auth_core.pkb
│   │   ├── log_utils.pks
│   │   ├── log_utils.pkb
│   └── install/
│       ├── create_users.sql
│       ├── seed_data.sql
│
├── rest/
│   ├── auth_api/
│   │   ├── get_user_status.sql
│   │   ├── post_login_audit.sql
│   └── system_monitor/
│       ├── get_logs.sql
│
├── apex/
│   ├── shared_components/
│   │   ├── templates/
│   │   ├── lists/
│   │   ├── substitutions/
│   └── apps/
│       ├── core_app/
│       ├── admin_app/
│       └── user_portal/
└── docs/
    └── architecture.md

Pro tips:

  • Use consistent prefixes for your packages (core_, mod_, app_).
  • Keep installation and seed scripts separated.
  • Document inter-module dependencies (ideally in architecture.md).

3. Module 1: PL/SQL Packages — The Heart of the Backend

PL/SQL packages are the foundation of modular Oracle architecture.
They centralize business logic and expose clean, reusable functions.

Packages don’t just group procedures — they protect your logic and prevent duplication across different apps.

Example: Authentication Package

auth_core.pks

CREATE OR REPLACE PACKAGE auth_core AS
  FUNCTION validate_user(p_username VARCHAR2, p_password VARCHAR2) RETURN BOOLEAN;
  PROCEDURE register_login(p_username VARCHAR2);
END auth_core;
/

auth_core.pkb

CREATE OR REPLACE PACKAGE BODY auth_core AS

  FUNCTION validate_user(p_username VARCHAR2, p_password VARCHAR2) RETURN BOOLEAN IS
    v_count NUMBER;
  BEGIN
    SELECT COUNT(*) INTO v_count
    FROM users
    WHERE username = p_username
      AND user_password = STANDARD_HASH(p_password, 'SHA256');
    RETURN v_count = 1;
  END validate_user;

  PROCEDURE register_login(p_username VARCHAR2) IS
  BEGIN
    INSERT INTO login_audit (username, login_time)
    VALUES (p_username, SYSDATE);
  END register_login;

END auth_core;
/

💡 Tip: place your business logic packages in a central schema (CORE_DB or APEX_UTILS) and grant limited execution privileges to each Oracle APEX app (GRANT EXECUTE ON auth_core TO app_user;).


4. Module 2: REST Data Sources — Connecting Applications

When several apps need the same data or services, copying logic is the worst approach.
With REST Data Sources, you can centralize your data exposure without reinventing the wheel.

Example: Logging Service (RESTful)

-- SQL Handler: GET_LOGS
SELECT username, action, log_date
FROM app_logs
WHERE log_date > SYSDATE - NVL(:DAYS, 7)
ORDER BY log_date DESC;

Recommended setup:

  • Endpoint: /ords/core/logs/
  • Methods: GET, POST
  • Authentication: OAuth2 or APEX Session Cookie
  • Caching: enable REST caching for static responses (Cache-Control).

💡 Tip: use APEX_WEB_SERVICE.MAKE_REST_REQUEST to consume REST services between apps in the same workspace, keeping your logic clean and isolated.


5. Module 3: Shared Components — Reusing Visual and Logical Elements

Just like your backend has its modules, your frontend can be modular too.
Shared Components are the secret to maintaining consistent UX across multiple Oracle APEX applications.

Common use cases:

  • Custom templates: buttons, regions, lists, reports.
  • LOVs and substitutions: defined once, reused everywhere.
  • JavaScript or CSS bundles: centralized in one base app and referenced by others.

Example: Unified Session Banner

In your base app (“Core App”), create a simple HTML region:

<div class="session-banner">
  Logged in as: &APP_USER.
</div>

Then use “Copy Shared Components” in other apps to import the same banner and maintain visual consistency across your ecosystem.


6. Integrated Example: Authentication and Logging Module

Imagine you have three applications — User Portal, Admin Dashboard, and Core App:

  1. Core App: contains auth_core and log_utils (backend).
  2. Admin Dashboard: consumes the REST endpoint /ords/core/logs/ to show audit logs.
  3. User Portal: uses auth_core.validate_user for user authentication.
  4. Both apps: import the unified session banner as a shared component.

The result is a modular, connected, and maintainable environment where each piece serves a single purpose and can evolve independently.


7. Benefits of a Modular Architecture

  • Scalability: add new modules without breaking existing ones.
  • Collaboration: teams can work on separate modules safely.
  • Security: clear and limited privileges between schemas.
  • Reusability: avoid duplicating logic or UI components.
  • Simpler debugging: when something fails, you know exactly where to look.

Conclusion: Build Modules, Not Monoliths

Modularity isn’t a luxury — it’s a strategy.
By dividing your Oracle APEX application into packages, REST services, and shared components, you’ll change the way you build, scale, and maintain your solutions.

Start small — with an authentication or logging module — and watch your Oracle Oracle APEX ecosystem grow more structured, faster, and cleaner.


Key References

  1. Oracle APEX REST Data Sources Guide
  2. Oracle Database PL/SQL Packages and Types Reference
  3. Joel Kallman’s Blog – Reusability in APEX Components

🚀 Need an APEX Expert?

I help companies facilitate professional Oracle APEX development and DevOps. If you want to build better applications or automate your pipeline, let's talk.

☕ Schedule a Call|💼 Connect on LinkedIn

💖 Support My Work

If you found this article helpful, consider supporting me!

GitHub Sponsors | Buy Me a Coffee

Your support helps me keep creating open-source demos and content for the Oracle APEX community. 🚀