Skip to content

Apache Fineract Plugin JAR Extensibility Guide

Apache Fineract supports extension through plugin JARs - self-contained Spring Boot modules that are loaded at startup alongside the core application. This allows you to add custom endpoints, services, domain logic, or reporting integrations without modifying or forking the upstream codebase.

The plugin mechanism was introduced in FINERACT-1177 and builds on Spring Boot's support for external classpath entries.

Running on Finecko?

Plugin JARs require access to the container runtime and deployment pipeline. If your instance is hosted on Finecko, contact support to discuss custom module support - see Plans.

How Plugin Loading Works

Fineract uses two different loading mechanisms depending on how the application is deployed.

JAR deployment - loader.path

When running Fineract directly as a Spring Boot executable JAR, the Java system property -Dloader.path adds a directory to the classpath before startup. Any JAR files found in that directory are treated as Spring Boot classpath entries and their @Configuration, @Component, and auto-configuration classes are picked up automatically.

bash
java -Dloader.path=libs/ -jar fineract-provider.jar

This starts Fineract and loads all JARs in the libs/ directory (relative to the current working directory) as additional classpath entries. The directory does not need to exist - Fineract will start normally if it is empty or absent.

Docker image - /app/plugins/

The official apache/fineract Docker image is built with Google JIB and includes an explicit extra classpath entry for /app/plugins/* in the JIB container configuration:

groovy
// fineract-provider/build.gradle
container {
    mainClass = 'org.apache.fineract.ServerApplication'
    extraClasspath = ['/app/plugins/*']
    ...
}

This means the container is pre-configured to load any JARs placed in /app/plugins/ at startup - no additional flags or entrypoint changes are needed.

Adding Plugins via Custom Docker Image

The simplest production workflow is to build a thin custom image on top of the official release:

dockerfile
FROM apache/fineract:latest

COPY my-custom-plugin.jar /app/plugins/my-custom-plugin.jar
COPY another-plugin.jar   /app/plugins/another-plugin.jar

Build and run:

bash
docker build -t fineract-custom:latest .

docker run -d \
  --name fineract \
  -p 8443:8443 \
  -e FINERACT_HIKARI_JDBC_URL=jdbc:postgresql://db:5432/fineract_tenants \
  -e FINERACT_HIKARI_USERNAME=postgres \
  -e FINERACT_HIKARI_PASSWORD=yourpassword \
  fineract-custom:latest

No additional environment variables or startup arguments are required. The JARs in /app/plugins/ are on the classpath at launch.

Mounting Plugins at Runtime

If you want to load plugins without rebuilding the image - for example during development or testing - mount the plugin directory as a volume:

yaml
# docker-compose override
services:
  fineract:
    image: apache/fineract:latest
    volumes:
      - ./plugins:/app/plugins:ro

Place your JARs in the local plugins/ directory. Fineract must be restarted for new JARs to take effect - there is no hot-reload.

Plugin Development Requirements

A plugin JAR must be a valid Spring Boot-compatible module. The key requirements:

  • Packaged as a standard JAR (not an executable fat JAR)
  • Any Spring @Configuration classes should be registered via META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports for Spring Boot 3.x, or META-INF/spring.factories for earlier Boot versions
  • Must not conflict with classes already present in the core fineract-provider.jar
  • Dependencies that are already provided by Fineract (Spring, Hibernate, Jackson, etc.) should be scoped as compileOnly / provided in the plugin's build file to avoid classpath conflicts

A minimal Gradle plugin module:

groovy
plugins {
    id 'java'
    id 'org.springframework.boot' apply false
    id 'io.spring.dependency-management'
}

dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-dependencies:3.3.x'
    }
}

dependencies {
    compileOnly 'org.springframework.boot:spring-boot-autoconfigure'
    compileOnly 'org.apache.fineract:fineract-core:1.14.0'
    // your implementation dependencies
}

jar {
    enabled = true
    archiveClassifier = ''
}

WAR Deployment Alternative (Legacy)

Fineract also ships as a WAR file. The WAR format does not natively support loader.path, but JARs can be added by exploding the WAR and placing additional JARs into WEB-INF/lib/. This approach requires manual WAR manipulation and is not recommended for production. The Spring Boot JAR or Docker deployment is the supported path for plugin use.

Intra-Repository Custom Modules

The Fineract repository also includes a custom/ directory structure for building full replacement images that include custom modules at compile time (via the fineract-custom JIB target). This approach produces a single image without a separate plugins/ directory - all modules are part of the classpath from build time. This is a more involved path suited to teams that want to maintain a full fork of the build system, rather than just dropping in JARs.

Known Community Plugins

PluginDescription
fineract-pentahoPentaho reporting integration - replaces the default reporting module with Pentaho Business Analytics

WARNING

Third-party plugins are community projects and are not maintained by the Apache Fineract PMC. Review their compatibility with your Fineract version before deploying.

Verifying a Plugin Loaded

After starting Fineract with a plugin, check the startup logs for Spring component registration. If your plugin defines a @RestController or @Service, it will appear in the Spring application context output:

INFO  o.s.b.w.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8443 (https) with context path '/fineract-provider'
INFO  o.a.f.ServerApplication - Started ServerApplication in X.XXX seconds

To confirm specific beans from your plugin are registered, you can query the Spring Boot actuator endpoint (if enabled):

bash
curl -k https://localhost:8443/fineract-provider/actuator/beans | jq '.contexts[].beans | keys[]' | grep my-plugin

Skip Plugin Management Overhead with Finecko

Managing custom plugin builds, image versioning, and classpath compatibility across Fineract upgrades adds non-trivial operational complexity. Finecko provides a managed platform where custom module support can be handled without maintaining your own image build pipeline.

Learn more about Finecko plans →