iDempiere Architecture Overview
Overview
- What you’ll learn:
- The three-tier architecture of iDempiere: database tier, application server tier, and web client tier
- How OSGi and the Eclipse Equinox container enable modular plugin-based development
- The role of the Application Dictionary in model-driven development and how a request flows from browser to database and back
- Prerequisites: Lesson 1 — What is iDempiere?
- Estimated reading time: 18 minutes
Introduction
Understanding iDempiere’s architecture is essential whether you plan to implement the system for a business, develop plugins to extend its functionality, or simply administer an existing installation. The architectural decisions made by the iDempiere founders — adopting OSGi modularity, the ZK web framework, and preserving the Application Dictionary from its Compiere heritage — define how the system behaves, how it is extended, and how it scales.
In this lesson, we will dissect iDempiere’s architecture layer by layer. By the end, you will have a clear mental model of how all the pieces fit together — from the moment a user clicks a button in their browser to the instant the results appear on screen.
The Three-Tier Architecture
iDempiere follows a classic three-tier architecture pattern, where responsibilities are separated into distinct layers. This separation promotes maintainability, scalability, and the ability to modify one tier without disrupting the others.
Tier 1: The Database
At the foundation of iDempiere sits the relational database, which serves as the persistent data store for all business data, configuration, and metadata. iDempiere supports two database systems:
- PostgreSQL (version 14 or higher) — the primary and most widely used option in the community. PostgreSQL is free, open-source, and provides excellent performance, reliability, and standards compliance.
- Oracle Database (version 12c or higher) — supported for organizations that have existing Oracle infrastructure or licensing. Oracle support has been part of the system since the original Compiere days.
The database stores far more than just transactional data (orders, invoices, payments). It also stores the Application Dictionary — the metadata that defines the application itself. Tables like AD_Window, AD_Tab, AD_Field, AD_Column, and AD_Table describe the structure of every window, tab, and field in the user interface. This means the database is both the data store and the application definition repository.
Key database concepts in iDempiere include:
- AD_Client_ID and AD_Org_ID: Nearly every table includes these columns, enabling multi-tenant data isolation and organizational segmentation at the database level.
- IsActive flag: Records are soft-deleted by setting
IsActive = 'N'rather than being physically removed, preserving audit trails and referential integrity. - Created/Updated timestamps and CreatedBy/UpdatedBy: Every record tracks when it was created and last modified, and by which user, providing a built-in audit trail.
Tier 2: The Application Server
The middle tier is the iDempiere application server, a Java-based process that runs inside the Eclipse Equinox OSGi container. This is where business logic executes: processing documents, running workflows, performing calculations, enforcing validation rules, and coordinating between the database and the user interface.
The application server handles:
- Business logic execution: Model classes (Java POJOs that correspond to database tables) contain the logic for validating, processing, and completing business documents.
- Process scheduling: Background processes and scheduled tasks (such as nightly accounting runs or automated report generation) are managed by the server’s scheduler.
- Session management: User authentication, session tracking, and security context (which client, organization, role, and warehouse the user is operating in) are maintained at this tier.
- Caching: The application server caches Application Dictionary metadata, reference data, and frequently accessed configuration to minimize database queries and improve response times.
Tier 3: The Web Client
The presentation tier is a web-based user interface built on the ZK Framework, an Ajax-based web application framework for Java. Users access iDempiere through a standard web browser — no client-side software installation is required.
The ZK Framework uses a server-centric programming model: UI components are created and managed on the server side in Java, and ZK automatically synchronizes the state between the server and the browser using Ajax calls. This means that iDempiere developers write Java code to define UI behavior, and ZK handles all the HTML, CSS, and JavaScript generation and communication.
Key characteristics of the web client:
- No plugins or applets required: The interface runs in any modern web browser (Chrome, Firefox, Edge, Safari).
- Desktop-like experience: ZK provides rich UI components — trees, grids, tabs, dialogs, drag-and-drop — that feel more like a desktop application than a traditional web page.
- Responsive communication: ZK uses Ajax to send only incremental UI updates rather than reloading entire pages, resulting in a smooth, responsive user experience.
OSGi and the Eclipse Equinox Container
The adoption of OSGi is what fundamentally distinguishes iDempiere from its predecessors (Compiere and ADempiere). Understanding OSGi is crucial for anyone who wants to extend or customize iDempiere.
What is OSGi?
OSGi (Open Services Gateway initiative) is a modularity framework for Java. It defines a system of bundles (modules) that can be independently developed, deployed, started, stopped, updated, and uninstalled — all without restarting the application. Each bundle has explicit declarations of what packages it exports (makes available to other bundles) and what packages it imports (requires from other bundles).
Think of OSGi bundles like apps on a smartphone: each one is self-contained, declares what it needs, and can be installed or removed without affecting the phone’s operating system or other apps.
How iDempiere Uses OSGi
iDempiere runs inside the Eclipse Equinox OSGi container, which is the same OSGi runtime that powers the Eclipse IDE. The iDempiere core is itself composed of multiple OSGi bundles:
- org.adempiere.base — Core business logic, model classes, and utility functions
- org.adempiere.ui.zk — The ZK-based web user interface
- org.adempiere.server — Server processes, schedulers, and background tasks
- org.adempiere.report.jasper — JasperReports integration for formatted reporting
- org.adempiere.install — Installation and setup utilities
When developers create plugins for iDempiere, they create new OSGi bundles that declare dependencies on the core bundles and register extensions through well-defined extension points. The most important extension mechanisms include:
- Model Validators: Plugins can register listeners that fire before or after records are saved, deleted, or documents are processed. This is the primary mechanism for adding custom business logic.
- Callouts: Plugins can register field-level event handlers that execute when a user changes a value in a form field, enabling real-time field calculations and auto-population.
- Process classes: Plugins can add new executable processes that appear in the iDempiere menu or can be attached to toolbar buttons.
- Form classes: Plugins can define custom user interface forms for specialized data entry or display needs.
- Event Handlers: Using OSGi’s event admin service, plugins can subscribe to and react to system events asynchronously.
Why OSGi Matters
The OSGi architecture provides several critical benefits:
- Clean separation: Custom code lives in separate plugin bundles, never mixed into the core source code. This makes upgrades dramatically easier — you update the core and your plugins continue to work (assuming the APIs they depend on haven’t changed).
- Runtime deployment: Plugins can be installed and updated while iDempiere is running. In many cases, you do not need to restart the server to activate a new plugin.
- Dependency management: OSGi enforces explicit dependency declarations, preventing classpath conflicts and ensuring that bundles load in the correct order.
- Isolation: Each bundle has its own classloader, preventing unintended interactions between plugins and reducing the risk that one plugin’s code breaks another.
The Plugin Bundle Structure
A typical iDempiere plugin bundle is structured as follows:
com.example.myplugin/
├── META-INF/
│ └── MANIFEST.MF # OSGi bundle metadata (name, version, dependencies)
├── src/
│ └── com/example/myplugin/
│ ├── Activator.java # Bundle lifecycle management
│ ├── MyModelValidator.java
│ └── MyProcess.java
├── OSGI-INF/
│ └── component.xml # OSGi Declarative Services component definitions
├── plugin.xml # Eclipse extension point registrations
└── build.properties # Build configuration
The MANIFEST.MF file is the most important descriptor. It declares the bundle’s symbolic name, version, the packages it imports, and the packages it exports:
Bundle-SymbolicName: com.example.myplugin
Bundle-Version: 1.0.0
Require-Bundle: org.adempiere.base;bundle-version="12.0.0"
Import-Package: org.compiere.model,
org.compiere.process,
org.compiere.util
The Application Dictionary: Model-Driven Development
The Application Dictionary (AD) is the heart of iDempiere’s configurability. It is a set of metadata tables in the database that describe every aspect of the application’s structure and behavior.
How the Dictionary Works
When a user opens a window in iDempiere, the system does not load a hard-coded Java screen. Instead, it queries the Application Dictionary to determine:
- What tabs the window contains (from
AD_Tab) - What fields each tab displays (from
AD_Field, linked toAD_Column) - What table each tab is bound to (from
AD_Table) - What validation rules apply to each field (from
AD_Val_Rule) - What callouts fire when field values change (from
AD_Column.Callout) - What display logic controls field visibility (from
AD_Field.DisplayLogic) - What default values to populate for new records (from
AD_Column.DefaultValue)
The ZK UI layer reads this metadata and dynamically generates the appropriate user interface components. This is why you can add a new column to a table, define it in the Application Dictionary, and immediately see it in the user interface — without writing any Java or JavaScript code.
Key Dictionary Tables
| Table | Purpose |
|---|---|
AD_Table |
Defines database tables registered in the system |
AD_Column |
Defines columns within tables, including data type, default value, validation, and callout references |
AD_Window |
Defines application windows (the top-level UI container) |
AD_Tab |
Defines tabs within a window, each bound to a table |
AD_Field |
Defines individual fields within a tab, controlling display sequence, read-only logic, and display logic |
AD_Process |
Defines executable processes (reports, batch jobs, actions) |
AD_Menu |
Defines the navigation menu tree |
AD_Reference |
Defines dropdown lists, search lookups, and other reference types |
AD_Val_Rule |
Defines SQL-based validation rules that filter dropdown values dynamically |
AD_Workflow |
Defines document approval workflows and automated processes |
The Power of Model-Driven Development
The Application Dictionary approach means that a significant portion of iDempiere customization can be performed by functional consultants through the application’s own user interface, without writing code. Common dictionary-level customizations include:
- Adding new fields to existing windows
- Creating entirely new windows, tabs, and fields for custom tables
- Defining validation rules that control what values appear in dropdown lists
- Setting up display logic to show or hide fields based on other field values
- Configuring default values using context variables and SQL expressions
- Building document workflows with approval steps and automated actions
Key Layers: Persistence, Model, and UI
Within the application server, iDempiere’s code is organized into three conceptual layers:
Persistence Layer
The persistence layer handles all communication with the database. iDempiere uses its own persistence framework (rather than an external ORM like Hibernate) built around the PO (Persistent Object) base class. Every business entity — orders, invoices, products, business partners — is represented by a Java class that extends PO. These model classes are largely auto-generated from the Application Dictionary, with methods like getC_Order_ID(), setDateOrdered(), and getDocStatus() corresponding directly to database columns.
The PO class provides:
- Automatic SQL generation for SELECT, INSERT, UPDATE, and DELETE operations
- Transparent handling of multi-tenant filtering (AD_Client_ID)
- Before-save and after-save event hooks for business logic
- Change logging for audit trail
- Caching of frequently accessed records
Model / Business Logic Layer
The model layer contains the business logic that operates on persistent objects. For documents (orders, invoices, payments, shipments), this includes the document processing engine that manages the document lifecycle: Draft → In Progress → Completed → Closed (or Voided/Reversed). The model layer enforces business rules — for example, ensuring that an invoice cannot be completed if there is no valid tax configuration, or that inventory cannot go negative if the warehouse is configured to disallow it.
Key classes in the model layer include:
MOrder,MInvoice,MPayment,MInOut— Document model classes with processing logicDocAction— The interface that defines the document processing lifecycleDocand its subclasses — The accounting engine that generates GL journal entries from business documentsMProcess— The process execution framework
UI Layer
The UI layer is built on the ZK Framework and is responsible for rendering the user interface in the browser. Key components include:
- ADWindow: The generic window renderer that reads Application Dictionary metadata and dynamically constructs the UI
- ADForm: The base class for custom forms that need specialized UI beyond what the dictionary can describe
- GridTable / GridField: The data-binding layer that connects UI components to the underlying model objects
- WEditor: Editor components for different field types (text, number, date, lookup, etc.)
How a Request Flows Through iDempiere
To tie everything together, let us trace what happens when a user opens a Sales Order window and saves a new order:
- Browser → ZK Engine: The user clicks “Sales Order” in the menu. The browser sends an Ajax request to the server-side ZK engine.
- ZK Engine → Application Dictionary: The ZK ADWindow component queries the Application Dictionary tables (
AD_Window,AD_Tab,AD_Field) to determine the window structure. - Dictionary → UI Rendering: Based on the dictionary metadata, ZK dynamically creates the appropriate UI components (tabs, fields, buttons, grids) and sends the rendered HTML/JavaScript back to the browser.
- User Enters Data: As the user fills in fields, callouts fire on the server side (via Ajax) to perform real-time calculations — for example, selecting a Business Partner automatically populates the payment terms, price list, and shipping address.
- Save Request: When the user clicks Save, an Ajax request sends the field values to the server.
- Model Validation: The
MOrdermodel class validates the data — checking required fields, verifying referential integrity, running any registered Model Validators from plugins. - Persistence: The
PO.saveEx()method generates the appropriate SQL INSERT or UPDATE statement and executes it against the database within a transaction. - Response: On success, the server updates the UI state and ZK sends an Ajax response to the browser confirming the save, updating status indicators, and refreshing any calculated fields.
This entire round trip typically completes in milliseconds for simple operations, demonstrating the efficiency of the server-centric ZK model combined with iDempiere’s caching layer.
Key Takeaways
- iDempiere uses a three-tier architecture: a relational database (PostgreSQL or Oracle), a Java application server running in an Eclipse Equinox OSGi container, and a ZK-based web client.
- The OSGi framework enables modular plugin development where extensions are self-contained bundles that can be deployed, updated, and removed at runtime without modifying core code.
- The Application Dictionary stores application metadata in the database, enabling model-driven development where windows, fields, and business rules can be configured without writing code.
- The ZK Framework provides a server-centric Ajax web UI that delivers a desktop-like experience through standard web browsers.
- The code is organized into persistence (PO classes), model/business logic (document processing, validation), and UI (ZK components) layers.
- A user request flows from browser to ZK engine, then to the Application Dictionary for metadata, through model validation and business logic, to database persistence, and back.
What’s Next
Now that you understand how iDempiere is structured internally, it is time to get hands-on. In the next lesson, you will install iDempiere on your own machine — either through a traditional installation on Linux or using Docker — and verify that everything is running correctly by logging in for the first time.