Skip to content

KB-212 – Accounting Engine Architecture

Knowledge Base ID: KB-212
Chapter: 15 - CCache & Object Caching Architecture
Project: BLACK ERP
Version: 1.5
Status: Draft
Last Updated: 2026-06-27
Applies To: ADempiere 3.9.4


Purpose

This chapter explains the in-memory caching architecture used throughout ADempiere.

Although the Accounting Engine appears to retrieve accounting metadata directly from the database, the Core framework relies heavily on an object cache implementation named CCache.

Understanding this component is essential for developing high-performance customizations while minimizing unnecessary database access.

Unlike many modern cache frameworks, ADempiere implements a lightweight and centralized caching strategy that is reused consistently across the entire application.


Why Caching Matters

Without object caching, nearly every business transaction would repeatedly query PostgreSQL for metadata.

Typical examples include:

  • Accounting Schemas
  • Clients
  • Organizations
  • Roles
  • Tables
  • Columns
  • Products
  • Taxes
  • Document Types
  • Periods
  • Currency Definitions
  • Accounting Combinations

Caching dramatically reduces the number of SQL statements executed during normal ERP operation.


High-Level Architecture

Conceptually, the Core follows this architecture.

Business Logic

↓

Business Model

↓

CCache

↓

Database

Whenever possible, objects are retrieved directly from memory.

Database access occurs only when the requested object is not already cached.


Internal Design

One of the most important discoveries during the source code review is that CCache is intentionally lightweight.

Rather than implementing a sophisticated caching engine, ADempiere extends the standard Java collection framework.

Conceptually:

HashMap

↓

CCache

↓

CacheInterface

The implementation is based on:

public class CCache<K,V>
    extends HashMap<K,V>
    implements CacheInterface

This design keeps the implementation simple while allowing every Core component to share the same caching behavior.


Cache Registration

Every cache automatically registers itself inside the global cache manager.

Conceptually:

New CCache

↓

CacheMgt.register()

↓

Global Cache Registry

This centralized registration allows ADempiere to manage every cache instance consistently across the application.


Cache Hit

When an object already exists inside memory:

Request

↓

CCache

↓

Hit

↓

Return Object

No SQL statement is executed.

The object is returned immediately.


Cache Miss

If the object is not yet available:

Request

↓

CCache

↓

Database

↓

Instantiate Object

↓

Store in Cache

↓

Return Object

Future requests reuse the cached instance.


Expiration Strategy

Unlike many cache frameworks, ADempiere does not continuously monitor cache expiration.

Instead, expiration is evaluated only when the cache is accessed.

Conceptually:

get()

↓

expire()

↓

Expired ?

↓

YES

↓

reset()

↓

clear()

↓

Continue

This lazy expiration strategy keeps the implementation extremely efficient.

No background cleanup thread is required.


Cache Reset

When a cache expires, ADempiere performs a complete reset.

Conceptually:

Expired

↓

reset()

↓

clear()

↓

Empty Cache

The framework does not remove entries individually.

Instead, the entire cache is cleared and rebuilt progressively as objects are requested again.


Cache Lifetime

Each cache may define its own expiration policy.

Typical configurations include:

0

↓

Never Expire
5

↓

Five Minutes
60

↓

One Hour
120

↓

Two Hours

Different business objects use different expiration periods depending on how frequently their metadata changes.


Cached Objects

Source code inspection confirms that CCache is used extensively throughout ADempiere.

Examples include:

  • MAcctSchema
  • MClient
  • MRole
  • MTable
  • MColumn
  • MProduct
  • MTax
  • MDocType
  • MWorkflow
  • MPeriod
  • MBankAccount
  • MCurrency
  • POInfo
  • Trx
  • Msg

These are only representative examples.

The cache implementation is shared by a very large portion of the Core framework.


Relationship with the Accounting Engine

During document posting, accounting metadata is resolved repeatedly.

Instead of querying PostgreSQL for every operation:

Doc

↓

MAccount

↓

MAcctSchema

↓

CCache

↓

Memory

The Posting Engine therefore minimizes metadata-related database traffic.


Performance Benefits

The caching architecture provides several important advantages.

  • Reduced SQL execution
  • Faster document posting
  • Lower PostgreSQL workload
  • Lower latency
  • Improved scalability
  • Faster metadata access
  • Better UI responsiveness

The simplicity of the implementation contributes to its reliability.


Engineering Considerations

Developers should understand that cached objects may remain in memory after metadata changes.

Whenever metadata is modified programmatically, cache invalidation may become necessary.

Typical scenarios include:

  • Dictionary modifications
  • New accounting schemas
  • New accounting combinations
  • Metadata synchronization
  • System configuration updates

Ignoring cache consistency may produce unexpected application behavior.


BLACK ERP Example

During the Mexican VAT Cash Basis implementation, additional accounting metadata is resolved multiple times while posting allocations.

Conceptually:

Allocation

↓

MXVATCashBasisEngine

↓

Resolve Accounts

↓

CCache

↓

FactLine

Because accounting metadata is already cached, repeated postings avoid unnecessary metadata queries.

This improves posting performance while preserving transactional consistency.


Engineering Principles

The source code demonstrates several important architectural principles.

  • Cache implementation is intentionally lightweight.
  • CCache extends Java HashMap.
  • Every cache is centrally registered.
  • Expiration is evaluated lazily.
  • Cache reset clears the entire cache.
  • Business logic remains completely unaware of caching.
  • Performance optimization is transparent to application code.

Key Takeaways

  • CCache is the standard caching mechanism used throughout ADempiere.
  • The implementation extends Java HashMap.
  • Cache instances are centrally managed.
  • Expiration occurs only during cache access.
  • Expired caches are completely reset.
  • Hundreds of Core operations depend on cached metadata.
  • The Accounting Engine benefits directly from this architecture.

Next Chapter

Chapter 16 explores CacheMgt, the global cache manager responsible for registering, coordinating and administrating every cache instance used throughout the ADempiere Core.


Revision History

Version Date Description
1.5 2026-06-27 Rewritten after source code analysis of CCache.java. Added internal architecture, cache registration, lazy expiration, reset strategy and real implementation details based on ADempiere 3.9.4 source code.