Cosmic Module

O

Qubits of DPK

March 20, 2026

Core Open Source
These are the foundation modules — every other module depends on them. Think of them as the concrete, steel, and wiring of the building. You never see them, but nothing stands without them.

1. fineract-core

Layman Analogy

This is the hospital's plumbing and electricity. Every department uses electricity. Nobody installs their own generator. fineract-core provides the shared infrastructure every module needs.

What's Inside

a) The Money Class — The Most Important Utility
In banking, you NEVER use Java's double or float for money. Why?
java
QUBITS OF DPK
1// This is WRONG — floating point loses precision
2double a = 0.1 + 0.2;
3System.out.println(a); // prints 0.30000000000000004 — NOT 0.3!
4
5// In banking, that extra 0.000...4 means someone's account is wrong
Fineract uses BigDecimal wrapped in a Money class:
java
QUBITS OF DPK
1// Money always carries: amount + currency together
2Money principal = Money.of(currency, new BigDecimal("100000"));
3Money interest  = Money.of(currency, new BigDecimal("1000"));
4Money total     = principal.plus(interest); // exactly 101000, never 100999.99999
5
6// You can do percentage calculations safely
7Money monthlyInterest = principal.percentageOf(new BigDecimal("1"), mc);
b) Exception Hierarchy
All Fineract exceptions extend from AbstractPlatformException:
javascript
QUBITS OF DPK
1AbstractPlatformException
2├── AbstractPlatformResourceNotFoundException404 Not Found
3├── AbstractPlatformDomainRuleException403 Forbidden (business rule)
4├── PlatformDataIntegrityException400 Bad Request (data issue)
5└── PlatformInternalServerException500 Internal Server Error
Example: trying to get a loan that doesn't exist:
java
QUBITS OF DPK
1public Loan findOneWithNotFoundDetection(Long id) {
2    return loanRepository.findById(id)
3        .orElseThrow(() -> new LoanNotFoundException(id));
4    // LoanNotFoundException extends AbstractPlatformResourceNotFoundException
5    // Spring automatically converts this to HTTP 404
6}
c) CommandProcessingResult — Standard Write Response
Every write operation (create, update, delete) returns this:
java
QUBITS OF DPK
1public class CommandProcessingResult {
2    private final Long commandId;           // ID in audit log
3    private final Long resourceId;          // the entity that was created/changed
4    private final String resourceExternalId; // external ID if applicable
5    private final Map<String, Object> changes; // what fields changed and to what values
6}
d) DateUtils — Date Handling
Banking deals with dates constantly. DateUtils handles:
  • Getting tenant's local date (not server's date)
  • Parsing dates from API requests
  • Comparing dates with business logic
java
QUBITS OF DPK
1LocalDate today = DateUtils.getLocalDateOfTenant(); // tenant's business date
2boolean isOverdue = DateUtils.isBefore(dueDate, today); // date comparison
e) Multi-Tenancy Infrastructure
ThreadLocalContextUtil stores which tenant is active for the current HTTP request:
java
QUBITS OF DPK
1// Set by security filter at start of each request
2ThreadLocalContextUtil.setTenant(tenantObject);
3
4// Read anywhere in the call stack
5FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
6String schema = tenant.getSchemaName(); // e.g., "fineract_bank_kenya"
Key Packages:
javascript
QUBITS OF DPK
1fineract-core/src/main/java/org/apache/fineract/
2├── infrastructure/core/
3│   ├── domain/Money.javaBigDecimal money wrapper
4│   ├── service/DateUtils.javaDate utilities
5│   ├── exception/All base exceptions
6│   └── context/ThreadLocalContextUtilTenant context
7└── commands/
8    └── CommandProcessingResult.javaStandard write response

2. fineract-provider

Layman Analogy

This is the hospital's main building and reception desk. It's where you enter. It connects all departments. It's the address everyone uses.

What's Inside

a) The Entry Point — FineractApplication.java
java
QUBITS OF DPK
1@SpringBootApplication
2public class FineractApplication {
3    public static void main(String[] args) {
4        SpringApplication.run(FineractApplication.class, args);
5        // This single line:
6        // 1. Scans all 30+ modules for Spring beans
7        // 2. Starts embedded Tomcat server on port 8443
8        // 3. Initialises database connections
9        // 4. Runs Liquibase migrations
10        // 5. Registers all scheduler jobs
11        // 6. Server is ready to accept requests
12    }
13}
b) application.properties — Master Configuration
javascript
QUBITS OF DPK
1# Server
2server.port=8443
3server.ssl.enabled=true
4
5# Database (for the tenant registry)
6spring.datasource.url=jdbc:mysql://localhost:3306/fineract_tenants
7
8# Scheduler
9fineract.mode.read-enabled=true
10fineract.mode.write-enabled=true
11fineract.mode.batch-worker-enabled=true
12fineract.mode.batch-manager-enabled=true
13
14# Liquibase
15spring.liquibase.enabled=true
c) Client Management — Lives in Provider
The Client domain (portfolio/client) lives in fineract-provider (not a separate module yet):
javascript
QUBITS OF DPK
1fineract-provider/src/main/java/org/apache/fineract/portfolio/
2├── client/Client entity, ClientWritePlatformService, ClientApiResource
3├── group/Group lending (being moved to fineract-group)
4├── office/Branch/office management
5└── staff/Bank employees (loan officers)
d) Infrastructure — The Technical Backbone
javascript
QUBITS OF DPK
1infrastructure/
2├── security/Spring Security config, filters, JWT
3├── jobs/Quartz scheduler, job registry API
4├── hooks/Webhooks — notify external systems on events
5├── businessdate/Business date API and management
6└── configuration/Global config API (feature flags)
e) Instance Mode — Read/Write/Batch
This is what your PR #5658 tests:
java
QUBITS OF DPK
1@ConfigurationProperties("fineract.mode")
2public class FineractProperties {
3    private boolean readEnabled;    // allow GET requests?
4    private boolean writeEnabled;   // allow POST/PUT/DELETE?
5    private boolean batchWorkerEnabled;  // run batch jobs?
6    private boolean batchManagerEnabled; // schedule batch jobs?
7}

3. fineract-command

Layman Analogy

The ticket routing system in the hospital. When a patient comes in, a ticket is created (Command). The ticket is routed to the right department (CommandRouter). The department processes it (CommandHandler).

What's Inside

The Command Pipeline:
javascript
QUBITS OF DPK
1HTTP Request
234 JsonCommand  (wraps raw JSON body)
567 CommandRouter  (finds the right handler by entity+action)
8910 CommandPipeline  (runs through middleware: audit, validation)
111213 CommandHandler.handle()  (the actual business logic)
141516 CommandProcessingResult  (returns resourceId + changes)
CommandHandler Interface:
java
QUBITS OF DPK
1// Every write operation implements this interface
2public interface CommandHandler {
3    CommandProcessingResult handle(JsonCommand command);
4}
5
6// Annotated so CommandRouter can find the right one:
7@CommandType(entity = "LOAN", action = "REPAYMENT")
8public class LoanRepaymentCommandHandler implements CommandHandler {
9    public CommandProcessingResult handle(JsonCommand command) {
10        // actual repayment logic
11    }
12}
CommandAuditor — Audit Trail:
Every command is recorded in m_portfolio_command_source table:
sql
QUBITS OF DPK
1INSERT INTO m_portfolio_command_source (
2    action_name,          -- "REPAYMENT"
3    entity_name,          -- "LOAN"
4    resource_id,          -- loan ID
5    made_on_date,         -- timestamp
6    api_user_id,          -- who did it
7    command_as_json       -- the full request JSON
8);
This creates a complete audit trail of every change in the system. Regulators can see who did what and when.
DisruptorCommandExecutor — High Performance:
For high throughput scenarios, Fineract uses the LMAX Disruptor (a ring buffer pattern) to process commands asynchronously without locks — much faster than traditional queues.

4. fineract-security

Layman Analogy

The security guard + ID card system of the hospital. Who can enter (authentication). What floors they can access (authorisation). Separate security for each company in the building (multi-tenant).

What's Inside

a) JWT Support — FineractJwtAuthenticationTokenConverter
java
QUBITS OF DPK
1// Converts a JWT token into an authenticated user object
2public class FineractJwtAuthenticationTokenConverter {
3    public Authentication convert(Jwt jwt) {
4        String username = jwt.getSubject();
5        String tenantId = jwt.getClaim("tenantId");
6        // Load user from that tenant's DB
7        // Return authenticated principal
8    }
9}
b) Two-Factor Authentication API
javascript
QUBITS OF DPK
1POST /twofactor          ← Request OTP
2POST /twofactor/validate  ← Submit OTP, get access token
c) User Details API
javascript
QUBITS OF DPK
1GET /userdetails  ← Returns currently logged-in user's info
2                    (used by frontend to show user's name, permissions)
d) Authentication API
javascript
QUBITS OF DPK
1POST /authentication  ← Login endpoint
2                        Body: { username, password }
3                        Returns: { base64EncodedAuthenticationKey, userId, roles }

5. fineract-validation

Layman Analogy

The form checker at the hospital entrance. Before your form goes to any department, someone checks: Is the date filled in correctly? Is the ID number format right? Is the required field empty?

What's Inside

Custom validation annotations for Fineract-specific types:
java
QUBITS OF DPK
1// @LocalDate validates that a string is a valid date in Fineract format
2public class LocalDateValidator implements ConstraintValidator<LocalDate, String> {
3    public boolean isValid(String value, ConstraintValidatorContext context) {
4        try {
5            LocalDate.parse(value, DateTimeFormatter.ofPattern("dd MMMM yyyy"));
6            return true;
7        } catch (DateTimeParseException e) {
8            return false;  // "32 March 2025" would fail here
9        }
10    }
11}
12
13// @EnumValue validates that a string matches an allowed enum value
14public class EnumValueValidator implements ConstraintValidator<EnumValue, String> {
15    public boolean isValid(String value, ConstraintValidatorContext context) {
16        // checks value is one of the allowed enum constants
17    }
18}
19
20// @Locale validates the locale string ("en", "fr", "hi" etc.)
21public class LocaleValidator ...
Used in request DTOs:
java
QUBITS OF DPK
1public class PostClientsRequest {
2    @LocalDate  // validates "01 March 2025" format
3    private String activationDate;
4
5    @Locale     // validates "en", "fr" etc.
6    private String locale;
7}

6. fineract-db

Layman Analogy

The filing room infrastructure — the shelves, cabinets, and labelling system. It doesn't store the files (that's the tenant schemas) but defines HOW things are stored.

What's Inside

  • Liquibase changelog files that define the schema
  • Base database configuration (connection pools, transaction managers)
  • Multi-tenant datasource routing logic
  • Database migration utilities
javascript
QUBITS OF DPK
1fineract-db/src/main/resources/db/changelog/
2├── tenant/
3│   └── parts/
4│       ├── 0001_create_m_client.xml     ← creates m_client table
5│       ├── 0002_create_m_loan.xml       ← creates m_loan table
6│       └── ...hundreds of migration files
7└── tenant-store/
8    └── parts/
9        └── 0001_create_tenants.xml      ← the global tenant registry
Why Liquibase?
Without Liquibase, if a developer adds a new column to m_loan, they'd have to manually run SQL on every database. Liquibase:
  1. #
    Tracks which scripts have run (in DATABASECHANGELOG table)
  2. #
    On startup, runs only the NEW scripts
  3. #
    Runs them on EVERY tenant's schema automatically

Quick Reference Card