/fineract

Apache Fineract

Primary LanguageJavaApache License 2.0Apache-2.0

Apache Fineract: A Platform for Microfinance Build Status Swagger Validation Docker Hub Docker Build

Fineract is a mature platform with open APIs that provides a reliable, robust, and affordable core banking solution for financial institutions offering services to the world’s 2 billion underbanked and unbanked.

Have a look at the FAQ on our Wiki at apache.org if this README does not answer what you are looking for. Visit our JIRA Dashboard to find issues to work on, see what others are working on, or open new issues.

Code Now! (Gitpod) to start contributing to this project in the online web-based IDE GitPod.io right away! (You may initially have to press F1 to Find Command and run "Java: Start Language Server".) It's of course also possible to contribute with a "traditional" local development environment (see below).

Community

If you are interested in contributing to this project, but perhaps don't quite know how and where to get started, please join our developer mailing list, listen into our conversations, chime into threads, and just send us a "Hello!" introduction email; we're a friendly bunch, and look forward to hearing from you.

Requirements

  • Java >= 11 (OpenJDK JVM is tested by our CI on Travis)
  • MySQL 5.7

You can run the required version of the database server in a container, instead of having to install it, like this:

docker run --name mysql-5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mysql -d mysql:5.7

and stop and destroy it like this:

docker rm -f mysql-5.7

Beware that this database container database keeps its state inside the container and not on the host filesystem. It is lost when you destroy (rm) this container. This is typically fine for development. See Caveats: Where to Store Data on the database container documentation re. how to make it persistent instead of ephemeral.

Tomcat v9 is only required if you wish to deploy the Fineract WAR to a separate external servlet container. Note that you do not require to install Tomcat to develop Fineract, or to run it in production if you use the self-contained JAR, which transparently embeds a servlet container using Spring Boot. (Until FINERACT-730, Tomcat 7/8 were also supported, but now Tomcat 9 is required.)

Instructions how to run for local development

Run the following commands:

  1. ./gradlew createDB -PdbName=fineract_tenants
  2. ./gradlew createDB -PdbName=fineract_default
  3. ./gradlew bootRun

Instructions to build the JAR file

  1. Clone the repository or download and extract the archive file to your local directory.
  2. Run ./gradlew clean bootJar to build a modern cloud native fully self contained JAR file which will be created at build/libs directory.
  3. Start it using java -jar build/libs/fineract-provider.jar (does not require external Tomcat)

The tenants database connection details are configured via environment variables (as with Docker container), e.g. like this:

export fineract_tenants_pwd=verysecret
...
java -jar fineract-provider.jar

Instructions to build a WAR file

  1. Clone the repository or download and extract the archive file to your local directory.
  2. Run ./gradlew clean war to build a traditional WAR file which will be created at build/libs directory.
  3. Deploy this WAR to your Tomcat v9 Servlet Container.

We recommend using the JAR instead of the WAR file deployment, because it's much easier.

Note that with the 1.4 release the tenants database pool configuration changed from Tomcat DBCP in XML to an embedded Hikari, configured by environment variables, see above.

Instructions to execute Integration Tests

Note that if this is the first time to access MySQL DB, then you may need to reset your password.

Run the following commands, very similarly to how .travis.yml does:

  1. ./gradlew createDB -PdbName=fineract_tenants
  2. ./gradlew createDB -PdbName=fineract_default
  3. ./gradlew clean test

Instructions to run and debug in Eclipse IDE

It is possible to run Fineract in Eclipse IDE and also to debug Fineract using Eclipse's debugging facilities. To do this, you need to create the Eclipse project files and import the project into an Eclipse workspace:

  1. Import the fineract-provider project into your Eclipse workspace (File->Import->Gradle->Existing Gradle Project into Workspace, choose root directory fineract/fineract-provider)
  2. Do a clean build of the project in Eclipse (Project->Clean...)
  3. Run / debug Fineract by right clicking on org.apache.fineract.ServerApplication class and choosing Run As / Debug As -> Java Application. All normal Eclipse debugging features (breakpoints, watchpoints etc) should work as expected.

You can also use Eclipse Junit support to run tests in Eclipse (Run As->Junit Test)

Finally, modifying source code in Eclipse automatically triggers hot code replace to a running instance, allowing you to immediately test your changes

Instructions to run using Docker and docker-compose

It is possible to do a 'one-touch' installation of Fineract using containers (AKA "Docker"). Fineract now packs the mifos community-app web UI in it's docker deploy. You can now run and test fineract with a GUI directly from the combined docker builds. This includes the database running in a container.

As Prerequisites, you must have docker and docker-compose installed on your machine; see Docker Install and Docker Compose Install.

Alternatively, you can also use Podman (e.g. via dnf install podman-docker), and Podman Compose (e.g. via pip3 install podman-compose) instead of Docker.

Now to run a new Fineract instance you can simply:

  1. git clone https://github.com/apache/fineract.git ; cd fineract
  2. for windows, use git clone https://github.com/apache/fineract.git --config core.autocrlf=input ; cd fineract
  3. docker-compose build
  4. docker-compose up -d
  5. fineract (back-end) is running at https://localhost:8443/fineract-provider/
  6. wait for https://localhost:8443/fineract-provider/actuator/health to return {"status":"UP"}
  7. you must go to https://localhost:8443 and remember to accept the self-signed SSL certificate of the API once in your browser, otherwise you get a message that is rather misleading from the UI.
  8. community-app (UI) is running at http://localhost:9090/?baseApiUrl=https://localhost:8443/fineract-provider&tenantIdentifier=default
  9. login using default username mifos and password password

The docker-compose.yml will build the fineract container from the source based on the Dockerfile. You could change that to use the pre-built container image instead of having to re-build it.

https://hub.docker.com/r/apache/fineract has a pre-built container image of this project, built continuously.

You must specify the MySQL tenants database JDBC URL by passing it to the fineract container via environment variables; please consult the docker-compose.yml for exact details how to specify those. (Note that in previous versions, the mysqlserver environment variable used at docker build time instead of at docker run time did something similar; this has changed in FINERACT-773), and the mysqlserver environment variable is now no longer supported.)

Instructions to run on Kubernetes

General Clusters

You can also run Fineract using containers on a Kubernetes cluster. Make sure you set up and connect to your Kubernetes cluster. You can follow this guide to set up a Kubernetes cluster on GKE. Make sure to replace apache-fineract-cn with apache-fineract

Now e.g. from your Google Cloud shell, run the following commands:

  1. git clone https://github.com/apache/fineract.git ; cd fineract/kubernetes
  2. ./kubectl-startup.sh

To shutdown and reset your Cluster, run:

./kubectl-shutdown.sh

Using Minikube

Alternatively, you can run fineract on a local kubernetes cluster using minikube. As Prerequisites, you must have minikube and kubectl installed on your machine; see Minikube & Kubectl install.

Now to run a new Fineract instance on Minikube you can simply:

  1. git clone https://github.com/apache/fineract.git ; cd fineract/kubernetes

  2. minikube start

  3. ./kubectl-startup.sh

  4. minikube service fineract-server --url --https

  5. Fineract is now running at the printed URL (note HTTP), which you can check e.g. using:

    http --verify=no --timeout 240 --check-status get $(minikube service fineract-server --url --https)/fineract-provider/actuator/health

To check the status of your containers on your local minikube Kubernetes cluster, run:

minikube dashboard

You can check Fineract logs using:

kubectl logs deployment/fineract-server

To shutdown and reset your cluster, run:

./kubectl-shutdown.sh

To shutdown and reset your cluster, run:

minikube ssh

sudo rm -rf /mnt/data/

We have some open issues in JIRA with Kubernetes related enhancement ideas which you are welcome to contribute to.

Instructions to download Gradle wrapper

The file gradle/wrapper/gradle-wrapper.jar binary is checked into this projects Git source repository, but won't exist in your copy of the Fineract codebase if you downloaded a released source archive from apache.org. In that case, you need to download it using the commands below:

wget --no-check-certificate -P gradle/wrapper https://github.com/apache/fineract/raw/develop/gradle/wrapper/gradle-wrapper.jar

(or)

curl --insecure -L https://github.com/apache/fineract/raw/develop/gradle/wrapper/gradle-wrapper.jar > gradle/wrapper/gradle-wrapper.jar

Instructions to run Apache RAT (Release Audit Tool)

  1. Extract the archive file to your local directory.
  2. Run ./gradlew rat. A report will be generated under build/reports/rat/rat-report.txt

Instructions to enable ActiveMQ

Messaging configuration is disabled by default. If you want to enable it and register some message listeners, application needs to be started with the proper Spring profile, ie -Dspring.profiles.active=activeMqEnabled (or one of the other Spring ways to configure it).

Checkstyle and Spotless

This project enforces its code conventions using checkstyle.xml through Checkstyle and fineract-formatting-preferences.xml through Spotless. They are configured to run automatically during the normal Gradle build, and fail if there are any violations detected. You can run the following command to automatically fix spotless violations:

`./gradlew spotlessApply`

Since some checks are present in both Checkstyle and Spotless, the same command can help you fix some of the Checkstyle violations (but not all, other Checkstyle violations need to fixed manually).

You can also check for Spotless violations (only; but normally don't have to, because the regular build full already includes this anyway):

`./gradlew spotlessCheck`

We recommend that you configure your favourite Java IDE to match those conventions. For Eclipse, you can go to Window > Java > Code Style and import our config/fineractdev-formatter.xml under formatter section and config/fineractdev-cleanup.xml under Clean up section. The same fineractdev-formatter.xml configuration file (that can be used in Eclipse IDE) is also used by Spotless to both check for violations and autoformat code on the CLI. You could also use Checkstyle directly in your IDE (but you don't neccesarily have to, it may just be more convenient for you). For Eclipse, use https://checkstyle.org/eclipse-cs/ and load our checkstyle.xml into it, for IntelliJ you can use CheckStyle-IDEA.

Code Coverage Reports

The project uses Jacoco to measure unit tests code coverage, to generate a report run the following command:

`./gradlew clean build jacocoTestReport`

Generated reports can be found in build/code-coverage directory.

Versions

The latest stable release can be viewed on the develop branch: Latest Release on Develop.

The progress of this project can be viewed here: View change log

License

This project is licensed under Apache License Version 2.0. See https://github.com/apache/incubator-fineract/blob/develop/LICENSE.md for reference.

The Connector/J JDBC Driver client library from MariaDB.org, which is licensed under the LGPL, is used in development when running integration tests that use the Flyway library. That JDBC driver is however not included in and distributed with the Fineract product and is not required to use the product. If you are developer and object to using the LGPL licensed Connector/J JDBC driver, simply do not run the integration tests that use the Flyway library. As discussed in LEGAL-462, this project therefore complies with the Apache Software Foundation third-party license policy.

Licensing Guidelines

Include a copy of the Apache License, typically in a file called LICENSE, in your work, and consider also including a NOTICE file that references the License.

To apply the Apache License to specific files in your work, attach the following boilerplate declaration, replacing the fields enclosed by brackets "[]" with your own identifying information. (Don't include the brackets!) Enclose the text in the appropriate comment syntax for the file format. We also recommend that you include a file or class name and description of purpose on the same "printed page" as the copyright notice for easier identification within third-party archives.

Copyright 2021 Muellners Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Apache Fineract Platform API

The API for Fineract is documented in apiLive.htm, and the apiLive.htm can be viewed on Fineract.dev. If you have your own Fineract instance running, you can find this documentation under /fineract-provider/api-docs/apiLive.htm.

The Swagger documentation (work in progress; see FINERACT-733) can be accessed under /fineract-provider/swagger-ui/index.html and live Swagger UI here on Fineract.dev.

Apache Fineract supports client code generation using Swagger Codegen based on the OpenAPI Specification. For more instructions on how to generate the client code, check docs/developers/swagger/client.md.

API clients (Web UIs, Mobile, etc.)

Online Demos

  • fineract.dev always runs the latest version of this code
  • demo.mifos.io A demo account is provided for users to experience the functionality of the Community App. Users can use "mifos" for USERNAME and "password" for PASSWORD (without quotation marks).
  • Swagger-UI Demo video This is a demo video for Swagger-UI documentation, more information here.

Developers

Please see https://cwiki.apache.org/confluence/display/FINERACT/Contributor%27s+Zone for the developers wiki page.

Please refer to https://cwiki.apache.org/confluence/display/FINERACT/Fineract+101 for the first-time contribution to this project.

Please see https://cwiki.apache.org/confluence/display/FINERACT/How-to+articles for technical details to get started.

Please visit our JIRA Dashboard to find issues to work on, see what others are working on, or open new issues.

Video Demonstration

Apache Fineract / Mifos X Demo (November 2016) - https://www.youtube.com/watch?v=h61g9TptMBo

Swagger-UI Documentation

We use Swagger-UI to generate and maintain our API documentation, you can see the demo video here or a live version here. If you interested to know more about Swagger-UI you can check their website.

Governance and Policies

Becoming a Committer documents the process through which you can become a committer in this project.

Github Workflow

Github Workflow

Steps:

  1. Create weekly pull request
  • Create a named branch on the Muellners repo reflecting the new changes made.
  • Create a PR from your fork of the Muellners repo (consider Dev 1, Dev 2, and Dev 3 to be branches on your fork), to be merged with the newly created branch.
  • Ensure there are no conflicts and all checks have passed, then merge the PR into the named branch.
  • Create a new PR for merging the named branch into develop
  • Ensure there are no conflicts and all checks have passed, then merge the named branch into develop.
  1. Do a monthly feature-based pull request
  • Create a branch on the Muellners repo called Fineract-oss-release.
  • Create a new PR for merging a named branch into Fineact-oss-release (done on a selective basis).
  • For each named branch chosen, ensure there are no conflicts and all checks have passed, then merge the named branch into the Fineract-oss-release branch.
  • Do a rebase (monthly), creating a feature based PR from Fineract-oss-release to be submitted to the Apache community.

Error Handling Guidelines

  • When catching exceptions, either rethrow them, or log them. Either way, include the root cause by using catch (SomeException e) and then either throw AnotherException("..details..", e) or LOG.error("...context...", e).
  • Completely empty catch blocks are VERY suspicous! Are you sure that you want to just "swallow" an exception? Really, 100% totally absolutely sure?? ;-) Such "normal exceptions which just happen sometimes but are actually not really errors" are almost always a bad idea, can be a performance issue, and typically are an indication of another problem - e.g. the use of a wrong API which throws an Exception for an expected condition, when really you would want to use another API that instead returns something empty or optional.
  • In tests, you'll typically never catch exceptions, but just propagate them, with @Test void testXYZ() throws SomeException, AnotherException..., so that the test fails if the exception happens. Unless you actually really want to test for the occurence of a problem - in that case, use JUnit's Assert.assertThrows() (but not @Test(expected = SomeException.class)).
  • Never catch NullPointerException & Co.

Logging Guidelines

  • We use SLF4J as our logging API.
  • Never, ever, use System.out and System.err or printStackTrace() anywhere, but always LOG.info() or LOG.error() instead.
  • Use placeholder (LOG.error("Could not... details: {}", something, exception)) and never String concatenation (LOG.error("Could not... details: " + something, exception))
  • Which Log Level is appropriate?
    • LOG.error() should be used to inform an "operator" running Fineract who supervises error logs of an unexpected condition. This includes technical problems with an external "environment" (e.g. can't reach a database), and situations which are likely bugs which need to be fixed in the code. They do NOT include e.g. validation errors for incoming API requests - that is signaled through the API response - and does (should) not be logged as an error. (Note that there is no FATAL level in SLF4J; a "FATAL" event should just be logged as an ERROR.)
    • LOG.warn() should be using sparingly. Make up your mind if it's an error (above) - or not!
    • LOG.info() can be used notably for one-time actions taken during start-up. It should typically NOT be used to print out "regular" application usage information. The default logging configuration always outputs the application INFO logs, and in production under load, there's really no point to constantly spew out lots of information from frequently traversed paths in the code about what's going on. (Metrics are a better way.) LOG.info() can be used freely in tests though.
    • LOG.debug() can be used anywhere in the code to log things that may be useful during investigations of specific problems. They are not shown in the default logging configuration, but can be enabled for troubleshooting. Developers should typically "turn down" most LOG.info() which they used while writing a new feature to "follow along what happens during local testing" to LOG.debug() for production before we merge their PRs.
    • LOG.trace() is not used in Fineract.

Pull Requests

We request that your commit message include a FINERACT JIRA issue, recommended to be put in parenthesis add the end of the first line. Start with an upper case imperative verb (not past form), and a short but concise clear description. (E.g. Add enforced HideUtilityClassConstructor checkstyle (FINERACT-821) or Fix inability to reschedule when interest accrued larger than EMI (FINERACT-1109) etc.).

If your PR is failing to pass our CI build due to a test failure, then:

  1. Understand if the failure is due to your PR or an unrelated unstable test.
  2. If you suspect it is because of a "flaky" test, and not due to a change in your PR, then please do not simply wait for an active maintainer to come and help you, but instead be a proactive contributor to the project - see next steps. Do understand that we may not review PRs that are not green - it is the contributor's (that's you!) responsability to get a proposed PR to pass the build, not primarily the maintainers.
  3. Search for the name of the failed test on https://issues.apache.org/jira/, e.g. for AccountingScenarioIntegrationTest you would find FINERACT-899.
  4. If you happen to read in such bugs that tests were just recently fixed, or ignored, then rebase your PR to pick up that change.
  5. If you find previous comments "proving" that the same test has arbitrarily failed in at least 3 past PRs, then please do yourself raise a small separate new PR proposing to add an @Disabled // TODO FINERACT-123 to the respective unstable test (e.g. #774) with the commit message mentioning said JIRA, as always. (Please do NOT just @Disabled any existing tests mixed in as part of your larger PR.)
  6. If there is no existing JIRA for the test, then first please evaluate whether the failure couldn't be a (perhaps strange) impact of the change you are proposing after all. If it's not, then please raise a new JIRA to document the suspected Flaky Test, and link it to FINERACT-850. This will allow the next person coming along hitting the same test failure to easily find it, and eventually propose to ignore the unstable test.
  7. Then (only) Close and Reopen your PR, which will cause a new build, to see if it passes.
  8. Of course, we very much appreciate you then jumping onto any such bugs and helping us figure out how to fix all ignored tests!

Pull Request Size Limit documents that we cannot accept huge "code dump" Pull Requests, with some related suggestions.

Guideline for new Feature commits involving Refactoring: If you are submitting PR for a new Feature, and it involves refactoring, try to differentiate "new Feature code" with "Refactored" by placing them in different commits. This helps review to review your code faster.

We have an automated Bot which marks pull requests as "stale" after a while, and ultimately automatically closes them.

Merge Strategy

This project's committers typically prefer to bring your Pull Requests in through Rebase and Merge instead of Create a Merge Commit. (If you are unfamiliar with GitHub's UI re. this, note the somewhat hidden little triangle drop-down at the bottom of PR, visible only to committers, not contributors.) This avoids the "merge commits" which we consider to be somewhat "polluting" the projects commits log history view. We understand this doesn't give an easy automatic reference to the original PR (which GitHub automatically adds to the Merge Commit message it generates), but we consider this an only very minor inconvenience; it's typically relatively easy to find the original PR even just from the commit message, and JIRA.

We expect most proposed PRs to typically consist of a single commit. Committers may use Squash and merge to combine your commits at merge time, and if they do so will rewrite your commit message as they see fit.

Neither of these two are hard absolute rules, but mere conventions. Multiple commits in single PR make sense in certain cases (e.g. branch backports).

Dependency Upgrades

This project uses a number of 3rd-party libraries, and this section provides some guidance for their updates. We have set-up Renovate's bot to automatically raise Pull Requests for our review when new dependencies are available FINERACT-962.

Upgrades sometimes require package name changes. Changed code should ideally have test coverage.

Our ClasspathHellDuplicatesCheckRuleTest detects classes that appear in more than 1 JAR. If a version bump in build.gradle causes changes in transitives dependencies, then you may have to add related exclude to our dependencies.gradle. Running ./gradlew dependencies helps to understand what is required.

Releasing

How to Release Apache Fineract documents the process how we make the source code that is available here in this Git repository into a binary release tar.gz available on http://fineract.apache.org.

Before you use Gradle to create a release you need to make sure that you provide the proper GPG parameters. You have to options:

  1. Provide the parameters via ~/gradle/gradle.properties in your home folder:
signing.gnupg.keyName=7890ABCD
signing.gnupg.passphrase=secret

IMPORTANT: Do not set your GPG secrets in one of the project gradle.properties and double check that you are not accidentally committing them to Git.

The release command would look then look like this:

./gradlew -Pfineract.release clean build
  1. Another way to provide these parameters are via project parameters on the command line. A release command would then look like this:
./gradlew -Pfineract.release -Psigning.gnupg.keyName=7890ABCD -Psigning.gnupg.passphrase=secret clean build

NOTE: Let's assume your GPG key ID would be "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD" then you have to use the last 8 characters (i. e. "7890ABCD") for the signing plugin property "signing.gnupg.keyName".

Above tasks will create the following files in folder build/distributions:

  • binary distribution file: apache-fineract-1.4.0-binary.tar.gz
  • ASCII armored signature for binary distribution: apache-fineract-1.4.0-binary.tar.gz.asc
  • SHA512 checksum for binary distribution: apache-fineract-1.4.0-binary.tar.gz.sha512
  • source distribution file: apache-fineract-1.4.0-src.tar.gz
  • ASCII armored signature for source distribution: apache-fineract-1.4.0-src.tar.gz.asc
  • SHA512 checksum for source distribution: apache-fineract-1.4.0-src.tar.gz.sha512

The signatures are automatically verified by the build script. It will throw an exception if the verification fails.

Additionally, you can verify the validity of the release distribution files e. g. with:

gpg --verify build/distributions/apache-fineract-1.4.0-binary.tar.gz.asc

The output should look somewhat like this:

gpg: assuming signed data in 'build/distributions/apache-fineract-1.4.0-binary.tgz'
gpg: Signature made Mi 26 Aug 2020 17:17:45 CEST
gpg:                using RSA key ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD
gpg: Good signature from "Aleksandar Vidakovic (Apache Fineract Release Manager) <aleks@apache.org>" [ultimate]

NOTE: All commands shown above are assuming that the current working directory is the project root folder.

More Information

More details of the project can be found at https://cwiki.apache.org/confluence/display/FINERACT.